From 3f80947678a9723434aa7fddfe23750b5393e24c Mon Sep 17 00:00:00 2001 From: Ogulcan Celik Date: Sun, 19 Jul 2026 23:52:20 +0300 Subject: feat: make agent automation a first-class cli primitive --- .../website/src/content/docs/agent-automation.mdx | 122 +++++++++++++++++++++ docs/next/website/src/content/docs/agent-skill.mdx | 2 +- docs/next/website/src/content/docs/agents.mdx | 36 +----- .../website/src/content/docs/cli-reference.mdx | 62 ++++++++--- .../src/content/docs/ja/agent-automation.mdx | 122 +++++++++++++++++++++ .../website/src/content/docs/ja/agent-skill.mdx | 2 +- docs/next/website/src/content/docs/ja/agents.mdx | 36 +----- .../website/src/content/docs/ja/cli-reference.mdx | 65 ++++++++--- .../website/src/content/docs/ja/socket-api.mdx | 10 +- docs/next/website/src/content/docs/socket-api.mdx | 10 +- .../src/content/docs/zh-cn/agent-automation.mdx | 122 +++++++++++++++++++++ .../website/src/content/docs/zh-cn/agent-skill.mdx | 2 +- .../next/website/src/content/docs/zh-cn/agents.mdx | 36 +----- .../src/content/docs/zh-cn/cli-reference.mdx | 65 ++++++++--- .../website/src/content/docs/zh-cn/socket-api.mdx | 10 +- 15 files changed, 543 insertions(+), 159 deletions(-) create mode 100644 docs/next/website/src/content/docs/agent-automation.mdx create mode 100644 docs/next/website/src/content/docs/ja/agent-automation.mdx create mode 100644 docs/next/website/src/content/docs/zh-cn/agent-automation.mdx (limited to 'docs/next/website/src') diff --git a/docs/next/website/src/content/docs/agent-automation.mdx b/docs/next/website/src/content/docs/agent-automation.mdx new file mode 100644 index 00000000..cbedd8c7 --- /dev/null +++ b/docs/next/website/src/content/docs/agent-automation.mdx @@ -0,0 +1,122 @@ +--- +title: Agent automation +description: Use Herdr's layout, pane, and agent primitives to coordinate coding agents from scripts or other agents. +--- + +Herdr can act as an automation layer for coding agents. A script can control them, or one agent can create work for other agents, inspect their state, and collect their results. The important part is choosing the primitive that matches the job. + +## Three primitives + +| Primitive | Responsibility | +| --- | --- | +| Layout (`workspace`, `tab`, and pane topology) | Create and organize terminal locations. | +| Pane | Control a raw terminal: run commands, send input, read output, and wait for output. | +| Agent | Control a recognized coding agent by name or pane and lifecycle state. | + +A pane exists whether or not it contains an agent. An agent is the recognized process currently running inside a pane. `agent start` therefore requires an existing shell pane and never creates, splits, or moves layout. + +Creating a workspace also creates its first tab and root pane; creating a tab creates its root pane. Use the returned pane ID for the first process, and split only when that layout needs another terminal. + +Creation commands print JSON. Capture IDs from the response instead of predicting them: + +```bash +created=$(herdr workspace create --cwd ~/project --label api --no-focus) +pane_id=$(printf '%s\n' "$created" | jq -r '.result.root_pane.pane_id') + +split=$(herdr pane split "$pane_id" --direction right --no-focus) +review_pane=$(printf '%s\n' "$split" | jq -r '.result.pane.pane_id') +``` + +`workspace create` returns `.result.workspace`, `.result.tab`, and `.result.root_pane`. `tab create` returns `.result.tab` and `.result.root_pane`. `pane split` returns the new pane as `.result.pane`. + +Moving a pane to another workspace changes its workspace-qualified pane ID. After any `pane move`, continue with `.result.move_result.pane.pane_id`; the response keeps the old value at `.result.move_result.previous_pane_id`. A running process keeps its launch-time Herdr environment, but the old `HERDR_PANE_ID` remains an alias for that terminal, so `--current` stays safe. New commands can still resolve the agent by name after the move, but a wait already in progress ends with `agent_not_running`. + +Use pane commands for shells, tests, servers, CI watchers, and other ordinary terminal processes. Use agent commands when Herdr needs to understand which agent is running or whether it is `working`, `blocked`, `done`, `idle`, or `unknown`. + +## Agent identity and launch + +A pane ID such as `w1:p2` identifies the terminal location. An agent name such as `reviewer` is a convenient alias for the current agent in that pane. Names must match `[a-z][a-z0-9_-]{0,31}` and be unique among live agents. The alias is cleared when that agent exits, is released, or is replaced; it does not permanently rename the pane. + +Agent commands accept either a unique live name or the pane ID that currently hosts the agent. + +An available shell pane is at its interactive shell prompt: the shell itself owns the foreground, with no foreground command, editor, or agent running. Return the pane to its prompt before calling `agent start`. + +`--kind` selects a supported agent and its canonical executable. Supported kinds are `pi`, `claude`, `codex`, `gemini`, `cursor`, `devin`, `agy`, `cline`, `omp`, `mastracode`, `opencode`, `copilot`, `kimi`, `kiro`, `droid`, `amp`, `grok`, `hermes`, `kilo`, `qodercli`, and `maki`. Arguments after `--` are passed unchanged to that executable. + +`agent start` returns only after Herdr detects the expected agent in the same terminal and marks it ready for interactive input. Startup waits for 30 seconds by default; `--timeout` must be greater than 3000 and no more than 300000 milliseconds. + +```bash +herdr agent start reviewer --kind codex --pane "$review_pane" -- -m gpt-5.4 +``` + +The equivalent fixed-ID example is: + +```bash +herdr pane split --current --direction right --no-focus +herdr agent start reviewer --kind codex --pane w1:p2 -- -m gpt-5.4 +``` + +Agents launched manually are detected automatically and can be addressed by pane ID. Give one a name when a stable human-readable target is useful: + +```bash +herdr agent get w1:p2 +herdr agent rename w1:p2 reviewer +``` + +## Choose the control surface + +| Goal | Command | +| --- | --- | +| Run a shell command and submit it | `pane run` | +| Send literal text without Enter | `pane send-text` | +| Send terminal keys or modifier chords | `pane send-keys` | +| Wait for text or a regular expression | `pane wait-output` | +| Start a supported agent in an existing pane | `agent start` | +| Submit a prompt, optionally waiting for it | `agent prompt` | +| Send keys to an agent's interactive UI | `agent send-keys` | +| Wait for agent lifecycle state | `agent wait` | + +`agent prompt` submits text plus encoded Enter and honors the terminal's live bracketed-paste mode. It can prompt an agent that is already working. Use `agent send-keys` for interactions such as `esc`, `up`, `enter`, or `ctrl+c`; `escape` is accepted as an alias for `esc`. Use the pane input commands when you deliberately want raw terminal control. + +Pane input addresses the terminal regardless of its current occupant. Agent input resolves the live agent and rejects the operation if that agent no longer controls the pane. + +`agent prompt --wait` submits immediately, then waits for the first matching lifecycle state observed afterward. It does not track individual turns. If the agent is already working, completion of that active turn may satisfy the wait. To run prompts as separate turns, send the next prompt only after the previous wait returns. To steer an active turn with several messages, send those prompts without `--wait`, then use `agent wait` when you want to wait for the next settled state. Standalone `agent wait` observes the current agent and returns immediately if its status already matches. Both commands default to `idle`, `done`, or `blocked`. Repeat `--until` to accept several exact states, for example `--until idle --until done`; use `--until unknown` explicitly when needed. On `agent prompt`, `--until` requires `--wait`. + +`idle` means the agent is ready for input and its tab has been seen in the focused Herdr UI. `done` is the same underlying idle state after background work finishes, until that tab is focused or `pane focus` / `agent focus` targets it. Reading through the CLI does not mark it seen. `blocked` means Herdr recognized an approval or question UI. `unknown` means an agent is present but Herdr cannot classify its lifecycle confidently; it does not prove successful completion. Use exact `--until` states when that distinction matters. + +`pane wait-output` does not interpret agent lifecycle. It polls the selected terminal snapshot and searches it immediately, so text that was already present can match. The default source name is `recent`; matching treats that source as unwrapped recent output. `--lines` limits the searched snapshot, `--regex` uses Rust regular-expression syntax and matches one line at a time, and `--raw` keeps ANSI escape sequences while matching. + +At the CLI, both `pane read` and `agent read` print terminal text directly. The default is UTF-8 text with ANSI escapes stripped; use `--format ansi` or `--ansi` to preserve terminal escapes where the source exposes them. The `detection` source is always plain text. For every read source, `--lines N` returns the last N logical lines. The socket API returns the text at `.result.read.text`. + +Successful `agent start`, `agent prompt`, and `agent wait` commands return the current agent at `.result.agent`. `pane wait-output` returns `.result.pane_id`, `.result.matched_line`, and the matched snapshot at `.result.read`. + +Wait commands have no default timeout and can wait indefinitely. On timeout or another server error, CLI commands print a JSON error to stderr and exit with status 1; invalid CLI syntax exits with status 2. + +## Recipes + +Start a helper, give it work, and wait for that work to settle: + +```bash +split=$(herdr pane split --current --direction right --no-focus) +review_pane=$(printf '%s\n' "$split" | jq -r '.result.pane.pane_id') +herdr agent start reviewer --kind codex --pane "$review_pane" -- -m gpt-5.4 +herdr agent prompt reviewer "Review the current diff" --wait --timeout 120000 +herdr agent read reviewer --source recent-unwrapped --lines 120 +``` + +Wait for an agent to ask for input, inspect it, and interact with its UI: + +```bash +herdr agent wait reviewer --until blocked --timeout 120000 +herdr agent read reviewer --source recent-unwrapped --lines 80 +herdr agent send-keys reviewer esc +``` + +Run an ordinary process and wait for its output without treating it as an agent: + +```bash +herdr pane run w1:p3 "just test --watch" +herdr pane wait-output w1:p3 --regex "passed|failed" --timeout 120000 +``` + +See the [CLI reference](/docs/cli-reference/) for the complete command and option list. Shell completions expose the same command tree interactively. diff --git a/docs/next/website/src/content/docs/agent-skill.mdx b/docs/next/website/src/content/docs/agent-skill.mdx index 13a90154..498861f7 100644 --- a/docs/next/website/src/content/docs/agent-skill.mdx +++ b/docs/next/website/src/content/docs/agent-skill.mdx @@ -58,7 +58,7 @@ This prevents an agent outside Herdr from trying to control a session it does no ## Agent-facing reference -The full command guide lives in the skill file itself. It covers pane IDs, `pane split`, `pane run`, `pane read`, `wait output`, `wait agent-status`, workspace and tab commands, and coordination recipes. +The full command guide lives in the skill file itself. It covers pane IDs, `pane split`, `pane run`, `pane read`, `pane wait-output`, `agent wait`, workspace and tab commands, and coordination recipes. Read the source file here: diff --git a/docs/next/website/src/content/docs/agents.mdx b/docs/next/website/src/content/docs/agents.mdx index 958852fa..ee275d19 100644 --- a/docs/next/website/src/content/docs/agents.mdx +++ b/docs/next/website/src/content/docs/agents.mdx @@ -5,6 +5,8 @@ description: See what Herdr can detect, how agent state works, and how integrati Herdr is built for running more than one coding agent at a time. Each agent stays in a real terminal pane with its shell, logs, prompts, and running processes intact. Herdr tracks which panes contain agents, rolls their state up to tabs and workspaces, and lets you jump straight to the pane that needs attention instead of polling every terminal by hand. +To coordinate agents from scripts or from another agent, see [Agent automation](/docs/agent-automation/). + ## Supported agents Automatic detection works out of the box for common coding agents. The important difference is not whether Herdr can see an agent. It is which signal is allowed to author `idle`, `working`, and `blocked`. @@ -110,7 +112,7 @@ herdr agent rename w1:p1 reviewer herdr agent rename reviewer --clear ``` -Targets accept terminal IDs, unique agent names, detected or reported agent labels, and legacy pane IDs. +Targets accept a unique live agent name or the pane ID that currently hosts the agent. Terminal IDs and bare agent-kind labels are not accepted. ## Custom status labels @@ -131,38 +133,6 @@ herdr pane report-metadata w1:p1 \ Agent sidebar rows can also opt into `terminal_title` or `terminal_title_stripped`; neither appears in the default rows. The first shows the latest safety-normalized OSC 0/2 terminal title. The second removes one recognized leading activity or spinner glyph and following whitespace. Herdr owns these values on the server; they are ephemeral across a cold restart and remain independent of metadata titles and semantic agent state. Spinner animation can therefore update the raw title without producing a pane update when the stripped text stays the same. -## Start agents from the CLI - -Use workspace, tab, pane, and layout commands to create topology first. Then activate an existing shell pane as a supported interactive agent with a unique name: - -```bash -herdr pane split --current --direction right --no-focus -herdr agent start reviewer --kind pi --pane w1:p2 -``` - -`agent start` never creates or splits topology. Herdr chooses the canonical executable for the requested kind, labels the target pane with the unique name, and returns after the expected interactive agent is detected as idle, done, or blocked. Optional native arguments follow `--`: - -```bash -herdr agent start reviewer --kind pi --pane w1:p2 -- --name scratch --no-session -``` - -Submit a prompt by name. `--wait` binds the wait to that prompt and returns when the agent finishes or becomes blocked: - -```bash -herdr agent prompt reviewer "Review the current diff" --wait --timeout 120000 -``` - -`agent prompt` honors the terminal's live bracketed-paste mode before sending Enter, so text such as `A != B` reaches agents without triggering input-mode keybindings. Use it for submissions; `agent send` remains a low-level literal-text operation and does not submit a turn. - -For an agent that is already working, `agent wait` returns when its status becomes idle, done, or blocked. It returns immediately if one of those statuses is already current. - -```bash -herdr agent wait reviewer --timeout 120000 -herdr agent read reviewer --source recent-unwrapped --lines 120 -``` - -Use `herdr pane ...` commands for ordinary terminals, servers, tests, shells, topology, and low-level terminal input. - ## Attach directly to an agent Attach your current terminal to one agent terminal instead of the full Herdr UI: diff --git a/docs/next/website/src/content/docs/cli-reference.mdx b/docs/next/website/src/content/docs/cli-reference.mdx index 4d668df9..88585b8a 100644 --- a/docs/next/website/src/content/docs/cli-reference.mdx +++ b/docs/next/website/src/content/docs/cli-reference.mdx @@ -130,6 +130,8 @@ Create a workspace without stealing focus: herdr workspace create --cwd ~/project --label api --no-focus ``` +A workspace is the top-level project or work context. Creating one also creates its first tab and root pane. The JSON response exposes their IDs as `.result.workspace.workspace_id`, `.result.tab.tab_id`, and `.result.root_pane.pane_id`. + ## Worktrees ```bash @@ -154,6 +156,10 @@ herdr tab rename