From ee51c5e5fbaea694e65bb0a4908f75bcaf9707d1 Mon Sep 17 00:00:00 2001 From: Ogulcan Celik Date: Mon, 8 Jun 2026 20:55:51 +0300 Subject: feat: use pty-first agent detection --- docs/next/website/src/content/docs/agents.mdx | 73 ++++++++++++---------- docs/next/website/src/content/docs/concepts.mdx | 2 +- .../next/website/src/content/docs/integrations.mdx | 33 +++++----- 3 files changed, 57 insertions(+), 51 deletions(-) (limited to 'docs') diff --git a/docs/next/website/src/content/docs/agents.mdx b/docs/next/website/src/content/docs/agents.mdx index e2054bf1..ca0e29b6 100644 --- a/docs/next/website/src/content/docs/agents.mdx +++ b/docs/next/website/src/content/docs/agents.mdx @@ -7,39 +7,46 @@ Herdr is built for running more than one coding agent at a time. Each agent stay ## Supported agents -Automatic detection works out of the box for common coding agents. - -| Agent | Idle / done | Working | Blocked | -| --- | --- | --- | --- | -| Pi | yes | yes | partial | -| Claude Code | yes | yes | yes | -| Codex | yes | yes | yes | -| Droid | yes | yes | yes | -| Amp | yes | yes | yes | -| OpenCode | yes | yes | yes | -| Grok CLI | yes | yes | yes | -| Hermes Agent | yes | yes | yes | -| Kilo Code CLI | yes | yes | yes | -| Cursor Agent | yes | yes | yes | -| Antigravity CLI | yes | yes | yes | -| Kimi Code CLI | yes | yes | yes | -| Kiro CLI | yes | yes | no | -| GitHub Copilot CLI | yes | yes | yes | -| Qoder CLI | yes | yes | yes | - -Detected but less thoroughly tested: Gemini CLI and Cline. - -Unsupported agents still run normally as terminal processes. They just may not get rich state unless you add an integration or report state over the socket API. - -## How detection works - -Herdr combines three signals: - -1. foreground process detection -2. terminal output heuristics -3. integration session identity or state reports - -Process detection tells Herdr which pane owns an agent. Heuristics infer native agent state from terminal screen snapshots. Claude Code, Codex, Droid, and OpenCode integrations provide session identity for restore; Pi, OMP, GitHub Copilot CLI, Kimi Code CLI, Hermes Agent, Qoder CLI, and custom socket integrations can report state when they define state outside the native terminal UI. +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`. + +| Agent | State authority | Integration role | +| --- | --- | --- | +| Pi | lifecycle hooks when installed; otherwise PTY/screen | state and session | +| OMP | lifecycle hooks when installed | state | +| GitHub Copilot CLI | lifecycle hooks when installed; otherwise PTY/screen | state and session | +| Kimi Code CLI | lifecycle hooks when installed; otherwise PTY/screen | state | +| Hermes Agent | lifecycle hooks when installed; otherwise PTY/screen | state and session | +| Qoder CLI | lifecycle hooks when installed; otherwise PTY/screen | state | +| Claude Code | PTY/screen | session | +| Codex | PTY/screen | session | +| Cursor Agent CLI | PTY/screen | session | +| Droid | PTY/screen | session | +| OpenCode | PTY/screen | session | +| Amp | PTY/screen | none | +| Grok CLI | PTY/screen | none | +| Kilo Code CLI | PTY/screen | none | +| Antigravity CLI | PTY/screen | none | +| Kiro CLI | PTY/screen | none | + +Detected but less thoroughly tested: Gemini CLI and Cline. Unsupported agents still run normally as terminal processes. They just may not get rich state unless you add an integration or report state over the socket API. + +## Status authority + +Herdr first detects the foreground process in each pane. After that, each pane has one status authority. + +For agents with complete lifecycle hooks, the integration is authoritative when it is installed and actively reporting for the running pane. Herdr uses those hook reports for `idle`, `working`, `blocked`, and session identity. It does not also run PTY/screen state fallback for that same lifecycle authority. This avoids two competing sources of truth. + +For agents without complete lifecycle hooks, Herdr uses PTY-first detection. Terminal render activity means the agent is probably `working`. When the terminal becomes quiet, Herdr reads the recent pane screen and asks one strict question: does the visible agent UI match a known blocked prompt? If yes, the pane is `blocked`. If not, the pane is `idle`. + +Herdr briefly ignores detection after a new agent process appears, and after input, mouse events, or pane resize. Those events can make a terminal UI redraw even when the agent did not resume work. Once the quiet window passes, normal detection starts again from fresh PTY activity. + +Claude Code, Codex, Cursor Agent CLI, Droid, and OpenCode integrations are intentionally not lifecycle authorities. They provide native session identity for restore, but their hooks do not cover the whole lifecycle. They can miss permission approval results, escape interrupts, or other transitions. For those agents, Herdr still uses PTY/screen state detection. + +## Blocked state + +Blocked detection is deliberately strict for PTY/screen agents. Herdr treats active terminal output as `working`; it only asks whether the agent is blocked after PTY activity becomes quiet. If the screen does not match a known blocked prompt shape, Herdr falls back to `idle`. + +This means unusual new agent prompts may initially show as `idle` instead of `blocked` until Herdr learns that screen shape. It also means opening an agent menu, moving a selection, or resizing a pane may delay state changes briefly. Those interactions should not make Herdr send input or take destructive action; they only affect the visible status and waits. Herdr can run inside tmux as the outer terminal environment. Agent detection does not inspect tmux sessions launched inside a Herdr pane. If a shell framework auto-enters tmux inside Herdr, Herdr sees `tmux` as the pane process instead of the agent behind it. diff --git a/docs/next/website/src/content/docs/concepts.mdx b/docs/next/website/src/content/docs/concepts.mdx index b1a7908f..356d73db 100644 --- a/docs/next/website/src/content/docs/concepts.mdx +++ b/docs/next/website/src/content/docs/concepts.mdx @@ -25,7 +25,7 @@ Panes can be split right or down. They can be renamed manually, read from the CL ## Agent -An agent is a process Herdr recognizes inside a pane. Herdr detects agents from foreground processes, screen heuristics, and optional integrations. +An agent is a process Herdr recognizes inside a pane. Herdr detects agents from foreground processes, PTY/screen activity, and optional integrations. Agent states are: diff --git a/docs/next/website/src/content/docs/integrations.mdx b/docs/next/website/src/content/docs/integrations.mdx index efe20fbc..b5ed6c77 100644 --- a/docs/next/website/src/content/docs/integrations.mdx +++ b/docs/next/website/src/content/docs/integrations.mdx @@ -3,9 +3,9 @@ title: Integrations description: Install Herdr integrations for Pi, OMP, Claude Code, Codex, GitHub Copilot CLI, Droid, Kimi Code CLI, OpenCode, Hermes Agent, Qoder CLI, and Cursor Agent CLI. --- -Herdr detects supported agents automatically. Official integrations can add native session identity for restore, semantic state reports, or both. Claude Code, Codex, Droid, and OpenCode state comes from screen detection even when their session identity integrations are installed. +Herdr detects supported agents automatically. Official integrations can add native session identity for restore, lifecycle state reports, or both. -Use integrations when you want native agent session restore, direct state reports from Pi/OMP/Copilot/Kimi/Hermes/Qoder-style hooks or plugins, or both. +Use integrations when you want native agent session restore, direct lifecycle reports from Pi/OMP/Copilot/Kimi/Hermes/Qoder-style hooks or plugins, or both. See [Agents](/docs/agents/) for the full status authority model. ## Install integrations @@ -43,15 +43,14 @@ herdr integration uninstall cursor ## How Herdr uses integrations -Herdr combines three signals: +Herdr uses integrations in two different ways: -| Signal | Purpose | -| --- | --- | -| Process detection | Identifies which pane owns which running process. | -| Screen heuristics | Infers visible native agent state such as `working` or `blocked`. | -| Integration events | Reports native session identity, semantic state, or both depending on the integration. | +| Integration type | Agents | Effect | +| --- | --- | --- | +| Lifecycle authority | Pi, OMP, GitHub Copilot CLI, Kimi Code CLI, Hermes Agent, Qoder CLI | When installed and actively reporting for the pane, hook or plugin events author `idle`, `working`, and `blocked`. Herdr does not also use PTY/screen fallback for that same lifecycle authority. | +| Session identity | Claude Code, Codex, Cursor Agent CLI, Droid, OpenCode | The integration reports native session references for restore. State still comes from Herdr's PTY/screen detection. | -Claude Code, Codex, Cursor Agent CLI, Droid, and OpenCode state detection is screen-read first. Their Herdr-owned integrations do not author `idle`, `working`, or `blocked` state. Pi, GitHub Copilot CLI, and Hermes Agent report semantic state and session identity. OMP, Kimi Code CLI, and Qoder CLI report semantic state but do not provide native session restore. Custom socket integrations can report state when they define state that is not visible in the native terminal UI. +Custom socket integrations can also report state when they define state that is not visible in the native terminal UI. Some integrations report native agent session references. Herdr uses official session references to resume Claude Code, Codex, Cursor Agent CLI, GitHub Copilot CLI, Droid, Pi, Hermes Agent, and OpenCode panes after a Herdr server restart unless `[session] resume_agents_on_restore = false` disables it. @@ -99,7 +98,7 @@ Install the Claude Code hook: herdr integration install claude ``` -The hook reports Claude Code session identity to the local Herdr socket on session start. Claude Code state comes from Herdr's screen detection. +The hook reports Claude Code session identity to the local Herdr socket on session start. Claude Code state comes from Herdr's PTY/screen detection. Herdr uses `~/.claude` by default, or `CLAUDE_CONFIG_DIR` when set. The Claude config directory must already exist. Install writes `hooks/herdr-agent-state.sh` and updates `settings.json` with Herdr hook entries. Uninstall removes the matching hook entries and deletes the hook script. @@ -111,7 +110,7 @@ Install the Codex hook: herdr integration install codex ``` -The Codex hook reports session identity through the same local socket API used by other integrations. Codex state comes from Herdr's screen detection. +The Codex hook reports session identity through the same local socket API used by other integrations. Codex state comes from Herdr's PTY/screen detection. Herdr uses `~/.codex` by default, or `CODEX_HOME` when set. The Codex config directory must already exist. Install writes `herdr-agent-state.sh`, updates `hooks.json`, and ensures `[features] hooks = true` in `config.toml`. It also removes the deprecated top-level `codex_hooks` flag when present. Uninstall removes Herdr entries from `hooks.json` and deletes the hook script, but leaves `config.toml` unchanged. @@ -141,7 +140,7 @@ The hook reports semantic state to Herdr when Kimi Code emits lifecycle, tool, a Herdr uses `~/.kimi-code` by default, or `KIMI_CODE_HOME` when set. The Kimi Code config directory must already exist. Install writes `hooks/herdr-agent-state.sh` and appends Herdr-managed `[[hooks]]` entries to `config.toml`. Uninstall removes the Herdr-managed config block and deletes the hook script. -Native screen heuristics remain available when the hook is not installed. +Native PTY/screen detection remains available when the hook is not installed. ## Droid @@ -151,7 +150,7 @@ Install the Droid hook: herdr integration install droid ``` -The Droid hook reports session identity through the same local socket API used by other integrations. Droid state comes from Herdr's screen detection. +The Droid hook reports session identity through the same local socket API used by other integrations. Droid state comes from Herdr's PTY/screen detection. Herdr uses `~/.factory` for Droid hooks. The Factory config directory must already exist. Install writes `hooks/herdr-agent-state.sh`, updates `settings.json` with a Herdr `SessionStart` hook entry, and removes older Herdr Droid hook entries from `hooks.json` if present. Uninstall removes Herdr entries from both config files and deletes the hook script. @@ -167,7 +166,7 @@ herdr integration install opencode Herdr writes the plugin to `~/.config/opencode/plugins/herdr-agent-state.js`. The OpenCode config directory must already exist. Uninstall removes only that plugin file. -The plugin reports session identity while OpenCode runs inside a Herdr pane. After OpenCode emits a session-bearing event, Herdr can use the reported session id to resume the pane with `opencode --session `. OpenCode state comes from Herdr's screen detection. +The plugin reports session identity while OpenCode runs inside a Herdr pane. After OpenCode emits a session-bearing event, Herdr can use the reported session id to resume the pane with `opencode --session `. OpenCode state comes from Herdr's PTY/screen detection. ## Hermes Agent @@ -179,7 +178,7 @@ herdr integration install hermes Herdr writes `~/.hermes/plugins/herdr-agent-state/` and enables `herdr-agent-state` in `~/.hermes/config.yaml`. The Hermes config directory must already exist. Restart Hermes after installing so the plugin loads. Uninstall removes the plugin directory and removes `herdr-agent-state` from `plugins.enabled`. -The plugin reports lifecycle, tool, approval state, and session id while Hermes runs inside a Herdr pane. Herdr can use the reported session id to resume the pane with `hermes --resume `. Native screen heuristics remain available when the plugin is not installed. +The plugin reports lifecycle, tool, approval state, and session id while Hermes runs inside a Herdr pane. Herdr can use the reported session id to resume the pane with `hermes --resume `. Native PTY/screen detection remains available when the plugin is not installed. ## Qoder CLI @@ -193,7 +192,7 @@ The hook reports semantic state to Herdr when Qoder CLI emits lifecycle events. Herdr uses `~/.qoder` by default, or `QODER_CONFIG_DIR` when set. The Qoder config directory must already exist. Install writes `hooks/herdr-agent-state.sh` and updates `settings.json` with Herdr hook entries. Uninstall removes the matching hook entries and deletes the hook script. -Native screen heuristics remain available when the hook is not installed. +Native PTY/screen detection remains available when the hook is not installed. ## Cursor Agent CLI @@ -203,7 +202,7 @@ Install the Cursor Agent CLI hook: herdr integration install cursor ``` -The hook reports session identity through Cursor's `sessionStart` hook while Cursor Agent CLI runs inside a Herdr pane. Cursor state comes from Herdr's screen detection. +The hook reports session identity through Cursor's `sessionStart` hook while Cursor Agent CLI runs inside a Herdr pane. Cursor state comes from Herdr's PTY/screen detection. Herdr uses `~/.cursor` by default, or `CURSOR_CONFIG_DIR` when set. The Cursor config directory must already exist. Install writes `herdr-agent-state.sh` and adds a Herdr `sessionStart` entry to `hooks.json`. Uninstall removes the matching hook entry and deletes the hook script. -- cgit v1.2.3