Watch
0
0
Fork
You've already forked hyperhive
0

docs/tools: the bash and matrix pages say what the tools do around the edges, not how to call them

Each page opens with its audience (the operator). The per-parameter tool
listings, which repeat the tools' own MCP descriptions, become short summaries
of the behaviour an operator needs: the completion todo, what status clears,
the process-group kill, the unread guard, how invites resolve. The wiring and
architecture sections are unchanged.
This commit is contained in:
iris 2026-10-26 16:47:28 +01:00 • committed by mara
commit 2d1b6a4e1a
2 changed files with 56 additions and 137 deletions

View file

@ -1,5 +1,8 @@
# Bash execution tools
For the operator: this page covers the daemon as deployed and what the tools do
around the edges. How an agent calls them is in the tools' own MCP descriptions.
Background shell execution via `hive-bash-daemon`. Tools land as
`mcp__bash__<tool>` (the MCP server name is `bash`, not `hyperhive`).
`nix/agent-modules/mcp.nix` registers bash into `services.hyperhive.agent.extraMcpServers`
@ -16,78 +19,30 @@ so a change applies at the next one. See "Relationship to the
## Tools
### `run(cmd, timeout_secs?, wait_seconds?, name?)`
Each tool's parameters and return values are in its own MCP description, which
is what an agent reads at call time. This section says what the tools do around
the edges.
Submit a shell command for background execution (runs via `bash`).
Stdout and stderr stream to `harness/bash-tasks/<id>.{out,err}`.
When the task completes (or times out, or the process errors), it
surfaces as a todo in the agent's loose-ends (via `get_loose_ends`),
carrying the exit code and a `Read(<path>)` pointer to the captured
output. Handle it on a future turn — unless `wait_seconds` already
delivered the terminal result inline, in which case the daemon creates
no todo (see `status` below).
- `timeout_secs` — kill the task after N seconds and mark it
`timed_out`. Omit for no timeout (runs until natural exit).
- `wait_seconds` — inline poll before returning (capped at 30).
When the task finishes within the window the full status is
returned immediately and the daemon creates no todo; when the window expires
the task keeps running and the daemon returns the normal
`task started: id=<id>` response. **Defaults to 3** — pass `wait_seconds: 0`
to disable inline waiting and always get the immediate response.
- `name` — optional caller-chosen task id. When set it replaces the
autogenerated hex id, so it surfaces in `status(<name>)` lookups and
the loose-ends list — a memorable label instead of an opaque id. A name
is **reusable once its previous task has finished**; the daemon
rejects a name whose task is still `pending`/`running`. Allowed
characters: `[a-z0-9-]` (a valid identifier — lowercase, digits,
hyphen; max 63). Omit for the autogenerated id.
Exposed as `mcp__bash__run`.
### `status(id, wait_seconds?)`
Poll the status of a task submitted with `run`. Returns:
- `status` — `pending` / `running` / `done` / `timed_out` / `interrupted` / `killed`
- `exit_code` — set when done
- run duration
- last 4 KiB of stdout and stderr (full output in the `.out` / `.err` files)
`wait_seconds` — optional inline poll (capped at 30): when the task
finishes within the window the call returns the full status immediately.
Useful to avoid a separate round-trip when you expect the task to
finish soon.
Any `status` call (waited or not) that observes a terminal task clears
that task's completion todo — you already have the result in this
response, so no redundant loose-end follows. Narrow best-effort race: a
`status`/`run` inline wait that resolves in the same instant the task
actually finishes can still occasionally get both.
Tasks marked `interrupted` had their process killed by a harness
restart; a best-effort todo is still surfaced so the agent isn't
silently blocked.
Exposed as `mcp__bash__status`.
### `kill(id, force?)`
Stop a running or pending task by its ID (from `run`). Fire-and-forget:
sends the signal and returns without waiting — the completion surfaces
in the agent's loose-ends; handle it on a future turn.
- `force: false` (default) — SIGINT to the task's **process group**
(graceful; lets the process clean up). The whole process group is
signalled, so children spawned by the shell (cargo, nix, etc.) are
also stopped.
- `force: true` — SIGKILL.
If a SIGINT'd task doesn't exit, call `kill` again with `force: true`.
The daemon cancels a still-pending task before it starts. The task ends as
`killed` and surfaces in the loose-ends like any completion.
Exposed as `mcp__bash__kill`.
- **`run`** submits a shell command (through `bash`) as a background task. Its
stdout and stderr stream to `harness/bash-tasks/<id>.{out,err}`. When the
task finishes, times out or its process errors, it surfaces as a todo in the
agent's loose-ends, with the exit code and a pointer to the captured output.
`run` waits up to 3 seconds (30 at most) for a result before it returns; a
result delivered that way makes no todo. A caller-chosen `name` replaces the
generated id. The daemon accepts the name again once its task has finished,
and rejects it while the task is still pending or running.
- **`status`** polls a task: its state (`pending`, `running`, `done`,
`timed_out`, `interrupted` or `killed`), the exit code, the run time and the last
4 KiB of each stream. A call that sees a finished task clears its completion
todo, since the agent already has the result; in a narrow race both can still
appear. A task marked `interrupted` had its process killed by a harness
restart, and a best-effort todo is still made so the agent isn't blocked
silently.
- **`kill`** stops a running or pending task and returns without waiting. The
completion surfaces as a todo like any other. It signals the task's whole
process group, so children the shell started stop too: SIGINT by default,
SIGKILL with `force`. The daemon cancels a task still pending before it
starts, and the task ends as `killed`.
## Namespace note