Skip to content
Back to skills

Terminal Tools Foundations

BSecurity

Required when terminal_* tools are available. Explains foreground execution, outer collect_result handles, promoted job IDs and their retrieval/cancellation, deadlines, output retention, platform shell selection, and structured editing when enabled.

  • 11,061 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 6, 2026
ai-agentspythonrustgoshellbashnodeterraformgit

Works with

  • terminal

Security analysis

B85/100
  • highPerforms destructive filesystem operations
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned September 22, 2026

npx -y skills add adenhq/hive --skill terminal-tools-foundations --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Terminal Tools Foundations?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Terminal Tools Foundations
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/adenhq-terminal-tools-foundations/badge)](https://www.skillsdirectory.com/skills/adenhq-terminal-tools-foundations)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: hive.terminal-tools-foundations
description: Required when terminal_* tools are available. Explains foreground execution, outer collect_result handles, promoted job IDs and their retrieval/cancellation, deadlines, output retention, platform shell selection, and structured editing when enabled.
metadata:
  author: hive
  type: preset-skill
  version: "1.0"
---

# terminal-tools — foundations

These tools provide command execution, background jobs, log streaming, filesystem search, and optional PTY sessions. POSIX uses bash for shell commands; Windows selects Git Bash, PowerShell, then cmd. Inspect `shell_kind` in results.

## Tool preference (read first)

Use `search_tools(query="inventory")` before describing capabilities. It reports this session's loaded, searchable, disabled, and configured-but-unavailable tools. Load searchable tools by exact name. An absent schema alone does not prove a capability is missing; configuration does not prove credentials or connectivity work. Terminal tools and coding file tools default to the injected session workdir; an explicit absolute path overrides it.

- **Reading files** → use `read_file` before `edit_file` when the coding tools are enabled; it records file state for the stale-edit guard. Otherwise use a command appropriate to `shell_kind`.
- **Editing files** → prefer `edit_file` when enabled. Replacement mode requires a unique match unless `replace_all=true`; patch mode validates all operations before writing. Inspect its changed-file summary and diff. Re-read files after external changes. Terminal editing remains available when coding tools are disabled.
- **Writing files** → heredoc: `terminal_exec("cat > PATH <<'EOF' ... EOF")`
- **Searching** → `terminal_rg` (content / regex grep) and `terminal_glob` (find files by name)
- **Browser / web pages** → call `browser_setup`, read the browser skill, then run `hive-browser <command> --json` through `terminal_exec`.
- **Web search** → check the inventory for `web_search` and load it if available; verify required credentials. Do not invent a callable tool name.
- **System operations** (process exec, jobs, PTYs) → terminal-tools. This is its territory.

## The standard envelope

Every spawn-style call (`terminal_exec`, the auto-promoted job state) returns this shape:

```jsonc
{
  "exit_code": 0,                    // null when auto-backgrounded or pre-spawn error
  "stdout": "...",                   // decoded, truncated to max_output_kb (default 256 KB)
  "stderr": "...",
  "stdout_truncated_bytes": 0,       // > 0 means more is in output_handle
  "stderr_truncated_bytes": 0,
  "runtime_ms": 42,
  "pid": 12345,
  "output_handle": null,             // "out_<hex>" when truncated — paginate with terminal_output_get
  "timed_out": false,
  "semantic_status": "ok",           // "ok" | "signal" | "error" — read THIS, not just exit_code
  "semantic_message": null,          // e.g. "No matches found" for grep exit 1
  "warning": null,                   // e.g. "may force-remove files" for rm -rf
  "auto_backgrounded": false,
  "job_id": null,                    // set when auto_backgrounded=true
  "shell_kind": "bash"               // interpreter that ran it: "bash" | "powershell" | "cmd" | "direct"
}
```

## Auto-promotion (the core mental model)

The agent loop first waits up to five seconds for `terminal_exec`. A slower call returns a `bg_*` handle; redeem it with `collect_result`. The terminal's own **promotion threshold** defaults to 30 seconds. Past that threshold it transfers the process to its job manager and returns:

```jsonc
{ "auto_backgrounded": true, "exit_code": null, "job_id": "job_<hex>", ... }
```

When you see `auto_backgrounded: true`, **pivot to polling**. The job is still running:

```
terminal_job_logs(job_id, since_offset=0, wait_until_exit=true, wait_timeout_sec=30)
  → blocks server-side until the job exits or the timeout, returns logs + status
```

You're not failing — you're freed up to do other work while the long task runs.

`collect_result` does not redeem `job_id`: after collecting a promoted call, use `terminal_job_logs` until status is `exited`. Track separate stdout/stderr offsets; use `terminal_job_manage(action="signal_term", job_id=...)` to cancel. Poll waits are capped at 45 seconds and do not extend execution deadlines. Job retrieval/management ship with basic exec; explicit job creation and PTYs require the advanced category.

`timeout_sec` defaults to 60 seconds **from command start**, including time after promotion. Expiry terminates the owned process tree; final logs report `timed_out=true`. A deadline at or before promotion kills inline. Set `timeout_sec=0` for unlimited execution with promotion enabled. To keep execution foreground, set `auto_background_after_sec=0` and a finite timeout of at most 220 seconds (or less if the caller has a smaller budget). Use managed jobs for longer waits. Jobs belong to the terminal server and do not survive its restart.

## Semantic exit codes — read `semantic_status`, not raw `exit_code`

Several common commands use exit 1 for legitimate non-error states:

| Command | exit 0 | exit 1 |
|---|---|---|
| `grep` / `rg` | matches found | **no matches** (not an error) |
| `find` | success | **some dirs unreadable** (informational) |
| `diff` | identical | **files differ** (informational) |
| `test` / `[` | true | **false** (informational) |

For these, `semantic_status` will be `"ok"` even when `exit_code == 1`, with `semantic_message` describing why ("No matches found"). For everything else, `semantic_status` defaults to `"ok"` on 0 and `"error"` on nonzero.

**Rule**: always check `semantic_status` first. Only fall back to `exit_code` when you need the exact number (e.g. distinguishing `make` errors).

## Destructive warnings — re-read your command

The envelope's `warning` field is set when the command matches a known destructive pattern (`rm -rf`, `git push --force`, `git reset --hard`, `DROP TABLE`, `kubectl delete`, `terraform destroy`, etc.). The command **still ran** — the warning is informational. Use it as a "did I mean to do that?" prompt before trusting subsequent steps that depend on the side effect.

If a `warning` appears unexpectedly, stop and verify: was the destructive action intended, or did a path/glob slip in?

## Output handles and retention

When `stdout_truncated_bytes > 0` or `stderr_truncated_bytes > 0`, retained output exceeded the inline cap (default 256 KiB per stream). An `output_handle` retrieves the retained bytes for **5 minutes**, subject to earlier eviction. Paginate with:

```
terminal_output_get(output_handle, since_offset=0, max_kb=64)
  → { data, offset, next_offset, eof, expired }
```

Track `next_offset` across calls. If `expired: true`, inspect saved log files first. Repeat a command only if replaying its side effects is appropriate.

The store has a 64 MiB cap with LRU eviction. Process output passes through a 4 MiB ring per stream; old bytes can be overwritten. Poll job logs promptly and check `truncated_bytes_dropped`. For complete build logs, redirect output to a file and inspect that file as well as the exit status.

## Bash, not zsh — even on macOS

On POSIX, `terminal_exec` uses direct argv execution for simple commands and `/bin/bash` for shell syntax or `shell=True`. The user's `$SHELL` does not select the interpreter. zsh is refused by the shell resolver. PTY sessions are POSIX-only.

Foreground commands and explicit background jobs inherit ordinary environment variables, with `ZDOTDIR` and `ZSH_*` removed from the inherited base even when `env` is omitted. Explicit `env` values are then merged and take precedence; framework-injected identity wins over an agent-supplied identity. Noninteractive shell configuration may differ from the user's interactive terminal.

## Windows — check `shell_kind` before assuming bash

On Windows the shell is resolved in priority order: **Git Bash → PowerShell → cmd**. Which one ran your command is reported in the envelope's `shell_kind` field. Bash is only available if Git for Windows is installed; otherwise you land in PowerShell (or cmd as the floor). **Read `shell_kind` and adapt** — bash idioms silently break in the others:

| You wrote | `bash` | `powershell` | `cmd` |
|---|---|---|---|
| `cat` / `ls` | ✓ | ✓ (aliases) | ✗ (`type` / `dir`) |
| `grep` / `sed` / GNU `find` | ✓ | ✗ | ✗ |
| `a && b` | ✓ | ✗ in PS 5.1 (use `;`) | ✓ |
| `2>/dev/null` | ✓ | `2>$null` | `2>nul` |
| single-quoted `'args'` | ✓ | ✓ | ✗ (use `"..."`) |

Practical rule: if `shell_kind != "bash"`, prefer commands that are portable (a bare program name + args, e.g. `node x.js`, `python -m pip install ...`) or write the PowerShell/cmd-native form. Don't assume coreutils. PTY sessions (`terminal_pty_*`) are POSIX-only and return an "unsupported on Windows" error.

**Paths under `shell_kind: "bash"` on Windows (Git Bash):** backslashes are escape characters, so a Windows path passed verbatim gets mangled (`cat C:\Users\me\x` → bash reads `C:Usersmex`). Use forward slashes (`C:/Users/me/x`, which Git Bash accepts) or the MSYS form (`/c/Users/me/x`). Quoting a backslash path in single quotes also preserves it (`cat 'C:\Users\me\x'`).

## Pipelines and complex commands

Pipes (`|`), redirects (`>`, `<`, `>>`), conditionals (`&&`, `||`, `;`), and globs (`*`, `?`, `[`) are detected automatically. You can pass them with the default `shell=False` and the runtime will transparently route through `/bin/bash -c` and surface `auto_shell: true` in the envelope:

```
terminal_exec("ps aux | sort -k3 -rn | head -40")
  → { exit_code: 0, stdout: "...", auto_shell: true, ... }
```

For simple argv commands (no metacharacters) `shell=False` is faster and direct-execs the binary. For commands with shell features but no metacharacters that the detector catches (rare — exotic bash builtins, here-strings), pass `shell=True` explicitly:

```
terminal_exec("set -e; complicated bash logic", shell=True)
```

Quoted strings work either way — the detector uses `shlex.split` which handles `"quoted args with spaces"` correctly.

## When to use what (cheat sheet)

| Need | Tool |
|---|---|
| One-shot command, ≤30s | `terminal_exec` |
| One-shot command, might be longer | `terminal_exec` (auto-promotes) |
| Long-running job from the start | `terminal_job_start` |
| State across calls (cd, env, REPL) | `terminal_pty_open` + `terminal_pty_run` |
| Search file contents (any path) | `terminal_rg` |
| Find files by name/glob (any path) | `terminal_glob` |
| Retrieve truncated output | `terminal_output_get` |
| Tree / stat / du | `terminal_exec("ls -la"/"stat foo"/"du -sh path")` |
| HTTP / DNS / ping / archives | `terminal_exec("curl ..."/"dig ..."/"tar xzf ...")` |

See `references/exit_codes.md` for the full POSIX + signal-induced + semantic catalog.

Files in this skill

  • SKILL.md9.7 KB
  • references/exit_codes.md2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.