diff options
| -rw-r--r-- | .pi/prompts/pre-release-audit.md | 46 | ||||
| -rw-r--r-- | CHANGELOG.md | 21 | ||||
| -rw-r--r-- | CONFIGURATION.md | 37 | ||||
| -rw-r--r-- | INTEGRATIONS.md | 44 | ||||
| -rw-r--r-- | README.md | 11 | ||||
| -rw-r--r-- | SOCKET_API.md | 85 | ||||
| -rw-r--r-- | docs/next/CHANGELOG.md | 18 | ||||
| -rw-r--r-- | docs/next/SOCKET_API.md | 3 |
8 files changed, 223 insertions, 42 deletions
diff --git a/.pi/prompts/pre-release-audit.md b/.pi/prompts/pre-release-audit.md index 62fe4362..4ff2ecd4 100644 --- a/.pi/prompts/pre-release-audit.md +++ b/.pi/prompts/pre-release-audit.md @@ -49,9 +49,11 @@ Process: - Treat `docs/next/CHANGELOG.md` as the next-release changelog. - Compare meaningful user-facing changes in the commit range against `docs/next/CHANGELOG.md`. - Flag missing entries for new features, bug fixes, removals, breaking changes, defaults, compatibility changes, user-visible command/config/API behavior, and security-relevant changes. + - Do not require changelog entries solely for internal client/server protocol version bumps. Mention protocol only when the release intentionally changes user-facing compatibility guidance beyond the normal restart requirement. - Inspect commit bodies for issue reference lines in the form `refs #<issue-number>`. - Flag normal commits that use GitHub closing keywords like `fixes #<issue-number>`, `closes #<issue-number>`, or `resolves #<issue-number>`, because they close issues before release when they land on `master`. - For each shipped issue reference, check whether the changelog has a matching user-facing entry that mentions `#<issue-number>` when appropriate. + - For each merged external PR, check whether the changelog entry mentions the PR number and thanks the contributor in the existing style, e.g. `(#129, thanks @username)`. If the PR primarily ships an issue fix, include both the issue and PR numbers when useful, e.g. `(#128, #129, thanks @username)`. - Do not require or add GitHub closing keywords like `fixes #<issue-number>`, `closes #<issue-number>`, or `resolves #<issue-number>` to changelog entries or release notes. - List shipped issue references under `Issue references to close after release:` so the release operator can verify what release CI will close after the GitHub Release is published. - Flag stale entries that do not appear to correspond to shipped changes in the range. @@ -82,16 +84,38 @@ Process: Output format: -- `Base ref:` -- `PRs included:` -- `Direct commits included:` -- `Excluded as housekeeping:` -- `Next-release changelog audit:` -- `Issue references to close after release:` -- `Next-release docs audit:` -- `Root finalization status:` -- `Required changes before release:` -- `Proposed changelog edits:` -- `Proposed docs edits:` +```md +Release readiness: READY | NOT READY + +Base: <base ref> +Range: <base ref>..HEAD +Meaningful shipped changes: yes | no + +Changelog: OK | MISSING ENTRIES | NEEDS ATTENTION +Missing: +- <only user-facing shipped changes missing from docs/next/CHANGELOG.md> + +Docs: OK | MISSING | INACCURATE | NEEDS DECISION +Missing: +- <only required next-release public docs gaps> + +Wrong or questionable: +- <docs that disagree with implementation, if any> + +Issue refs: OK | NEEDS ATTENTION +Will close after release: +- #<issue> + +Accepted/no action: +- <items the user explicitly accepted, such as known closing-keyword commits> + +Root docs finalized: YES | NO +<result of just release-docs-check or why it was not run> + +Required before release: +1. <short action> +``` + +Keep the main output glanceable. Put commit inventories, excluded housekeeping, and commands run in an appendix only when they materially help the operator. If the range has no meaningful user-facing changes, say that plainly instead of forcing entries. diff --git a/CHANGELOG.md b/CHANGELOG.md index ec9402b7..e3435397 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,27 @@ ## Unreleased +### Added +- Added indexed keybind families under `[keys.indexed]` for jumping directly to workspace, tab, or visible agent positions 1-9. +- Added hook-owned custom agent status labels, so integrations can show short visual states like `indexing` without changing semantic agent status. +- Added terminal-backed agent commands and socket API methods for listing, reading, sending to, renaming, focusing, waiting on, attaching to, and starting agent terminals. +- Added direct terminal attach with `herdr agent attach <target>` and `herdr terminal attach <terminal_id>`. +- Added `ui.prompt_new_tab_name = false` for creating new tabs immediately with generated names instead of opening the rename dialog. (#123) +- Added optional `keys.edit_scrollback` to open the focused pane's retained scrollback in `$EDITOR` inside a temporary zoomed pane. (#122) + +### Changed +- Renamed the focused pane fullscreen keybinding to `keys.zoom`; `keys.fullscreen` remains supported as a legacy alias. + +### Fixed +- Grok Build is now detected as `grok`, with basic working, blocked, and idle state detection. Conflicting known-agent hook labels are ignored once native foreground-process detection identifies a different known agent. (#133) +- Terminal cursor shapes now forward through attached clients. (#116) +- Herdr now redraws immediately when the outer terminal regains focus. +- GitHub Copilot is now correctly detected when its process name is `copilot`. (#118) +- Integration installs now respect `PI_CODING_AGENT_DIR`, `CLAUDE_CONFIG_DIR`, and `CODEX_HOME` when choosing Pi, Claude Code, and Codex config paths. (#121) +- Split pane resize hit areas no longer overlap the first content column or row, making text selection work from the start of right and bottom panes. (#120) +- Dragging text selections near pane edges now autoscrolls into scrollback, and selection state now clears correctly when switching workspaces, tabs, or panes. (#128, #129, thanks @leeeanh) +- Zoomed panes now keep their border visible in tabs that contain multiple panes. (#115) + ## [0.5.9] - 2026-05-15 ### Added diff --git a/CONFIGURATION.md b/CONFIGURATION.md index 5fb924d5..e988e72e 100644 --- a/CONFIGURATION.md +++ b/CONFIGURATION.md @@ -77,14 +77,14 @@ keybindings live under `[keys]`. supported syntax: - plain keys: `n`, `x`, `-`, `` ` `` -- modifiers: `ctrl+b`, `shift+n`, `alt+x` +- modifiers: `ctrl+b`, `shift+n`, `alt+x`, `cmd+x`, `super+x` - special keys: `enter`, `esc`, `tab`, `backspace`, `left`, `right`, `up`, `down` - function keys: `f1`, `f12` - uppercase letters also imply shift: `D` works like `shift+d` notes: - most reliable bindings are plain keys, `ctrl+letter`, `esc`/`tab`/`enter`, and function keys -- `alt+...` and punctuation-with-modifiers may vary depending on terminal/tmux setup +- `alt+...`, `cmd`/`super`, and punctuation-with-modifiers may vary depending on terminal/tmux setup - bindings marked `unset` in the key reference are supported actions with no default key assigned - for navigate-mode actions, duplicate keybindings are treated as config errors; later conflicting bindings fall back to defaults @@ -103,7 +103,8 @@ split_vertical = "d" split_horizontal = "D" close_pane = "x" rename_pane = "" # optional, unset by default -fullscreen = "f" +edit_scrollback = "" # optional, opens focused pane scrollback in $EDITOR +zoom = "f" # legacy alias: fullscreen resize_mode = "r" toggle_sidebar = "b" previous_workspace = "ctrl+alt+[" @@ -116,6 +117,11 @@ focus_pane_left = "alt+h" focus_pane_down = "alt+j" focus_pane_up = "alt+k" focus_pane_right = "alt+l" + +[keys.indexed] +tabs = "" # optional; e.g. "ctrl" makes ctrl+1..9 switch tabs +workspaces = "" # optional; e.g. "ctrl+shift" makes ctrl+shift+1..9 switch workspaces +agents = "" # optional; follows visible agent panel order ``` ### key reference @@ -146,10 +152,30 @@ focus_pane_right = "alt+l" | `split_horizontal` | `-` | split pane horizontally (stacked) | | `close_pane` | `x` | close focused pane | | `rename_pane` | unset | rename the focused pane | -| `fullscreen` | `f` | toggle focused pane fullscreen | +| `edit_scrollback` | unset | open the focused pane's retained scrollback in `$EDITOR` inside a temporary zoomed pane | +| `zoom` | `f` | zoom focused pane; legacy alias: `fullscreen` | | `resize_mode` | `r` | enter or leave resize mode | | `toggle_sidebar` | `b` | collapse or expand the sidebar | +`edit_scrollback` writes the focused pane's retained plain-text scrollback to a temporary file, opens `${EDITOR:-vi}` on that file in a temporary zoomed pane, then removes the file when the editor exits. + +### indexed keybindings + +Use `[keys.indexed]` to bind number keys `1` through `9` as positional shortcuts. Each value is a modifier combo only. Empty values disable that shortcut family. + +```toml +[keys.indexed] +tabs = "" +workspaces = "" +agents = "" +``` + +| key | default | action | +|-----|---------|--------| +| `tabs` | unset | switch to tab 1-9 in the active workspace, left to right | +| `workspaces` | unset | switch to workspace 1-9 in sidebar order, top to bottom | +| `agents` | unset | focus agent row 1-9 in the visible agent panel order | + ### custom command keybindings Use `[[keys.command]]` to bind a prefix-mode key to a command. Press the prefix key, then the configured key. @@ -270,6 +296,7 @@ for `panel_bg`, you can also use `reset`, `default`, `none`, or `transparent` to sidebar_width = 26 mouse_capture = true confirm_close = true +prompt_new_tab_name = true show_agent_labels_on_pane_borders = false agent_panel_scope = "all" accent = "cyan" @@ -282,6 +309,7 @@ accent = "cyan" | `sidebar_width` | `26` | base sidebar width before auto-scaling | | `mouse_capture` | `true` | capture mouse input for Herdr's mouse UI; set false to let the terminal handle normal clicks while still forwarding mouse to pane apps that request it | | `confirm_close` | `true` | ask before closing a workspace | +| `prompt_new_tab_name` | `true` | ask for a tab name before creating a new tab; set false to create tabs immediately with generated names | | `show_agent_labels_on_pane_borders` | `false` | show detected/reported agent labels in split pane borders when no manual pane name is set | | `agent_panel_scope` | `all` | sidebar agent list scope: `current` or `all` | | `accent` | `cyan` | highlight and border color | @@ -374,6 +402,7 @@ available agent keys: - `kimi` - `droid` - `amp` +- `grok` ## experimental diff --git a/INTEGRATIONS.md b/INTEGRATIONS.md index ec4e4884..23b41ab8 100644 --- a/INTEGRATIONS.md +++ b/INTEGRATIONS.md @@ -55,6 +55,14 @@ this writes the bundled pi extension to: ~/.pi/agent/extensions/herdr-agent-state.ts ``` +if `PI_CODING_AGENT_DIR` is set, herdr uses that agent directory instead and writes to: + +```text +$PI_CODING_AGENT_DIR/extensions/herdr-agent-state.ts +``` + +`~` is expanded in `PI_CODING_AGENT_DIR`. + pi is the cleanest integration. it already has an authoritative hook model, so herdr can get direct state reports over the socket api without guessing as much from the terminal. bundled source: [`src/integration/assets/pi/herdr-agent-state.ts`](./src/integration/assets/pi/herdr-agent-state.ts) @@ -65,11 +73,7 @@ uninstall: herdr integration uninstall pi ``` -this removes: - -```text -~/.pi/agent/extensions/herdr-agent-state.ts -``` +this removes the same extension path herdr would install, using `PI_CODING_AGENT_DIR` when it is set. ## claude code @@ -84,6 +88,8 @@ this: - writes the hook script to `~/.claude/hooks/herdr-agent-state.sh` - updates `~/.claude/settings.json` +if `CLAUDE_CONFIG_DIR` is set, herdr uses that directory instead, for example `$CLAUDE_CONFIG_DIR/hooks/herdr-agent-state.sh` and `$CLAUDE_CONFIG_DIR/settings.json`. `~` is expanded in `CLAUDE_CONFIG_DIR`. + bundled source: [`src/integration/assets/claude/herdr-agent-state.sh`](./src/integration/assets/claude/herdr-agent-state.sh) current hook mapping: @@ -102,6 +108,7 @@ notes: - claude code hooks also run inside subagents. herdr treats subagent `working` and `blocked` reports as real pane state. - subagent stop/release events are converted to `working` by the bundled hook script so a completed subagent does not make the parent claude pane look idle. - `PostToolUse` and `PostToolUseFailure` move the pane back to `working` after a permissioned tool call resolves. +- some non-claude tools, including grok cli, may load claude settings or plugins. herdr ignores conflicting known-agent hook labels once native foreground-process detection identifies a different known agent. uninstall: @@ -109,10 +116,7 @@ uninstall: herdr integration uninstall claude ``` -this: - -- removes `~/.claude/hooks/herdr-agent-state.sh` -- removes herdr-owned hook entries from `~/.claude/settings.json` +this removes the same hook path and settings entries herdr would install, using `CLAUDE_CONFIG_DIR` when it is set. ## codex @@ -129,6 +133,8 @@ this: - ensures `hooks = true` under `[features]` in `~/.codex/config.toml` - migrates the deprecated top-level `[features] codex_hooks = true` setting to `hooks = true` +if `CODEX_HOME` is set, herdr uses that directory instead, for example `$CODEX_HOME/herdr-agent-state.sh`, `$CODEX_HOME/hooks.json`, and `$CODEX_HOME/config.toml`. `~` is expanded in `CODEX_HOME`. + bundled source: [`src/integration/assets/codex/herdr-agent-state.sh`](./src/integration/assets/codex/herdr-agent-state.sh) current hook mapping: @@ -153,9 +159,9 @@ herdr integration uninstall codex this: -- removes `~/.codex/herdr-agent-state.sh` -- removes herdr-owned hook entries from `~/.codex/hooks.json` -- intentionally leaves `~/.codex/config.toml` alone +- removes the same hook path herdr would install, using `CODEX_HOME` when it is set +- removes herdr-owned hook entries from the matching `hooks.json` +- intentionally leaves the matching `config.toml` alone that last point is deliberate: herdr does **not** try to guess whether `hooks = true` is still needed for some other codex hook setup. @@ -204,6 +210,20 @@ this removes: ~/.config/opencode/plugins/herdr-agent-state.js ``` +## grok cli + +herdr does not currently install a grok hook or plugin. + +grok is heuristic-only in herdr. herdr detects `grok` and `grok-build` from the foreground process and uses screen heuristics for `working`, `blocked`, and `idle` states. + +grok cli may load claude settings or plugins as a compatibility feature, including hooks from `~/.claude/settings.json`. if that causes the claude herdr hook to run in a grok pane, herdr ignores the conflicting `claude` hook label once native foreground-process detection identifies the pane as `grok`. + +## amp + +herdr does not currently install an Amp plugin. + +Amp's public plugin API exposes lifecycle and tool-call hooks, but not passive permission/request-blocked events. A Herdr Amp plugin that only reports `idle` and `working` would take hook authority for the pane and mask Herdr's existing screen heuristics for Amp `blocked` states. Until Amp exposes permission state as an observable plugin event, Amp remains heuristic-only in Herdr. + ## known limitations - these integrations only activate inside herdr-managed panes. @@ -108,6 +108,12 @@ Host workbox same session, same agents, same state. +### direct agent attach + +`herdr` and `herdr --remote` attach to the full Herdr session UI. `herdr agent attach <target>` attaches your current terminal directly to one server-owned terminal, like a single-pane terminal attach. `herdr terminal attach <terminal_id>` does the same by terminal id. + +Direct attach streams the current rendered terminal state first, then live ANSI frames. Your input goes straight to that terminal. Detach with `ctrl+b q`; send a literal `ctrl+b` with `ctrl+b ctrl+b`. One writable client owns input and resize for a terminal. A second attach fails unless you pass `--takeover`. + ## agent awareness the sidebar shows which agents are blocked, working, or done. workspaces roll up to their most urgent state so you can scan the full list at a glance. @@ -147,7 +153,7 @@ herdr tab create --label "logs" herdr pane split 1-1 --direction right herdr pane run 1-2 "npm test" -# wait for an agent +# wait for a pane-level UI attention state herdr wait agent-status 1-1 --status done # read output @@ -171,6 +177,7 @@ automatic detection works out of the box. process name matching plus terminal ou | [droid](https://factory.ai) | ✓ | ✓ | ✓ | | [amp](https://ampcode.com) | ✓ | ✓ | ✓ | | [opencode](https://github.com/anomalyco/opencode) | ✓ | ✓ | ✓ | +| [grok cli](https://x.ai/grok) | ✓ | ✓ | ✓ | detected but not fully tested: gemini cli, cursor agent, cline, kimi, github copilot cli. @@ -202,7 +209,7 @@ press `ctrl+b` to enter navigate mode. | `v` / `-` | split pane | | `x` | close pane | | `b` | toggle sidebar | -| `f` | fullscreen pane | +| `f` | zoom pane | | `r` | resize mode | | `q` | detach (quit client) | diff --git a/SOCKET_API.md b/SOCKET_API.md index 51046860..7ffb276e 100644 --- a/SOCKET_API.md +++ b/SOCKET_API.md @@ -9,7 +9,7 @@ if you are teaching an agent that is already running inside herdr, start with [` there are three practical ways to integrate with herdr: - **agent skill** — [`SKILL.md`](./SKILL.md). best when an agent inside herdr just needs to learn the workflow quickly. -- **cli wrappers** — `herdr server stop`, `herdr workspace ...`, `herdr tab ...`, `herdr pane ...`, `herdr wait ...`. best for shell scripts and simple orchestration. +- **cli wrappers** — `herdr server stop`, `herdr workspace ...`, `herdr tab ...`, `herdr agent ...`, `herdr pane ...`, `herdr wait ...`. best for shell scripts and simple orchestration. - **raw socket api** — best when you want direct request/response control or long-lived event subscriptions. these layers are intentionally stacked on top of the same control surface. @@ -141,6 +141,7 @@ for backward compatibility, requests also accept the older positional forms like ```json { "pane_id": "w64e95948145ed1-1", + "terminal_id": "term_64e95948145ed1", "workspace_id": "w64e95948145ed1", "tab_id": "w64e95948145ed1:1", "focused": true, @@ -148,18 +149,42 @@ for backward compatibility, requests also accept the older positional forms like "label": "reviewer", "agent": "pi", "agent_status": "working", + "custom_status": "indexing", "revision": 0 } ``` +`terminal_id` is an opaque terminal identity. during the pane-backed transition each pane has one terminal id, but clients should not derive it from the pane id. + `label` is an optional manual pane name set through `pane.rename`. +`agent_info` responses contain a terminal-facing view of a live agent terminal: + +```json +{ + "terminal_id": "term_64e95948145ed1", + "name": "reviewer", + "agent": "pi", + "agent_status": "working", + "workspace_id": "w64e95948145ed1", + "tab_id": "w64e95948145ed1:1", + "pane_id": "w64e95948145ed1-1", + "focused": true, + "cwd": "/home/can/Projects/herdr", + "revision": 0 +} +``` + +`name` is an optional unique agent alias set by `agent.start` or `agent.rename`. it is separate from the pane `label`: `pane.rename` names a terminal/pane for UI purposes, while `agent.rename` declares or changes the agent-facing name and rejects duplicate active agent names. + `agent` is an optional display label string. - when herdr detects a built-in agent, this is that built-in name like `pi` or `claude` - when a hook or plugin reports a custom agent through `pane.report_agent`, this can be any non-empty label like `hermes` - when no agent identity is known, it is omitted +`custom_status` on `pane_info` and agent-status events is an optional hook-owned display label. It is present only while hook authority is active. It does not change `agent_status`, `done` semantics, waits, notifications, or workspace/tab rollup priority. + `pane_read` responses contain objects like: ```json @@ -203,6 +228,13 @@ for backward compatibility, requests also accept the older positional forms like | `tab.focus` | focus a tab | `tab_info` | | `tab.rename` | rename a tab | `tab_info` | | `tab.close` | close a tab | `ok` | +| `agent.list` | list terminal-backed agents | `agent_list` | +| `agent.get` | inspect one agent by terminal id, unique agent name, detected agent label, or pane id | `agent_info` | +| `agent.read` | read output from one agent terminal | `pane_read` | +| `agent.send` | send literal text to one agent terminal | `ok` | +| `agent.rename` | set or clear the unique agent name | `agent_info` | +| `agent.focus` | show the agent terminal in the TUI | `agent_info` | +| `agent.start` | start a named agent terminal from argv | `agent_started` | | `pane.list` | list panes, optionally filtered by workspace | `pane_list` | | `pane.get` | inspect one pane | `pane_info` | | `pane.rename` | set or clear a manual pane label | `pane_info` | @@ -624,7 +656,8 @@ params: "source": "custom:hermes", "agent": "hermes", "state": "working", - "message": "running tools" + "message": "running tools", + "custom_status": "indexing" } ``` @@ -637,6 +670,9 @@ notes: - while this authority is active, the reported `agent` and `state` override heuristic display for that pane - process detection still owns pane liveness and fallback when hook authority is cleared or released - `message` is optional metadata for the reporting integration +- `custom_status` is an optional short display label such as `scheduled`, `indexing`, or `stuck` +- `custom_status` is visual-only; use `state` for semantic behavior like working or blocked +- omitting `custom_status` clears any previous custom status from this reporting source returns `ok`. @@ -916,12 +952,13 @@ example pushed `pane.agent_status_changed` event: "pane_id": "1-1", "workspace_id": "1", "agent_status": "done", - "agent": "pi" + "agent": "pi", + "custom_status": "scheduled" } } ``` -`agent` in pushed events follows the same rules as `pane_info.agent`: it may be a built-in detected name, a custom hook-reported label, or omitted. +`agent` in pushed events follows the same rules as `pane_info.agent`: it may be a built-in detected name, a custom hook-reported label, or omitted. `custom_status` may be included when the pane has hook-owned custom status metadata at the time of the semantic status transition. ## cli wrappers these commands provide the shell-facing control surface. most command groups talk to the local socket; `status client` only inspects the local executable. @@ -960,6 +997,30 @@ herdr tab rename <tab_id> <label> herdr tab close <tab_id> ``` +agent commands: + +```text +herdr agent list +herdr agent get <target> +herdr agent read <target> [--source visible|recent|recent-unwrapped] [--lines N] [--format text|ansi] [--ansi] +herdr agent send <target> <text> +herdr agent rename <target> <name>|--clear +herdr agent focus <target> +herdr agent wait <target> --status <idle|working|blocked|unknown> [--timeout MS] +herdr agent attach <target> [--takeover] +herdr agent start <name> [--cwd PATH] [--workspace ID] [--tab ID] [--split right|down] [--focus|--no-focus] -- <argv...> +``` + +agent targets accept terminal ids, unique agent names, detected/reported agent labels, and legacy pane ids. `agent list` shows terminals with explicit agent identity, detected/reported agent identity, or `agent.start` launch metadata. `pane.rename` does not make a plain terminal appear in `agent list`; use `agent.rename` for agent identity. + +terminal commands: + +```text +herdr terminal attach <terminal_id> [--takeover] +``` + +`terminal attach` is the low-level direct attach primitive. it streams the current rendered terminal state first, then live ANSI frames. direct attach has one writable input/resize owner; a second direct attach fails unless you pass `--takeover`. detach with `ctrl+b q`; send a literal `ctrl+b` with `ctrl+b ctrl+b`. + pane commands: ```text @@ -971,6 +1032,7 @@ herdr pane split <pane_id> --direction right|down [--cwd PATH] [--focus] [--no-f herdr pane close <pane_id> herdr pane send-text <pane_id> <text> herdr pane send-keys <pane_id> <key> [key ...] +herdr pane report-agent <pane_id> --source ID --agent LABEL --state idle|working|blocked|unknown [--message TEXT] [--custom-status TEXT] [--seq N] herdr pane run <pane_id> <command> ``` @@ -994,11 +1056,16 @@ herdr wait agent-status <pane_id> --status <idle|working|blocked|done|unknown> [ - `tab create` without `--label` keeps the default numbered tab naming - `tab create --label` applies the custom tab name immediately - `tab create` returns `result.tab` and `result.root_pane` +- `agent list` shows agent terminals, not arbitrary named panes +- `agent wait --status idle` is the CLI completion wait; it treats the UI-only `done` attention state as satisfying idle +- `agent focus` switches the TUI workspace/tab/pane focus; it is not direct terminal attach +- `agent attach` attaches the current terminal directly to the agent terminal stream +- `agent start <name> -- <argv...>` starts a named agent terminal and returns `result.agent` plus `result.argv` - `pane split` keeps focus where it is by default; pass `--focus` to switch to the new pane - `pane read` prints **text**, not json - `pane read --format ansi` and `pane read --ansi` print a rendered ANSI snapshot with colors/styles preserved - `pane read --source recent-unwrapped` returns recent terminal text with soft wraps joined back together -- `pane send-text`, `pane send-keys`, and `pane run` print nothing on success +- `pane send-text`, `pane send-keys`, `pane report-agent`, and `pane run` print nothing on success - list/get/create/split/wait commands print json on success - `pane run` is a convenience wrapper for `pane.send_input` with the command text followed by a real `Enter` keypress - `wait agent-status` is a cli convenience built on top of event subscriptions @@ -1017,7 +1084,13 @@ herdr pane run 1-2 "npm run dev" herdr wait output 1-2 --match "ready" --timeout 30000 ``` -wait for another agent to finish in the same user-facing sense the UI shows: +wait for an agent by name to become idle for CLI automation: + +```bash +herdr agent wait reviewer --status idle --timeout 60000 +``` + +wait for a pane-level UI attention state: ```bash herdr wait agent-status 1-1 --status done --timeout 60000 diff --git a/docs/next/CHANGELOG.md b/docs/next/CHANGELOG.md index 32148d7b..e3435397 100644 --- a/docs/next/CHANGELOG.md +++ b/docs/next/CHANGELOG.md @@ -3,17 +3,25 @@ ## Unreleased ### Added -- Added `ui.prompt_new_tab_name = false` for creating new tabs immediately with generated names instead of opening the rename dialog. -- Added optional `keys.edit_scrollback` to open the focused pane's retained scrollback in `$EDITOR` inside a temporary zoomed pane. +- Added indexed keybind families under `[keys.indexed]` for jumping directly to workspace, tab, or visible agent positions 1-9. +- Added hook-owned custom agent status labels, so integrations can show short visual states like `indexing` without changing semantic agent status. +- Added terminal-backed agent commands and socket API methods for listing, reading, sending to, renaming, focusing, waiting on, attaching to, and starting agent terminals. +- Added direct terminal attach with `herdr agent attach <target>` and `herdr terminal attach <terminal_id>`. +- Added `ui.prompt_new_tab_name = false` for creating new tabs immediately with generated names instead of opening the rename dialog. (#123) +- Added optional `keys.edit_scrollback` to open the focused pane's retained scrollback in `$EDITOR` inside a temporary zoomed pane. (#122) ### Changed - Renamed the focused pane fullscreen keybinding to `keys.zoom`; `keys.fullscreen` remains supported as a legacy alias. ### Fixed - Grok Build is now detected as `grok`, with basic working, blocked, and idle state detection. Conflicting known-agent hook labels are ignored once native foreground-process detection identifies a different known agent. (#133) -- GitHub Copilot is now correctly detected when its process name is `copilot`. -- Integration installs now respect `PI_CODING_AGENT_DIR`, `CLAUDE_CONFIG_DIR`, and `CODEX_HOME` when choosing Pi, Claude Code, and Codex config paths. -- Split pane resize hit areas no longer overlap the first content column or row, making text selection work from the start of right and bottom panes. +- Terminal cursor shapes now forward through attached clients. (#116) +- Herdr now redraws immediately when the outer terminal regains focus. +- GitHub Copilot is now correctly detected when its process name is `copilot`. (#118) +- Integration installs now respect `PI_CODING_AGENT_DIR`, `CLAUDE_CONFIG_DIR`, and `CODEX_HOME` when choosing Pi, Claude Code, and Codex config paths. (#121) +- Split pane resize hit areas no longer overlap the first content column or row, making text selection work from the start of right and bottom panes. (#120) +- Dragging text selections near pane edges now autoscrolls into scrollback, and selection state now clears correctly when switching workspaces, tabs, or panes. (#128, #129, thanks @leeeanh) +- Zoomed panes now keep their border visible in tabs that contain multiple panes. (#115) ## [0.5.9] - 2026-05-15 diff --git a/docs/next/SOCKET_API.md b/docs/next/SOCKET_API.md index e639940e..7ffb276e 100644 --- a/docs/next/SOCKET_API.md +++ b/docs/next/SOCKET_API.md @@ -166,7 +166,6 @@ for backward compatibility, requests also accept the older positional forms like "name": "reviewer", "agent": "pi", "agent_status": "working", - "custom_status": "indexing", "workspace_id": "w64e95948145ed1", "tab_id": "w64e95948145ed1:1", "pane_id": "w64e95948145ed1-1", @@ -184,7 +183,7 @@ for backward compatibility, requests also accept the older positional forms like - when a hook or plugin reports a custom agent through `pane.report_agent`, this can be any non-empty label like `hermes` - when no agent identity is known, it is omitted -`custom_status` is an optional hook-owned display label. It is present only while hook authority is active. It does not change `agent_status`, `done` semantics, waits, notifications, or workspace/tab rollup priority. +`custom_status` on `pane_info` and agent-status events is an optional hook-owned display label. It is present only while hook authority is active. It does not change `agent_status`, `done` semantics, waits, notifications, or workspace/tab rollup priority. `pane_read` responses contain objects like: |
