Read when a terminal-tools call returned something surprising — empty stdout despite no error, exit_code is null, output_handle came back expired, "too many jobs" / "session busy" / "too many PTYs", warning was set unexpectedly, semantic_status disagrees with exit_code. Diagnostic recipes only — load on demand. Don't preload; the foundational skill covers the happy path.
npx skills add https://github.com/aden-hive/hive --skill hive.terminal-tools-troubleshooting
Recipes for surprising results. Match the symptom to the section.
stdout despite the command "should have" produced outputPossible causes:
stderr in the envelope (or use merge_stderr=True for jobs).max_output_kb is too small. Check stdout_truncated_bytes > 0. Bump max_output_kb or paginate via output_handle.silent flags, no matches).> /dev/null, redirected via 2>&1).stdbuf -oL (line-buffered) or unbuffer to the command.exit_code: null| Cause | Other field |
|---|---|
| Auto-backgrounded | auto_backgrounded: true, job_id: <X> |
| Hard timeout, process killed | timed_out: true |
| Pre-spawn failure (command not found) | error: ... set, pid: null |
| Still running (in terminal_job_logs) | status: "running" |
output_handle returned expired: true5-minute TTL. Either (a) you waited too long, or (b) the store evicted it under memory pressure (64 MB total cap, LRU eviction). Re-run the command.
To reduce risk: paginate the handle as soon as you receive it, or use terminal_job_* for huge outputs (4 MB ring buffer with offsets — no expiry).
JobLimitExceededTERMINAL_TOOLS_MAX_JOBS (default 32) hit. Either:
terminal_job_logs(wait_until_exit=True))terminal_job_manage(action="list") to see what's running, then signal_term the abandoned onesA terminal_pty_run was issued while another _run is in flight on the same session. PTY sessions are single-threaded conversations. Wait for the prior call to return, or open a second session.
TERMINAL_TOOLS_MAX_PTY (default 8) hit. Close idle sessions (terminal_pty_close). Idle reaping is lazy; force it by opening — no, actually, opening throws when the cap is hit. Just close manually.
warning is set, the command workedInformational only. The pattern matched (e.g. rm -rf literally appears, or git push --force was used). The command ran. The warning is your "did I mean to do that?" prompt — verify the side effect was intended before continuing.
semantic_status: "ok" but exit_code: 1Working as designed. Some commands use exit 1 for legitimate non-error states:
grep / rg exit 1 when no matches foundfind exit 1 when some directories were unreadable (typical on /proc, etc.)diff exit 1 when files differtest / [ exit 1 when condition is falseThe semantic_message field explains. Trust semantic_status, not raw exit_code.
semantic_status: "error" but exit_code: 0Shouldn't happen. If it does, file a bug.
truncated_bytes_dropped > 0 in terminal_job_logsYour since_offset was older than the ring buffer's floor — bytes evicted before you could read them. Either:
merge_stderr=True (single 4 MB ring instead of 4 MB × 2)next_offsetterminal_pty_open succeeds but the first _run times outThe session may not have produced its first prompt sentinel within the 2-second startup window. Try:
terminal_pty_run(sid, read_only=True, timeout_sec=2) to drain whatever's accumulatedterminal_pty_run(sid, command="true")) to force a prompt cycleCould also indicate the bash process died at startup — terminal_pty_run(sid, ...) would then return "session has exited".
shell="/bin/zsh" returned an errorBy design. terminal-tools is bash-only on POSIX. Use shell=True (default /bin/bash) or omit shell= to exec directly.
shell=True is interpreted differently than expectedBash, not zsh, semantics. **/* doesn't recurse without shopt -s globstar; =cmd expansion doesn't work; arrays use arr[idx] not ${arr[idx]} differently than zsh. When in doubt, the foundational skill's "bash, not zsh" section is the canonical statement.
Create new skills, modify and improve existing skills, and measure skill performance. Use when users want to create a skill from scratch, edit, or optimize an existing skill, run evals to test a skill, benchmark skill performance with variance analysis, or optimize a skill's description for better triggering accuracy.
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
Replace with description of the skill and when Claude should use it.
Use when facing 2+ independent tasks that can be worked on without shared state or sequential dependencies
This skill should be used when the user wants to "create a skill", "add a skill to plugin", "write a new skill", "improve skill description", "organize skill content", or needs guidance on skill structure, progressive disclosure, or skill development best practices for Claude Code plugins.
Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities. This skill should be used when the user is looking for functionality that might exist as an installable skill.
Use when creating new skills, editing existing skills, or verifying skills work before deployment
Take aden-hive/hive.terminal-tools-troubleshooting from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.