# Herdr — full corpus # LLM Wiki An open-source template for building LLM-powered knowledge bases, following [Andrej Karpathy's "LLM Wiki" pattern](https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f). You provide raw sources. The LLM reads them, writes structured wiki pages, cross-links everything, and maintains it over time. You never edit the wiki directly — you curate sources and ask questions. ## How It Works The system has three layers: ``` raw/ Sources you collect (articles, transcripts, notes, PDFs) wiki/ LLM-written & maintained pages (summaries, concepts, entities, syntheses) CLAUDE.md Schema that tells the LLM how to structure everything ``` Three operations drive the workflow: | Operation | Trigger | What happens | |-----------|---------|--------------| | **Ingest** | "ingest raw/my-source.txt" | LLM reads the source, creates a summary page, creates/updates concept and entity pages, adds cross-links, updates the index and log | | **Query** | Ask any question | LLM searches the wiki, synthesizes an answer with citations, optionally creates a synthesis page for novel insights | | **Lint** | "lint" or "health check" | LLM audits all pages for orphans, contradictions, missing links, incomplete sections, and low-confidence claims — fixes what it can, reports the rest | ## Quick Start 1. **Clone this repo** ```bash git clone https://github.com/YOUR_USERNAME/llm-wiki.git my-knowledge-base cd my-knowledge-base ``` 2. **Customize CLAUDE.md** for your domain - Update the Purpose section with your topic - Replace the placeholder tagging taxonomy with your own categories - Adjust confidence level descriptions if needed - Everything else (workflows, page formats, linking rules) works as-is 3. **Drop sources into `raw/`** - Text files, transcripts, articles, notes — any plain text - These are immutable once added; the LLM never modifies them 4. **Tell the LLM to ingest** ``` ingest raw/my-first-source.txt ``` The LLM will create summary pages, concept pages, entity pages, cross-links, and update the index. 5. **Ask questions** ``` What are the key differences between X and Y? ``` The LLM answers from the wiki, citing specific pages. 6. **Run health checks** ``` lint ``` The LLM audits the wiki and fixes issues. ## Directory Structure ``` . ├── CLAUDE.md # Schema — the LLM's instructions ├── raw/ # Your source documents (immutable) └── wiki/ ├── index.md # Master catalog of all pages ├── log.md # Append-only activity log ├── dashboard.md # Dataview dashboard (Obsidian) ├── analytics.md # Charts View analytics (Obsidian) ├── flashcards.md # Spaced repetition cards ├── summaries/ # One page per source document ├── concepts/ # Concept and framework pages ├── entities/ # People, tools, organizations, etc. ├── syntheses/ # Cross-cutting analyses and comparisons ├── journal/ # Research/session journal entries │ └── template.md # Journal entry template └── presentations/ # Marp slide decks ``` ## Enhancements This template includes several extras beyond the core wiki pattern: ### Dataview Dashboard (`wiki/dashboard.md`) Live queries that surface low-confidence pages, recent updates, concepts by tag, and pages with the most sources. Requires the [Dataview](https://github.com/blacksmithgu/obsidian-dataview) Obsidian plugin. ### Charts View Analytics (`wiki/analytics.md`) Visual analytics with pie charts, bar charts, and word clouds. Requires the [Charts View](https://github.com/caronchen/obsidian-chartsview-plugin) Obsidian plugin. ### Mermaid Diagrams Use Mermaid code blocks in any wiki page to create flowcharts, sequence diagrams, or concept maps. Native support in Obsidian and GitHub. ### Marp Slides (`wiki/presentations/`) Create slide decks from markdown using [Marp](https://marp.app/). Drop presentation files in this directory. ### Research Journal (`wiki/journal/`) Track your research sessions, experiments, or applied work with the included template. The LLM can reference journal entries when answering queries. ### Spaced Repetition (`wiki/flashcards.md`) Flashcards in the format used by the [Spaced Repetition](https://github.com/st3v3nmw/obsidian-spaced-repetition) Obsidian plugin. Ask the LLM to generate flashcards from any wiki page. ### MCP Server This repo works with Claude Code's MCP server capabilities. Point an MCP-compatible client at this repo and the LLM can read/write the wiki programmatically. ## Customizing for Your Domain The schema in `CLAUDE.md` is domain-agnostic. To adapt it: 1. **Purpose** — Describe your knowledge domain in one paragraph 2. **Tagging taxonomy** — Replace placeholder categories with your own (e.g., for a cooking KB: `cuisine`, `technique`, `ingredient`, `equipment`) 3. **Confidence levels** — Adjust the descriptions to match your domain's evidence standards 4. **Entity types** — Update the entity page description to match what entities mean in your domain (people, tools, companies, etc.) 5. **Journal template** — Customize `wiki/journal/template.md` for your workflow Everything else — page format, linking conventions, workflows, rules — is universal and works across domains. ## Example Domains This template works for any knowledge-intensive topic: - **Research notes** — papers, experiments, methodologies - **Book analysis** — themes, characters, author techniques - **Competitive analysis** — companies, products, market trends - **Course notes** — lectures, readings, key concepts - **Personal development** — frameworks, habits, book summaries - **Technical documentation** — APIs, architectures, design patterns - **Hobby deep-dives** — any subject you want to master ## License MIT --- title: "Knowledge Base Index" type: index updated: 2026-07-23 herdr_version: "v0.7.5" --- # Knowledge Base Index Master catalog of all wiki pages. Every page in the wiki must have an entry here. ## Concepts | Page | Tags | Confidence | Updated | |------|------|------------|---------| | [[concepts/agent-automation-and-socket-api]] | automation, agents, cli | high | 2026-07-23 | | [[concepts/agents-and-integrations]] | agents, panes, config | high | 2026-07-23 | | [[concepts/cli-reference]] | cli, automation, intermediate, advanced, foundational, well-established | high | 2026-07-23 | | [[concepts/configuration]] | config, intermediate, advanced, foundational, well-established | high | 2026-07-23 | | [[concepts/herdr-overview]] | agents, foundational, well-established, beginner | high | 2026-07-23 | | [[concepts/install-and-quickstart]] | install, beginner, foundational, well-established | high | 2026-07-23 | | [[concepts/panes-and-keyboard]] | panes, agents, beginner, intermediate, foundational, well-established | high | 2026-07-23 | | [[concepts/persistence-and-remote]] | persistence, remote, panes | high | 2026-07-23 | | [[concepts/plugins-and-marketplace]] | plugins, agents, config | high | 2026-07-23 | | [[concepts/troubleshooting]] | troubleshooting, config, install | high | 2026-07-23 | ## Entities | Page | Tags | Updated | |------|------|---------| | _(none)_ | | | ## Summaries | Page | Source | Key Topics | Created | |------|--------|------------|---------| | [[summaries/release-digest]] | `raw/github_release-v0-7-5.md` | Release Digest | 2026-07-23 | ## Syntheses | Page | Pages Compared | Created | |------|----------------|---------| | [[syntheses/issues-casebook]] | troubleshooting, agents, panes, remote, persistence, config, install | 2026-07-23 | ## Statistics - **Total pages**: 12 - **Concepts**: 10 - **Entities**: 0 - **Summaries**: 1 - **Syntheses**: 1 - **Sources ingested**: 0 - **High confidence**: 12 - **Medium confidence**: 0 - **Low confidence**: 0 --- title: "Agent Automation and the Socket API" type: concept tags: [automation, agents, cli] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_doc-docs-next-website-src-content-docs-agent-automation-mdx.md", "raw/github_doc-docs-next-website-src-content-docs-socket-api-mdx.md"] confidence: high herdr_version: "v0.7.5" --- ## Definition Herdr can be driven from scripts or from another agent, not just an interactive UI: a caller can create terminal layout, run and read raw commands, and start/prompt/wait-on recognized coding agents by name. Every layer — CLI wrappers, the agent skill, and the raw socket protocol — shares the same underlying control surface, a local newline-delimited-JSON socket (Unix domain socket, or named pipe on Windows). ## How It Works Three primitives, each with a distinct responsibility: **layout** (`workspace`/`tab`/pane topology — creates and organizes terminal locations), **pane** (controls a raw terminal: run commands, send input, read output, wait for output), and **agent** (controls a recognized coding agent by name or pane, by lifecycle state). A pane exists whether or not it holds an agent; `agent start` requires an existing shell pane and never creates/splits/moves layout itself. Creation commands return JSON; capture IDs from the response rather than 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`, `.result.root_pane`; `tab create` returns `.result.tab`/`.result.root_pane`; `pane split` returns `.result.pane`. After a `pane move`, continue from `.result.move_result.pane.pane_id` (the old id is kept only as `.result.move_result.previous_pane_id` and a wait already in progress ends with `agent_not_running`). **Starting an agent.** `--kind` selects a supported agent/executable — `pi`, `claude`, `codex`, `gemini`, `cursor`, `devin`, `agy`, `cline`, `omp`, `mastracode`, `opencode`, `copilot`, `kimi`, `kiro`, `droid`, `amp`, `grok`, `hermes`, `kilo`, `qodercli`, `maki`. The target pane must be at an available interactive shell prompt (no foreground command/editor/agent): ```bash herdr agent start reviewer --kind codex --pane "$review_pane" -- -m gpt-5.4 ``` `agent start` blocks until Herdr detects the expected agent ready for input (default 30s timeout; `--timeout` must be > 3000 and ≤ 300000 ms). Names must match `[a-z][a-z0-9_-]{0,31}` and be unique among live agents; the alias clears when the agent exits/is released/is replaced. **Choosing 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 --wait` submits immediately; from a non-working state it requires an observed lifecycle change within 5 seconds or returns `agent_prompt_stalled` (a `--timeout` ≤ 5s instead returns a plain `timeout`). It (and standalone `agent wait`) default to settling on `idle`, `done`, or `blocked`; repeat `--until` for several exact states (`--until idle --until done`), and use `--until unknown` explicitly when wanted. `idle` = ready for input and its tab has been seen; `done` = idle but not yet seen; `blocked` = Herdr recognized approval/question UI; `unknown` = present but unclassifiable, not proof of completion. ```bash herdr agent wait reviewer --until blocked --timeout 120000 herdr agent read reviewer --source recent-unwrapped --lines 80 herdr agent send-keys reviewer esc ``` **Known caveat — alternate screen.** Full-screen agents (Claude Code, OpenCode) may render on the terminal's alternate screen; those rows never enter Herdr's host scrollback, so raising `--lines` won't recover missing history once it's gone. Workarounds: ask for concise responses, enlarge the pane/shrink the font, use `--source visible` after scrolling inside the agent, or as a last resort ask the agent to write its full response to a temp Markdown file and read that file directly (don't request file output in the initial prompt). **Raw socket API.** Sits below CLI wrappers and the agent skill for custom tools, protocol clients, and long-lived event subscribers. Method names use dot notation grouped by area: `server.*`, `notification.show`, `client.window_title.*`, `session.snapshot`, `workspace.*`, `worktree.*`, `tab.*`, `pane.*` (including `pane.report_agent`, `pane.report_agent_session`, `pane.report_metadata`, `pane.graphics.*`), `popup.close`, `layout.export`/`layout.apply`/`layout.set_split_ratio`, `agent.*` (including `agent.view.set`/`clear`, `agent.explain`), `events.subscribe`/`events.wait`, `integration.install`/`uninstall`, and `plugin.*`. One request per line, response echoes the same `id`: ```json {"id":"req_1","method":"ping","params":{}} {"id":"req_1","result":{"type":"pong"}} ``` Print the bundled protocol schema with `herdr api schema` (`--json` for the full JSON Schema, `--output PATH` to save it), and print a live session bootstrap with `herdr api snapshot`. Socket path resolution order: explicit CLI `--session ` → `HERDR_SOCKET_PATH` → `HERDR_SESSION=` → default session socket, at `~/.config/herdr/herdr.sock` (or `~/.config/herdr/sessions//herdr.sock` for named sessions). Prefer `HERDR_BIN_PATH` + CLI wrappers from plugins for cross-platform portability; use the raw socket only for protocol clients. ## Key Parameters - `--kind` — agent executable to launch (`claude`, `codex`, `gemini`, etc.); args after `--` pass through unchanged. - `--until` (repeatable) — exact settle states for `agent wait`/`agent prompt --wait`. - `--no-focus` — background work without stealing UI focus. - `--lines` / `--source` on `pane read`/`agent read` — `visible`, `recent`, `recent-unwrapped`, `detection`. - `pane.report_agent` / `pane.report_agent_session` / `pane.report_metadata` — custom state vs. session vs. display-only reporting. ## When To Use Use `pane run`/`pane wait-output` for ordinary processes (tests, servers, CI watchers) where lifecycle semantics don't apply. Use the `agent.*` surface specifically when Herdr needs to understand which agent is running and whether it's `working`/`blocked`/`done`/`idle`/`unknown` — e.g., one agent orchestrating helper agents in sibling panes. Reach past the CLI to the raw socket only when you need direct request/response control, event subscriptions, or you're building a protocol client rather than a shell script. ## Risks & Pitfalls - Alternate-screen agents silently drop scrollback outside Herdr's host buffer — `--lines` cannot recreate it once gone. - `agent_prompt_stalled` and `agent_not_running` are real failure signals from pane moves and non-advancing lifecycle — check for them rather than assuming a timeout. - Wait commands have no default timeout and can block indefinitely; CLI server errors are JSON on stderr with exit status 1, syntax errors exit status 2. - `pane.send_keys`/`pane.send_input.keys` accept Herdr key-combo strings but not `prefix+` binding strings. ## Related Concepts - [[concepts/agents-and-integrations]] — the lifecycle-state model (`idle`/`working`/`blocked`/`done`/`unknown`) that waits and prompts observe. - [[concepts/plugins-and-marketplace]] — the agent skill and plugins both call back through this same CLI/socket surface. - [[concepts/persistence-and-remote]] — terminal session observe/control commands used for scripted remote bridges. ## Sources - raw/github_doc-docs-next-website-src-content-docs-agent-automation-mdx.md - raw/github_doc-docs-next-website-src-content-docs-socket-api-mdx.md --- title: "Agents and Integrations" type: concept tags: [agents, panes, config] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_doc-docs-next-website-src-content-docs-agents-mdx.md", "raw/github_doc-docs-next-website-src-content-docs-integrations-mdx.md"] confidence: high herdr_version: "v0.7.5" --- ## Definition Herdr detects coding agents running inside its terminal panes and rolls their lifecycle state (`idle`, `working`, `blocked`, `done`, `unknown`) up to tabs and workspaces so a user can see, at a glance, which project needs attention. Detection works out of the box for a long list of agents; installing an official **integration** for a given agent adds hook- or plugin-based reporting on top of that baseline detection, either for richer session identity (restore) or for authoritative lifecycle state, or both. ## How It Works Herdr first identifies the foreground process in a pane, then applies one status authority per pane: - **Lifecycle authority (hook/plugin installed and reporting):** Pi, OMP, Kimi Code CLI, OpenCode, Kilo Code CLI, Hermes Agent, and MastraCode can author `idle`, `working`, and `blocked` directly through installed hooks or plugins. When one of these is installed and actively reporting for a pane, Herdr does **not** also run screen-manifest detection for that same authority, to avoid two competing sources of truth. - **Session-identity only:** Claude Code, Codex, GitHub Copilot CLI, Devin CLI, Droid, Qoder CLI, and Cursor Agent CLI integrations report native session references for restore, but their hooks don't cover the whole lifecycle (they can miss permission results, escape interrupts, or other transitions). For these, Herdr still uses screen-manifest detection for state. - **Screen manifest only (no integration, or agent has none):** Amp, Grok CLI, Antigravity CLI, Kiro CLI, and Maki are detected via screen manifest with no integration role at all. Herdr reads the live bottom-buffer screen snapshot (not the scrolled-back viewport) and evaluates TOML manifests against it to classify state; manifests can also match terminal title/OSC progress sequences as extra evidence. Gemini CLI and Cline are detected but "less thoroughly tested." Bundled detection manifests live inside the Herdr binary. Herdr also checks herdr.dev for remote manifest updates and applies them automatically without a restart; set `[update] manifest_check = false` to disable that background check. Local overrides always win and live at: ```text ~/.config/herdr/agent-detection/.toml ``` Without a local override, Herdr uses the newer compatible manifest between the cached remote manifest and the one bundled in the running binary. Run `herdr server update-agent-manifests` to fetch updates immediately and reload the running server, or `herdr server reload-agent-manifests` after manually editing a local override. Adding support for a brand-new agent (not just patching rules for a known one) still requires a Herdr binary update. `blocked` detection is deliberately strict for screen-manifest agents: Herdr only marks `blocked` when the snapshot matches known approval/question/permission UI. If nothing matches for a known agent, Herdr falls back to `idle`, labeled `default_known_agent_idle_fallback` in explain output — so an unfamiliar prompt shape may show `idle` until Herdr learns it. ## Key Parameters - **Install/uninstall an integration:** ```bash herdr integration install claude herdr integration status herdr integration uninstall claude ``` Supported integration names: `pi`, `omp`, `claude`, `codex`, `copilot`, `devin`, `droid`, `kimi`, `opencode`, `kilo`, `hermes`, `qodercli`, `cursor`, `mastracode`. - **Minimum integration versions for native session restore:** Pi `2`, OMP `3`, Claude Code `6`, Codex `5`, Copilot `2`, Devin `2`, Droid `2`, Kimi `3`, Qoder `2`, Cursor `1`, OpenCode `5`, Kilo `1`, Hermes `2`, MastraCode `1`. Check with `herdr integration status`. - **Diagnose a wrong status:** ```bash herdr agent explain herdr agent explain --file screen.txt --agent codex --json ``` - **VMs/sandboxes hiding the real agent process:** set `HERDR_AGENT=` on the wrapper command, e.g. `HERDR_AGENT=claude fence -- claude` (Linux) or `HERDR_AGENT=claude nono run --profile claude-code -- claude` (macOS). Scope this to the foreground process; don't export it globally. - **Custom/manual state and display:** ```bash herdr pane report-agent w1:p1 --source custom:indexer --agent docs-bot --state working herdr pane report-metadata w1:p1 --source custom:indexer-display --token summary=indexing ``` - **Rename and attach:** ```bash herdr agent rename w1:p1 reviewer herdr agent attach reviewer ``` ## When To Use Install an integration when you want native session restore after a Herdr server restart, or when you want an agent's own hook/plugin (not Herdr's screen scraping) to author lifecycle state. Rely on plain screen-manifest detection for agents with no integration, or when you don't want to modify that agent's config files. Use `herdr agent explain` any time a pane shows a state that looks wrong before assuming it's a bug — it is often an unmatched manifest rule falling back to `idle`. ## Risks & Pitfalls - Herdr running inside tmux as the outer environment does not see into a tmux session launched *inside* a Herdr pane — if a shell framework auto-enters tmux there, Herdr sees `tmux` as the pane process instead of the real agent. - Screen-manifest `blocked` detection is strict by design; new/unfamiliar agent prompt shapes default to `idle`, not `blocked`, until Herdr learns them — this is a visibility issue only, not a safety one. - Custom `report-agent`/`report-metadata` state is display- and semantics-layered separately: `state` drives waits/notifications/rollups, while `summary` tokens and state labels are display-only. ## Related Concepts - [[concepts/persistence-and-remote]] — what native session restore (built on integrations) actually preserves across a server restart. - [[concepts/agent-automation-and-socket-api]] — scripting agent start/prompt/wait using the identity and state this page describes. - [[concepts/plugins-and-marketplace]] — OpenCode/Kilo integrations ship as plugins; Herdr's own agent skill is a separate mechanism for agents *using* Herdr. - [[concepts/troubleshooting]] — diagnosing stale sessions and detection problems. ## Sources - raw/github_doc-docs-next-website-src-content-docs-agents-mdx.md - raw/github_doc-docs-next-website-src-content-docs-integrations-mdx.md --- title: "CLI Reference" type: concept tags: [cli, automation, intermediate, advanced, foundational, well-established] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_doc-docs-next-website-src-content-docs-cli-reference-mdx.md"] confidence: high herdr_version: v0.7.5 --- ## Definition The `herdr` CLI talks to the running server over the same local socket API used by integrations and agents. Most commands print JSON responses, making them suitable for deterministic scripted automation. This page catalogs the full documented command surface: launch/status, sessions, workspaces, worktrees, tabs, panes, agents, direct terminal attach, output waits, integrations, and plugins. ## How It Works **Launch and status:** ```bash herdr # launch or attach to the default session herdr --session work # launch or attach to a named session herdr --remote workbox # attach through SSH, using local keybindings herdr --remote workbox --remote-keybindings server herdr --remote workbox --handoff herdr --no-session # single-process escape hatch herdr --default-config # print default config herdr update # download and install from the configured channel herdr update --handoff # opt into live handoff for supported running servers herdr completion zsh # generate a zsh completion script herdr channel show # print stable or preview herdr channel set preview # opt into preview builds herdr channel set stable # return Linux/macOS direct installs to stable herdr --version # print version ``` Status: `herdr status`, `herdr status server`, `herdr status client`. API schema: `herdr api schema`, `herdr api schema --json`, `herdr api schema --output herdr-api.schema.json` — prints a summary or the full JSON Schema of the socket protocol bundled with the installed binary. **Shell completions:** ```bash herdr completion zsh herdr completions zsh herdr completion bash herdr completion fish herdr completion powershell herdr completion elvish ``` `completion` prints to stdout; `completions` is an alias. Temporary zsh session: `source <(herdr completion zsh)`. Persistent zsh setup: `mkdir -p ~/.zfunc && herdr completion zsh > ~/.zfunc/_herdr`, then ensure `.zshrc` contains `fpath=(~/.zfunc $fpath)`, `autoload -Uz compinit`, `compinit`. **Server:** ```bash herdr server herdr server stop herdr server reload-config herdr server agent-manifests [--json] herdr server update-agent-manifests [--json] herdr server reload-agent-manifests ``` `herdr server` runs the headless server explicitly (supervised/service setups). `reload-config` applies reloadable settings without restarting panes. `agent-manifests` shows active agent detection manifest sources, cached remote versions, and last update results. `update-agent-manifests` fetches remote manifest updates immediately and reloads them. `reload-agent-manifests` reloads detection manifests after local override edits. **Notifications:** ```bash herdr notification show [--body TEXT] [--position top-left|top-right|bottom-left|bottom-right] [--sound none|done|request] ``` Uses the configured `[ui.toast]` delivery; `--position` only affects in-app toasts; `--sound` defaults to `none`. **Sessions:** ```bash herdr session list [--json] herdr session attach <name> herdr session stop <name> [--json] herdr session delete <name> [--json] ``` Use `default` as the session name to stop the default session explicitly. **Workspaces:** ```bash herdr workspace list herdr workspace create [--cwd PATH] [--label TEXT] [--env KEY=VALUE] [--focus] [--no-focus] herdr workspace get <workspace_id> herdr workspace focus <workspace_id> herdr workspace rename <workspace_id> <label> herdr workspace report-metadata <workspace_id> --source ID [--token NAME=VALUE] [--clear-token NAME] [--seq N] [--ttl-ms N] herdr workspace close <workspace_id> ``` Example creating without stealing focus: `herdr workspace create --cwd ~/project --label api --no-focus`. Creating a workspace also creates its first tab and root pane; the JSON response exposes `.result.workspace.workspace_id`, `.result.tab.tab_id`, `.result.root_pane.pane_id`. **Worktrees:** ```bash herdr worktree list [--workspace ID | --cwd PATH] [--json] herdr worktree create [--workspace ID | --cwd PATH] [--branch NAME] [--base REF] [--path PATH] [--label TEXT] [--focus] [--no-focus] [--json] herdr worktree open [--workspace ID | --cwd PATH] (--path PATH | --branch NAME) [--label TEXT] [--focus] [--no-focus] [--json] herdr worktree remove --workspace ID [--force] [--json] ``` `worktree create` creates a Git worktree checkout, opens it as a workspace grouped with the parent repo workspace; with `--branch` naming an existing local branch it checks it out, otherwise creates the branch from `--base` or `HEAD`. Without `--path`, checkout lands under `<worktrees.directory>/<repo>/<branch-slug>`. `workspace close` closes Herdr state only; `worktree remove` is the explicit deletion path (`git worktree remove`, never deletes the branch, requires `--force` on a dirty checkout). **Tabs:** ```bash herdr tab list [--workspace <workspace_id>] herdr tab create [--workspace <workspace_id>] [--cwd PATH] [--label TEXT] [--env KEY=VALUE] [--focus] [--no-focus] herdr tab get <tab_id> herdr tab focus <tab_id> herdr tab rename <tab_id> <label> herdr tab close <tab_id> ``` Without `--workspace`, `tab create` uses the active workspace and fails if none exists; JSON response exposes `.result.tab.tab_id` and `.result.root_pane.pane_id`. Workspace/tab creation and pane splitting leave focus unchanged by default (`--focus` selects the new layout, `--no-focus` is the explicit default). Without `--cwd`, new terminals follow `terminal.new_cwd` policy. Each `--env KEY=VALUE` adds/replaces that variable in the new root shell. **Panes:** ```bash herdr pane list [--workspace <workspace_id>] herdr pane current [--pane ID|--current] herdr pane get <pane_id> herdr pane layout [--pane ID|--current] herdr pane process-info [--pane ID|--current] herdr pane neighbor --direction left|right|up|down [--pane ID|--current] herdr pane edges [--pane ID|--current] herdr pane focus --direction left|right|up|down [--pane ID|--current] herdr pane resize --direction left|right|up|down [--amount FLOAT] [--pane ID|--current] herdr pane zoom [<pane_id>|--pane ID|--current] [--toggle|--on|--off] herdr pane rename <pane_id> <label>|--clear herdr pane split [<pane_id>|--pane ID|--current] --direction right|down [--ratio FLOAT] [--cwd PATH] [--env KEY=VALUE] [--focus] [--no-focus] herdr pane swap --direction left|right|up|down [--pane ID|--current] herdr pane swap --source-pane ID --target-pane ID herdr pane move <pane_id> --tab <tab_id> --split right|down [--target-pane ID] [--ratio FLOAT] [--focus|--no-focus] herdr pane move <pane_id> --new-tab [--workspace ID] [--label TEXT] [--focus|--no-focus] herdr pane move <pane_id> --new-workspace [--label TEXT] [--tab-label TEXT] [--focus|--no-focus] herdr pane close <pane_id> ``` For commands accepting `--current`, Herdr uses the calling pane's `HERDR_PANE_ID` when the command runs inside a Herdr pane. Split response exposes the new pane ID as `.result.pane.pane_id`. After `pane move`, use `.result.move_result.pane.pane_id`; a cross-workspace move changes the workspace-qualified pane ID (prior value stays at `.result.move_result.previous_pane_id`); the running process keeps its launch-time `HERDR_PANE_ID`/`HERDR_TAB_ID`/`HERDR_WORKSPACE_ID` and the old pane ID remains a resolvable alias, so `--current` keeps working and a live agent name follows the terminal across the move. Read output: ```bash herdr pane read <pane_id> [--source visible|recent|recent-unwrapped|detection] [--lines N] [--format text|ansi] [--ansi] [--raw] herdr pane read <pane_id> --source visible --ansi herdr pane read <pane_id> --source recent-unwrapped --lines 120 ``` Prints UTF-8 terminal text; ANSI stripped by default (`--format ansi`/`--ansi` preserves it where the source has styling). `detection` is always plain text. For recent sources, `--lines N` selects the last N rendered rows before optional unwrapping (default 80 rows). For `visible`/`detection`, omitting `--lines` returns the full snapshot; specifying it keeps the last N newline-delimited lines. `agent read` behaves the same way. Send input: ```bash herdr pane send-text <pane_id> <text> herdr pane send-keys <pane_id> <key> [key ...] herdr pane run <pane_id> <command> ``` `<key>` syntax: plain printable keys (`a`), specials (`enter`, `tab`, `esc`, `backspace`, `left`, `right`, `up`, `down`), modifier chords (`ctrl+h`, `control+j`, `alt+x`, `shift+tab`), function keys (`f1`), named punctuation (`minus`, `plus`, `backtick`). Legacy `C-c`/`c-c` alias `ctrl+c`; `esc` is canonical, `escape` also accepted. `pane run` honors live bracketed-paste mode and submits text plus Enter atomically — prefer it over `send-text` + `send-keys Enter` for commands. Report agent state from custom hooks: ```bash herdr pane report-agent <pane_id> \ --source ID \ --agent LABEL \ --state idle|working|blocked|unknown \ [--message TEXT] \ [--seq N] \ [--agent-session-id ID] \ [--agent-session-path PATH] herdr pane report-agent-session <pane_id> \ --source ID \ --agent LABEL \ [--seq N] \ [--agent-session-id ID] \ [--agent-session-path PATH] \ [--session-start-source SOURCE] herdr pane release-agent <pane_id> \ --source ID \ --agent LABEL \ [--seq N] ``` `report-agent-session` updates native session identity without lifecycle state; `release-agent` ends that source's lifecycle authority when its process exits. `pane get`/`pane list`/`agent get`/`agent list` include a read-only `agent_session` object when a native session reference has been reported, and include `foreground_cwd` when the foreground process's cwd is resolvable (`cwd` remains the pane/workspace cwd used for labels/follow-cwd). `pane get`/`pane list` include `scroll` when scroll metrics are available (`scroll.offset_from_bottom == 0` means at bottom). Report display-only metadata: ```bash herdr pane report-metadata <pane_id> \ --source ID \ [--agent LABEL] \ [--applies-to-source ID] \ [--title TEXT|--clear-title] \ [--display-agent TEXT|--clear-display-agent] \ [--state-label STATUS=TEXT] \ [--clear-state-labels] \ [--token NAME=VALUE] \ [--clear-token NAME] \ [--seq N] \ [--ttl-ms N] ``` `STATUS` is `idle`, `working`, `blocked`, `done`, or `unknown`. `--agent`/`--applies-to-source` guard only `--title`/`--display-agent`/`--state-label` (not token patches). Text is normalized (trimmed, control chars stripped) and capped at 80 characters for `--title`, `--display-agent`, each `--state-label`, and token values; empty normalized token values clear that key. `--token`/`--clear-token` patch/remove one named value; unmentioned tokens stay unchanged (available to sidebar rows as `$name` per [[concepts/configuration]]). `--source`/`--applies-to-source` must be ≤80 ASCII chars (letters, digits, colon, dot, underscore, hyphen); `--ttl-ms` must be 1–86400000 ms (omit for persist-until-replaced/cleared/pane-closed); `--seq` lets Herdr ignore stale reports from the same source. A pane/workspace accepts sequenced token reports from at most 32 distinct sources over its lifetime (clearing/expiry does not free slots). **Agents** (see [[concepts/agent-automation-and-socket-api]] for orchestration examples): ```bash herdr agent list herdr agent get <target> herdr agent read <target> [--source visible|recent|recent-unwrapped|detection] [--lines N] [--format text|ansi] [--ansi] herdr agent send-keys <target> <key> [key ...] herdr agent prompt <target> <text> [--wait] [--until STATUS]... [--timeout MS] herdr agent rename <target> <name>|--clear herdr agent focus <target> herdr agent wait <target> [--until STATUS]... [--timeout MS] herdr agent attach <target> [--takeover] herdr agent start <name> --kind KIND --pane ID [--timeout MS] [-- <agent-args...>] herdr agent explain <target> [--json|--verbose] herdr agent explain --file PATH --agent LABEL [--json|--verbose] ``` Agent targets are a unique live agent name or the pane ID hosting it (terminal IDs and bare agent-kind labels are not valid targets). `agent start` activates an existing available shell pane whose interactive shell owns the foreground with nothing else running; topology must be created separately. Names must match `[a-z][a-z0-9_-]{0,31}` and are unique among live agents. Supported `--kind` values: `pi`, `claude`, `codex`, `gemini`, `cursor`, `devin`, `agy`, `cline`, `omp`, `mastracode`, `opencode`, `copilot`, `kimi`, `kiro`, `droid`, `amp`, `grok`, `hermes`, `kilo`, `qodercli`, `maki`. A name follows the pane occupant and clears when that agent exits/is released/is replaced (temporary detection uncertainty does not clear it). `agent start` returns only once the expected agent owns the terminal and is ready for input; default startup timeout 30000 ms (explicit values must be >3000 and ≤300000). `agent prompt` honors live bracketed-paste mode and submits text + encoded Enter atomically, even mid-work. With `--wait`, a prompt sent from a non-working state must show an observed lifecycle change within five seconds or Herdr returns `agent_prompt_stalled`; a caller timeout ≤5s keeps the normal `timeout` error. After activity is observed, it waits for the first requested settled status (does not track individual turns — if already working, completion of that active turn may satisfy the wait). `--until` narrows matched states and requires `--wait`. Standalone `agent wait` returns immediately if the current status already matches. Both default to `idle`, `done`, or `blocked`; use `--until unknown` explicitly when needed. `idle` = ready for input after its tab has been seen in the focused UI; `done` = same underlying idle state after unseen background work completes. Focusing the tab (or `pane focus`/`agent focus`) marks it seen; CLI reads do not. `blocked` = Herdr recognized an approval/question UI. `unknown` = present but not confidently classified (not a claim about success). `agent send-keys` sends logical keys (`enter`, `up`, `esc`, `ctrl+c`) validated before any bytes are written. `agent rename` names an already-detected agent. `agent explain` classifies the same bottom-buffer detection snapshot used by screen detection, live against the server's active manifest cache (restart/hand off to an updated server after upgrading before using live explain, since it uses the `agent.explain` socket method). `--file PATH --agent LABEL` explains a saved fixture locally. Default output: agent, final state, manifest source/version, matched rule with region evidence, and fallback/skip/warning reasons. `--verbose` adds visible evidence flags, cached remote version, local override shadowing, remote update status, and the full evaluated-rules list. `--json` for issue reports/tests. Use `pane send-text`, `pane send-keys`, `pane run`, and `terminal attach` for ordinary terminals/servers/tests/shells or low-level terminal control; use `pane run` to submit a command with Enter. **Direct terminal attach:** ```bash herdr terminal attach <terminal_id> [--takeover] herdr terminal session control <target> [--takeover] [--cols N] [--rows N] herdr terminal session observe <target> [--cols N] [--rows N] herdr terminal title set <title> herdr terminal title clear ``` Detach from direct attach with `ctrl+b q`; send literal `ctrl+b` with `ctrl+b ctrl+b`. `terminal session control` opens a writable live terminal stream for a pane/terminal/agent target, printing newline-delimited `terminal.frame`/`terminal.closed` records, and reads newline-delimited JSON commands on stdin (`terminal.input`, `terminal.resize`, `terminal.scroll`, `terminal.release`); one controller owns a terminal at a time, `--takeover` replaces it. `terminal session observe` opens a read-only stream (base64-encoded ANSI bytes in `terminal.frame`, then `terminal.closed`); multiple observers can watch without input/resize/scroll/takeover authority. `terminal title clear` restores Herdr's default outer terminal window title. **Output waits:** ```bash herdr pane wait-output <pane_id> (--match <text> | --regex <pattern>) [--source visible|recent|recent-unwrapped] [--lines N] [--timeout MS] [--raw] ``` Use `pane wait-output` for normal commands/servers, `agent wait` for coding agents. `pane wait-output` checks the selected snapshot immediately (including pre-existing output), then polls until it matches. Default source `recent` (unwrapped recent output from the latest 80 rendered rows); `--lines` changes the row limit. `--match` finds a literal substring on one line; `--regex` uses Rust regex syntax, matching one line at a time. `pane wait-output`, `agent wait`, and `agent prompt --wait` wait indefinitely when `--timeout` is omitted; a timeout or server error is emitted as JSON on stderr with exit status 1, while CLI usage errors exit status 2. **Integrations:** ```bash herdr integration install pi herdr integration install omp herdr integration install claude herdr integration install codex herdr integration install copilot herdr integration install devin herdr integration install droid herdr integration install kimi herdr integration install opencode herdr integration install kilo herdr integration install hermes herdr integration install qodercli herdr integration install cursor herdr integration install mastracode herdr integration uninstall pi herdr integration uninstall omp herdr integration uninstall claude herdr integration uninstall codex herdr integration uninstall copilot herdr integration uninstall devin herdr integration uninstall droid herdr integration uninstall kimi herdr integration uninstall opencode herdr integration uninstall kilo herdr integration uninstall hermes herdr integration uninstall qodercli herdr integration uninstall cursor herdr integration uninstall mastracode herdr integration status [--outdated-only] ``` **Plugins.** A plugin is a manifest plus out-of-process commands; Herdr owns the host surface, plugins own their implementation language. ```bash herdr plugin install <owner>/<repo>[/subdir...] [--ref REF] [--yes] herdr plugin list [--plugin ID] [--json] herdr plugin uninstall <plugin_id|owner/repo[/subdir...]> herdr plugin enable <plugin_id> herdr plugin disable <plugin_id> ``` `plugin install` accepts GitHub shorthand only (e.g. `ogulcancelik/herdr-plugin-examples/worktree-bootstrap`), uses `git`, shows a trust preview in interactive terminals, runs supported manifest build commands, and stores GitHub installs in a Herdr-managed directory (`--yes` for noninteractive). Reinstalling a GitHub-managed plugin replaces that checkout; installing over a locally linked plugin is refused. Manifests must declare `min_herdr_version`; install/link fail if the plugin needs a newer Herdr binary. `plugin list` is human-readable by default, `--json` for the raw API response. Plugin install/enabled state is global to the current user — available with the same state in every session immediately. Local development: ```bash herdr plugin link <path> [--disabled] herdr plugin unlink <plugin_id> ``` `plugin link` accepts a plugin directory containing `herdr-plugin.toml` or a direct manifest path — the right command while authoring/testing from a local checkout. `plugin unlink` unregisters and leaves files alone. `plugin uninstall` unregisters and also removes Herdr-managed GitHub checkout files (accepts plugin id or `owner/repo[/subdir...]`). Actions/event hooks/panes/link handlers are declared in the manifest; runtime action registration is not part of v1. Config directory: `herdr plugin config-dir <plugin_id>` prints (and creates/seeds from legacy locations if needed) the plugin's config directory — use it for `.env` files and user-editable config separate from the managed checkout. Actions: ```bash herdr plugin action list [--plugin ID] herdr plugin action invoke <action_id> [--plugin ID] ``` `plugin action invoke` starts the manifest command for an installed/enabled/platform-compatible action and prints the started command log record. Use the qualified id (`plugin.id.action`) when more than one plugin shares an action id (local action ids cannot contain dots, so qualified ids stay unambiguous). Logs: `herdr plugin log list [--plugin ID] [--limit N]`. Managed terminal panes: ```bash herdr plugin pane open --plugin ID --entrypoint ID [--placement overlay|popup|split|tab|zoomed] [--width SIZE] [--height SIZE] [--workspace ID] [--target-pane PANE] [--direction right|down] [--cwd PATH] [--env KEY=VALUE] [--focus|--no-focus] herdr plugin pane focus <pane_id> herdr plugin pane close <pane_id> ``` `plugin pane open` requires the plugin linked/enabled/platform-compatible; starts a manifest-declared `[[panes]]` command as a managed terminal pane. Default placement `overlay` (temporary zoomed overlay); can also be a split, new tab, zoomed pane, or session-modal `popup` (does not change tab layout). `--width`/`--height` are cells or percentages (e.g. `80%`); omitted defaults to half the terminal, clamped to the popup minimum. A popup is not a Herdr pane — no `HERDR_PANE_ID`, no pane/agent API participation. Native non-terminal plugin panes are a later surface. `--env KEY=VALUE` (repeatable) applies only to the newly launched process; Herdr-managed vars (`HERDR_SOCKET_PATH`, `HERDR_BIN_PATH`, `HERDR_ENV`, `HERDR_WORKSPACE_ID`, `HERDR_TAB_ID`, `HERDR_PANE_ID`, `HERDR_PLUGIN_ID`, `HERDR_PLUGIN_ROOT`, `HERDR_PLUGIN_CONFIG_DIR`, `HERDR_PLUGIN_STATE_DIR`, `HERDR_PLUGIN_ENTRYPOINT_ID`, `HERDR_PLUGIN_CONTEXT_JSON`) stay authoritative over caller-provided env on conflict. **Read sources** (for reads generally): | Source | Meaning | | --- | --- | | `visible` | Current rendered screen. Best for UI feedback loops. | | `recent` | Recent scrollback with terminal wrapping. | | `recent-unwrapped` | Recent scrollback without soft wrapping. Best for logs. | | `detection` | Bottom-buffer snapshot used by agent screen detection. | For `pane wait-output` only, both `recent` and `recent-unwrapped` search the unwrapped recent snapshot (`recent` remains the default spelling). **Environment variables:** | Variable | Purpose | | --- | --- | | `HERDR_CONFIG_PATH` | Override the config file path. | | `HERDR_SESSION` | Select a named session for CLI commands. | | `HERDR_SOCKET_PATH` | Low-level socket path override. | | `HERDR_ENV` | Set to `1` inside Herdr-managed pane processes. | | `HERDR_PANE_ID` | Public pane id for the running pane process. | | `HERDR_TAB_ID` | Public tab id for the running pane process. | | `HERDR_WORKSPACE_ID` | Public workspace id for the running pane process. | | `HERDR_LOG` | Set log filter, for example `HERDR_LOG=herdr=debug`. | | `HERDR_DISABLE_SOUND` | Disable sound playback even when sound notifications are enabled. | ## Key Parameters - **Target resolution** — pane commands take a `pane_id` or `--current`/`--pane ID`; agent commands take a "target" that is a live agent name or the hosting pane ID. - **`--json` flags** — sprinkled across `session`, `worktree`, `plugin list`, `agent explain` etc. for machine-readable output versus human-readable default. - **Wait semantics** — `--wait`, `--until STATUS`, `--timeout MS` govern `agent prompt`, `agent wait`, and `pane wait-output`; omitted timeout means indefinite wait, timeout/server error exit 1, usage error exit 2. - **`--seq` / `--ttl-ms`** — sequencing and expiry controls shared by the `report-agent*`/`report-metadata` command family. ## When To Use Reach for the CLI whenever you want deterministic, scriptable control instead of manual pane interaction: spawning workspaces/tabs/panes for a fixed project layout, writing custom `$name` sidebar metadata reporters, driving an agent from another agent or script (`agent prompt --wait`, `agent wait`), or diagnosing detection with `agent explain`. Prefer `pane run`/`agent prompt` (atomic submit) over manual `send-text`+`send-keys enter` sequences for reliability, especially under bracketed-paste mode. ## Risks & Pitfalls - `agent send-keys`/`pane send-keys` are logical key sends, not atomic submits — for submitting a full command or prompt, prefer `pane run` or `agent prompt`, which handle bracketed-paste and Enter atomically. - `agent explain`'s live mode reflects the server's active manifest cache — after upgrading Herdr, restart or hand off to an updated server before trusting live `agent explain` output. - Cross-workspace `pane move` changes the workspace-qualified pane ID; scripts holding onto the old ID should switch to `.result.move_result.pane.pane_id` (the previous value is preserved only at `.result.move_result.previous_pane_id`). - `worktree remove`/`workspace close` are easy to conflate: `workspace close` never touches the checkout or branch, only `worktree remove` deletes the checkout (and only with `--force` on a dirty tree), and neither ever deletes the branch. - A pane/workspace only accepts sequenced token reports from 32 distinct `--source` values over its lifetime; clearing/expiry does not free a slot, so unbounded dynamically-generated source IDs will eventually be rejected. ## Related Concepts - [[concepts/herdr-overview]] — the workspace/tab/pane/agent/session model these commands operate on. - [[concepts/configuration]] — config keys referenced by CLI behavior (`terminal.new_cwd`, `[ui.toast]`, `[worktrees] directory`, sidebar `$name` tokens). - [[concepts/panes-and-keyboard]] — `herdr terminal attach`, detach key (`ctrl+b q`), and the pane model in human terms. - [[concepts/install-and-quickstart]] — `herdr update`, `herdr channel`, `herdr completion`, `herdr --default-config` in the install/update lifecycle. - [[concepts/agent-automation-and-socket-api]] — deeper orchestration patterns built on `agent start`/`prompt`/`wait`/`send-keys`. - [[concepts/agents-and-integrations]] — the `--kind` values and `herdr integration install/uninstall` targets. - [[concepts/plugins-and-marketplace]] — `herdr plugin install/link/action/pane` command family in context. - [[concepts/persistence-and-remote]] — `herdr session`, `herdr --remote`, `herdr server stop` in the persistence/remote workflow. - [[concepts/troubleshooting]] — using `herdr status`, `herdr server agent-manifests`, and `agent explain` to diagnose issues. ## Sources - raw/github_doc-docs-next-website-src-content-docs-cli-reference-mdx.md <!-- ===== herdr/wiki/concepts/configuration.md ===== --> --- title: "Configuration" type: concept tags: [config, intermediate, advanced, foundational, well-established] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_doc-docs-next-website-src-content-docs-configuration-mdx.md", "raw/github_doc-docs-next-website-src-content-docs-config-reference-mdx.md"] confidence: high herdr_version: v0.7.5 --- ## Definition Herdr works fully without a config file; you add `config.toml` only when you want custom keys, themes, sidebar layouts, notifications, or advanced behavior. This page covers the config file's location, reload behavior, and every documented config area; the canonical per-key reference (types, defaults, allowed values) lives in the rendered `<ConfigReference />` component on the docs site, which this KB does not mirror key-by-key — use `herdr --default-config` as the authoritative live listing. ## How It Works **Config file location:** ```text Linux and macOS: ~/.config/herdr/config.toml Windows: %APPDATA%\herdr\config.toml ``` Run `herdr --help` to see the resolved config path for your system. Print the full default config with: ```bash herdr --default-config ``` Save it as a starting point: ```bash herdr --default-config > ~/.config/herdr/config.toml ``` If a config value is invalid, Herdr falls back to a safe default and shows a startup warning. Herdr shows first-run onboarding when `onboarding` is missing or `true`; continuing from onboarding writes `onboarding = false` and opens settings on the integrations tab: ```toml onboarding = false ``` **Reload.** After editing `config.toml` on a running server: ```bash herdr server reload-config ``` (or choose "reload config" from Herdr's global menu). Reload applies most UI settings without restarting panes; startup-only settings still need a restart. **Terminal defaults.** Executable used for new interactive panes: ```toml [terminal] default_shell = "nu" ``` Unset/empty falls back to `$SHELL`, then `/bin/sh` on Unix or PowerShell on Windows. This is an executable name/path, not a command line; existing panes keep their shell until recreated. Custom command keybinding strings run through `/bin/sh -c` (pane commands) or `/bin/sh -lc` (detached commands) on Unix, and `cmd.exe /d /c` on Windows. Shell startup mode: ```toml [terminal] shell_mode = "auto" ``` `"auto"` starts login shells on macOS (so `/usr/libexec/path_helper` and Homebrew init run) but keeps non-login behavior elsewhere; `"login"` forces login-shell startup; `"non_login"` opts out. New-pane working directory policy: ```toml [terminal] new_cwd = "follow" ``` `"follow"` inherits the source pane/workspace (falling back to `$HOME` with no source workspace); `"home"` always starts in `$HOME`; `"current"` uses Herdr's process directory; or set a fixed path such as `"~/Projects"`. Explicit `--cwd` from the CLI/socket API always takes precedence. **Worktrees.** Root directory for Git worktree checkouts created from the sidebar: ```toml [worktrees] directory = "~/.herdr/worktrees" ``` Checkouts land at `<directory>/<repo>/<branch-slug>`; relative values resolve to absolute paths. `New worktree` creates a checkout (checking out an existing local branch or creating one), opens it as a new workspace grouped under the source workspace; `Open worktree...` lists existing checkouts. Closing a grouped parent workspace closes the whole group but does not delete checkout folders or branches; `Delete worktree checkout...` runs `git worktree remove` explicitly (branches are never deleted). **Remote attach.** ```toml [remote] manage_ssh_config = true ``` When enabled, `herdr --remote` writes a private temporary SSH config including your `~/.ssh/config` and `/etc/ssh/ssh_config` first, then adds fallback `ServerAliveInterval`/`ServerAliveCountMax` (your own keepalive settings win), and uses a private per-attach OpenSSH control socket to reuse the first authenticated connection. Set `manage_ssh_config = false` to use plain `ssh` with no generated config or control socket. **Keybindings.** Default prefix is `ctrl+b`; strings are explicit (`prefix+n`, or a direct chord like `ctrl+alt+n`): ```toml [keys] prefix = "ctrl+b" goto = "prefix+g" new_tab = "prefix+c" next_tab = "prefix+n" previous_tab = "prefix+p" focus_pane_left = "prefix+h" navigate_workspace_down = "j" navigate_pane_down = "ctrl+j" split_horizontal = "prefix+minus" ``` The default keymap is prefix-first so Herdr doesn't steal input from shells/editors/tmux/terminal apps; search `keys.` in the config reference for every action and default. `prefix+?` shows active bindings in-app. A binding may be an array for multiple shortcuts: ```toml [keys] next_tab = ["prefix+n", "ctrl+alt+]"] ``` Optional actions are unset by default; bind with `prefix+` for prefix-mode behavior or an explicit modified chord for a direct shortcut. Key strings accept plain keys, modifiers (`ctrl+a`, `shift+n`, `alt+1`, `cmd+k`), specials (`enter`, `tab`, `esc`, `left`, `right`, `up`, `down`), and named punctuation (`minus`, `comma`, `ampersand`, `plus`, `backtick`). Plain printable keys like `n` are unsafe (they intercept typing) — use `prefix+n` unless a direct binding is intentional. `navigate_workspace_*`/`navigate_pane_*` are navigate-mode-only and may use plain keys such as `j`/`k`, but must not use `prefix+`, `esc`, `enter`, `tab`, `shift+tab`, `left`, `right`, or unmodified `1`-`9`; left/right arrows are permanent pane-left/pane-right aliases. When a navigate-mode shortcut and a general action binding share a key, the navigate-mode shortcut wins while navigate mode is open. Reset to new defaults: ```bash herdr config reset-keys ``` This backs up `config.toml`, removes `[keys]` and `[[keys.command]]`, and uses built-in v2 defaults after restart or `herdr server reload-config`. **Indexed jumps** use `1..9` in normal fields: ```toml [keys] switch_tab = "prefix+1..9" switch_workspace = "prefix+shift+1..9" focus_agent = "prefix+alt+1..9" ``` The legacy `[keys.indexed]` table still parses for compatibility; new configs should prefer explicit action fields. **Custom command keybindings** share the same syntax: ```toml [[keys.command]] key = "prefix+alt+g" type = "popup" command = "lazygit" description = "run lazygit" width = "80%" height = "80%" ``` `type = "popup"` opens a session-modal popup that receives all input (including Escape) until the command exits; `width`/`height` are optional (numbers = terminal cells, strings like `"80%"` = percentage, clamped to the popup minimum; dimensions include the border). Popup commands do not receive `HERDR_PANE_ID` — use `HERDR_ACTIVE_PANE_ID` for the underlying tiled pane. On Unix/macOS, a popup can host an ad-hoc scratch terminal: ```toml [[keys.command]] key = "prefix+t" type = "popup" command = "exec \"${SHELL:-sh}\"" description = "open scratch terminal" width = "80%" height = "80%" ``` On Windows, use e.g. `command = "powershell.exe -NoLogo"`. `type = "pane"` opens a temporary zoomed pane and closes it when the command exits; `type = "shell"` runs detached in the background; `type = "plugin_action"` invokes an installed plugin action id (use the qualified id when not globally unique): ```toml [[keys.command]] key = "prefix+l" type = "plugin_action" command = "example.layout.apply" description = "apply layout" ``` `description` shows in the `prefix+?` help panel in place of `'custom command'`. Custom commands receive `HERDR_SOCKET_PATH`, `HERDR_BIN_PATH`, `HERDR_ACTIVE_WORKSPACE_ID`, `HERDR_ACTIVE_TAB_ID`, `HERDR_ACTIVE_PANE_ID`, and `HERDR_ACTIVE_PANE_CWD` when available, and run from the focused pane's cwd when detectable. On Windows, custom command strings use `cmd.exe /d /c`, so env vars use `%HERDR_BIN_PATH%` syntax; invoke PowerShell explicitly, e.g. `powershell.exe -NoProfile -Command "..."`. **Theme.** ```toml [theme] name = "catppuccin" ``` Search `theme.name` in the config reference for every built-in theme; use `terminal` to follow the host terminal's ANSI palette. Auto light/dark switching: ```toml [theme] name = "catppuccin" auto_switch = true light_name = "catppuccin-latte" dark_name = "catppuccin" ``` `auto_switch` defaults `false`. If `light_name`/`dark_name` is omitted, Herdr uses the matching built-in sibling when one exists (e.g. `tokyo-night`/`tokyo-night-day`, `gruvbox`/`gruvbox-light`). Manual theme selection in Settings disables `auto_switch`. Override individual colors: ```toml [theme.custom] panel_bg = "reset" accent = "#a6e3a1" green = "#a6e3a1" blue = "#89b4fa" red = "#f38ba8" yellow = "#f9e2af" ``` Color values accept hex, named colors, `rgb(r,g,b)`, or reset aliases (`reset`, `default`, `none`, `transparent`). **UI and sidebar.** Search `ui.` in the config reference for sizing, collapsed mode, Agent panel ordering, mouse behavior, pane borders. Default sidebar row layouts: ```toml [ui.sidebar.agents] row_gap = 0 rows = [ ["state_icon", "workspace", "tab"], ["agent"], ] [ui.sidebar.spaces] row_gap = 0 rows = [ ["state_icon", "workspace"], ["branch", "git_status"], ] ``` Agent row tokens: `state_icon`, `state_text` (`idle`/`working`/`blocked`/`done`/`unknown`, with reported display label when present), `workspace`, `tab`, `pane`, `agent`, `terminal_title`, `terminal_title_stripped`, and custom `$name` pane metadata. Space row tokens: `state_icon`, `state_text`, `workspace`, `branch`, `git_status`, and custom `$name` workspace metadata. Tokens render in configured order, separated by ` · ` (single space after `state_icon`); missing values and their separators disappear, and a row disappears if none of its tokens have a value. Each layout allows at most 16 rows of at most 16 tokens each. Inline per-token styling: ```toml [ui.sidebar.agents] rows = [ ["state_icon", { token = "workspace", bold = false }, "tab"], [{ token = "$summary", fg = "#89b4fa", bold = true, dim = false }], ] ``` `fg` accepts strict `#RGB`/`#RRGGBB`; `bold`/`dim` accept booleans; omitted fields preserve contextual style, explicit `false` removes a modifier; a foreground override replaces all semantic foregrounds in that occurrence (e.g. `git_status` ahead/behind counts become one color instead of green/red). `row_gap` (default `0`) controls blank rows between entries independently per panel; set to `1` for the previous spacing. Per-agent row overrides: ```toml [ui.sidebar.agents] rows = [ ["state_icon", "agent", "state_text"], ["workspace", "tab"], ] [ui.sidebar.agents.rows_by_agent] claude = [ ["state_icon", "agent", "state_text"], ["terminal_title_stripped"], ["workspace", "tab"], ] ``` An override replaces `rows` entirely; keys are case-sensitive canonical agent IDs (`claude`, `codex`, `pi` — not aliases like `claude-code`). Custom `$name` tokens are populated dynamically: ```toml [ui.sidebar.agents] rows = [ ["state_icon", "agent", "$model"], ["$summary"], ["workspace", "tab"], ] ``` ```bash herdr pane report-metadata <pane_id> \ --source my-agent-hook \ --token model=opus \ --token summary="reviewing authentication" ``` `herdr workspace report-metadata` does the same for Space tokens. Sidebar row settings only affect the expanded desktop sidebar; collapsed/mobile keep compact layouts. **Notifications.** ```toml [ui.toast] delivery = "herdr" delay_seconds = 1 [ui.toast.herdr] position = "bottom-right" ``` `delivery` is `herdr` (in-app toast), `terminal` (outer-terminal notification, good over SSH), `system` (OS notification service), or `off`. Popups are suppressed for the active tab. **Sound.** ```toml [ui.sound] path = "sounds/notification.mp3" done_path = "sounds/done.mp3" request_path = "sounds/request.mp3" ``` Custom sounds must be mp3; relative paths resolve from the config file's directory. `path` sets one sound for all notifications; `done_path`/`request_path` override just the finished/needs-input sounds. Per-agent overrides (`default`/`on`/`off`): ```toml [ui.sound.agents] droid = "off" claude = "on" ``` Droid is muted by default. **Kitty graphics** (experimental, off by default): ```toml [experimental] kitty_graphics = true ``` **Agent session restore** (see [[concepts/persistence-and-remote]]): ```toml [session] resume_agents_on_restore = true ``` Only panes with a valid native session reference from an official integration can resume; others restore as normal shells. **IME cursor tracking** (macOS): ```toml [experimental] reveal_hidden_cursor_for_cjk_ime = true cjk_ime_agents = ["claude", "pi", "codex"] ``` Reveals a cursor anchor so native IME candidate windows follow the focused pane when an Agent TUI hides the hardware cursor; restrict `cjk_ime_agents` to avoid showing an extra hardware cursor elsewhere. **Prefix input source switching** (macOS): ```toml [experimental] switch_ascii_input_source_in_prefix = true ``` Temporarily switches to the system ASCII-capable input source while prefix commands/prefix-launched modes are active, restoring the previous source afterward. No effect on other platforms. **Environment variables:** | Variable | Purpose | | --- | --- | | `HERDR_CONFIG_PATH` | Override the config file path. | | `HERDR_SESSION` | Select a named session for CLI commands. | | `HERDR_SOCKET_PATH` | Low-level socket path override. | | `HERDR_LOG` | Set log filtering, for example `HERDR_LOG=herdr=debug`. | | `HERDR_DISABLE_SOUND` | Disable sound playback even when `[ui.sound] enabled = true`. | **Logs:** ```text ~/.config/herdr/herdr.log ~/.config/herdr/herdr-client.log ~/.config/herdr/herdr-server.log ``` Logs rotate automatically; include the current log and rotated siblings when reporting issues. ## Key Parameters - **`[terminal] default_shell` / `shell_mode` / `new_cwd`** — controls what shell launches and where. - **`[keys] prefix`** plus per-action bindings and `[[keys.command]]` — the entire keybinding surface. - **`[theme] name` / `auto_switch` / `[theme.custom]`** — visual theme and per-color overrides. - **`[ui.sidebar.agents]` / `[ui.sidebar.spaces]`** — sidebar row token layout, `rows_by_agent` overrides, `row_gap`. - **`[ui.toast]` / `[ui.sound]`** — notification delivery and sound behavior. - **`[remote] manage_ssh_config`** — whether `herdr --remote` manages its own SSH config/control socket. - **`[worktrees] directory`** — root for Git worktree checkouts. - **`[session] resume_agents_on_restore`** and **`[experimental]`** keys — advanced/opt-in behavior. ## When To Use Add a config file as soon as you want a non-default prefix, a theme, sidebar tokens showing agent metadata, or notification/sound tuning. Use `herdr --default-config` to get every key with defaults and comments as a starting point rather than hand-writing sections from memory. Use `herdr server reload-config` for iterative tuning without disrupting running panes; reserve a full restart for startup-only settings. ## Risks & Pitfalls - An invalid config value doesn't hard-fail Herdr — it silently falls back to a safe default with only a startup warning, so misconfigurations can go unnoticed. Check the startup warning output after edits. - `rows_by_agent` overrides **replace** `rows` entirely rather than extending it — a common authoring mistake. - Windows custom commands need `cmd.exe`-style `%VAR%` syntax, not POSIX `$VAR` — Unix-style command strings silently fail to interpolate. - `navigate_workspace_*`/`navigate_pane_*` keys have their own restricted grammar (no `prefix+`, no `esc`/`enter`/`tab`/arrows/unmodified digits) — reusing a general-binding key here has navigate-mode silently win over the general binding. - Kitty graphics and CJK IME reveal are both off by default for good reason (compatibility/extra-cursor side effects) — read the caveats in [[concepts/install-and-quickstart]] (Windows) before enabling. ## Related Concepts - [[concepts/herdr-overview]] — the workspace/tab/pane/agent/session model these keys configure. - [[concepts/panes-and-keyboard]] — the human-facing keyboard guide this reference underpins. - [[concepts/cli-reference]] — `herdr --default-config`, `herdr server reload-config`, `herdr config reset-keys`, `herdr pane report-metadata`, `herdr workspace report-metadata`. - [[concepts/install-and-quickstart]] — config file paths per OS and first-run onboarding. - [[concepts/persistence-and-remote]] — `[session] resume_agents_on_restore`, `[remote] manage_ssh_config`. - [[concepts/plugins-and-marketplace]] — `type = "plugin_action"` custom commands and plugin config directories. - [[concepts/agents-and-integrations]] — per-agent sound and sidebar overrides (`claude`, `codex`, `droid`, etc.). - [[concepts/troubleshooting]] — using `HERDR_LOG` and the log file locations to diagnose issues. ## Sources - raw/github_doc-docs-next-website-src-content-docs-configuration-mdx.md - raw/github_doc-docs-next-website-src-content-docs-config-reference-mdx.md <!-- ===== herdr/wiki/concepts/herdr-overview.md ===== --> --- title: "Herdr Overview" type: concept tags: [agents, foundational, well-established, beginner] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_doc-readme-md.md", "raw/github_doc-docs-next-website-src-content-docs-index-mdx.md", "raw/github_doc-docs-next-website-src-content-docs-concepts-mdx.md"] confidence: high herdr_version: v0.7.5 --- ## Definition Herdr (herdr.dev, github.com/ogulcancelik/herdr) is an **agent multiplexer that lives in your terminal**. Its own README frames the thesis directly: it is a terminal workspace manager for AI coding agents, positioned as what tmux is to terminals — but for agents instead of shells. It is shipped as one Rust binary with no Electron dependency, and runs in whatever terminal you already use. The core pitch, in the project's own words: "every agent at a glance — blocked, working, done. real terminal views, not a wrapped interpretation." Agents keep running when you detach, and can be reattached from any terminal or over SSH — sessions survive restarts. Agents can also drive Herdr itself through a pure socket API (spawning panes, reading output, waiting on each other), and Herdr supports plugins that extend panes and workflows. ## How It Works Herdr runs as a background **server** plus one or more attached **clients**. The server owns panes and process state (the real terminal processes); the client is the terminal UI that attaches to that server and renders it. Detaching a client with `ctrl+b q` does not stop anything — the server and its agents keep running until you explicitly stop the server with `herdr server stop`. Herdr's structural model has four layers, from largest to smallest: - **Workspace** — the top-level project container. Use one workspace per repo, task, or investigation. A workspace owns tabs and panes, and its sidebar state rolls up from the agents inside it so you can see which project needs attention. - **Tab** — a layout inside a workspace, used to separate views such as `agents`, `logs`, `server`, or `review`. Tabs are addressable from the CLI and socket API. - **Pane** — a real terminal. Herdr renders the terminal's output, sends input back to the process, and preserves the pane across client detach. Panes can be split right or down, renamed, read from the CLI, sent input, and closed. - **Agent** — a process Herdr recognizes inside a pane, detected from foreground processes, screen manifests, and optional integrations. Detected agents carry one of five states: `blocked` (needs input, approval, or a decision), `working` (actively running), `done` (finished, not yet looked at), `idle` (finished or waiting, and seen), or `unknown` (Herdr cannot confidently classify it). A **session** is a persistent Herdr server namespace; the default `herdr` command attaches to the default session, and named sessions (`herdr session list`, `herdr session attach work`) give you completely separate panes, sockets, and persisted runtime state when workspaces alone aren't enough separation. Herdr also defines three interaction **modes**: terminal mode (keys go to the focused pane), prefix mode (one Herdr action after the prefix key, default `ctrl+b`), and navigate mode (the persistent workspace navigation surface). ## Key Parameters - **Mouse-first, keyboard-optional** — Herdr is explicitly mouse-native: click panes/tabs/workspaces/agents, drag split borders, use right-click menus. Keyboard control (the tmux-style prefix system) is a fully optional layer, not a requirement. - **Detection sources** — agent state comes from foreground process inspection, screen manifests, and optional first-class integrations that self-report lifecycle state, which improves accuracy over passive detection alone. - **Client/server separation** — this is what makes persistence, remote attach, and multi-client viewing possible; it is the foundational mechanic behind almost every other Herdr feature. - **One binary** — a single Rust binary, no bundled runtime like Electron, which keeps footprint and install friction low. ## When To Use Herdr fits anyone running one or more long-lived coding agents (Claude Code, Codex, Pi, OpenCode, and others) who wants to glance at agent state across many concurrent projects without babysitting each terminal window, who wants agents to survive laptop sleep/disconnect/SSH drops, or who wants agents to be able to orchestrate each other (spawning panes, reading each other's output) through a real API rather than screen-scraping. It is also a reasonable direct substitute for tmux/zellij for people who want the same session-persistence and pane model but with agent-awareness layered on top. ## Risks & Pitfalls - Herdr explicitly is not a "wrapped interpretation" of terminal output — it shows real terminal views. This means agent state classification is inherently heuristic (hence the `unknown` state) and depends on correct detection or an installed integration; see [[concepts/agents-and-integrations]] for how detection accuracy is improved per agent. - Confusing "workspace" (project container) with "session" (server namespace) is an easy early mistake — sessions are for full runtime isolation, workspaces are the normal unit of project separation. - Detaching (`ctrl+b q`) is not the same as stopping — new users coming from other tools may expect closing a terminal to end the agents; it does not, by design. ## Related Concepts - [[concepts/install-and-quickstart]] — getting Herdr running for the first time. - [[concepts/panes-and-keyboard]] — the pane model and full keyboard surface in depth. - [[concepts/configuration]] — config file structure and precedence. - [[concepts/cli-reference]] — the full `herdr` CLI surface. - [[concepts/agents-and-integrations]] — supported agents and how detection/integrations work. - [[concepts/persistence-and-remote]] — detach/reattach, SSH, and remote thin-client modes. - [[concepts/plugins-and-marketplace]] — extending Herdr with plugins. - [[concepts/agent-automation-and-socket-api]] — agents driving Herdr through the socket API. - [[concepts/troubleshooting]] — the community troubleshooting layer. - [[summaries/release-digest]] — release history and what changed recently. - [[syntheses/issues-casebook]] — cross-cutting analysis of reported issues. ## Sources - raw/github_doc-readme-md.md - raw/github_doc-docs-next-website-src-content-docs-index-mdx.md - raw/github_doc-docs-next-website-src-content-docs-concepts-mdx.md <!-- ===== herdr/wiki/concepts/install-and-quickstart.md ===== --> --- title: "Install and Quick Start" type: concept tags: [install, beginner, foundational, well-established] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_doc-docs-next-website-src-content-docs-install-mdx.md", "raw/github_doc-docs-next-website-src-content-docs-quick-start-mdx.md", "raw/github_doc-docs-next-website-src-content-docs-windows-beta-mdx.md"] confidence: high herdr_version: v0.7.5 --- ## Definition Installing and starting Herdr covers getting the `herdr` binary onto your PATH through one of several install paths, then launching it to create your first [[concepts/herdr-overview|workspace]] and running an agent inside a pane. Herdr ships **stable** binaries for Linux and macOS; native Windows support is **preview-only beta**. ## How It Works On Linux or macOS, the standard install is: ```bash curl -fsSL https://herdr.dev/install.sh | sh ``` On Windows preview beta, install the preview channel: ```powershell powershell -ExecutionPolicy Bypass -c "irm https://herdr.dev/install.ps1 | iex" ``` Other install paths: ```bash brew install herdr mise use -g herdr ``` If mise reports `herdr not found in mise tool registry`, update mise and retry; `mise use -g github:ogulcancelik/herdr` is a temporary fallback on older mise versions. Nix (builds from source via a flake): ```bash nix run github:ogulcancelik/herdr/v0.x.y nix build github:ogulcancelik/herdr/v0.x.y nix profile install github:ogulcancelik/herdr/v0.x.y nix develop github:ogulcancelik/herdr ``` Replace `v0.x.y` with the latest release tag (currently v0.7.5); omitting the tag tracks `master`. Update a Nix profile install with `nix profile list` then `nix profile upgrade <index-or-name>`, or `nix flake update herdr` if Herdr is an input in your own flake. Manual binary download from GitHub releases, matched to system (`herdr-linux-x86_64`, `herdr-linux-aarch64`, `herdr-macos-x86_64`, `herdr-macos-aarch64`; Windows beta asset `herdr-windows-x86_64.exe` published only on preview prereleases): ```bash chmod +x herdr-linux-x86_64 mv herdr-linux-x86_64 ~/.local/bin/herdr ``` The installer downloads the right release binary for your platform and places it on PATH, using versioned install folders and a `current` junction so updates don't need to overwrite a running `herdr.exe`. **First run and quick start.** Start Herdr from any project directory: ```bash herdr ``` Herdr launches or attaches to your default background session; you don't manage sockets, and if you detach, agents keep running. When a session has no workspaces, Herdr opens one automatically — a workspace is the project-level container for tabs, panes, and agents. Give each active project its own workspace so agent state stays readable in the sidebar. Use the mouse first: click panes, tabs, workspaces, and agents to focus them; drag split borders to resize; right-click for context menus (splitting panes, creating tabs); drag-select text to copy (double-click a token to copy it directly) — copying does not require Ctrl+C. Ctrl-click opens pane links (OSC 8 hyperlinks or visible `http://`/`https://` URLs) when your terminal forwards the modified click. Run your coding agent in a pane: ```bash claude ``` (or `codex`, `pi`, `opencode`, or any other supported agent — see [[concepts/agents-and-integrations]]). Herdr detects it automatically and the sidebar shows `working`, `blocked`, `done`, or `idle` across every workspace. Keyboard is optional; press `ctrl+b` to enter prefix mode, then an action key. Quick-start's common actions table: | Action | Key | | --- | --- | | Split right | `prefix+v` | | Split down | `prefix+minus` | | New tab | `prefix+c` | | Next / previous tab | `prefix+n` / `prefix+p` | | Workspace navigation | `prefix+w` | | New workspace | `prefix+shift+n` | | Detach client | `prefix+q` | Press `prefix+?` to see every active binding, and `prefix+[` to enter copy mode. See [[concepts/panes-and-keyboard]] for the complete keyboard surface. Detach with `prefix+q` or simply close the terminal window — the server and every agent keep running. Run `herdr` again to reattach. To actually end the session and stop its panes: ```bash herdr server stop ``` **Verify and update.** Verify with `herdr`; if the shell cannot find it, restart the terminal or check PATH. Update manually with: ```bash herdr update ``` `herdr update` only applies to installs managed by Herdr's own installer — Homebrew, mise, and Nix installs update through those package managers. Linux/macOS default to the stable update channel; opt into preview with `herdr channel set preview`, and return with `herdr channel set stable`. Preview builds are manually published GitHub prereleases from the current development branch — useful for early fixes, but can regress. Windows beta builds are preview-only; `herdr channel set stable` is rejected on Windows until stable Windows releases exist. If an update changes the client/server protocol, Herdr asks whether to stop the old server after installing; for the default session run `herdr server stop` then `herdr` again, or for a named session `herdr session stop <name>` then `herdr session attach <name>`. To opt into experimental live handoff for supported running sessions: ```bash herdr update --handoff ``` Live handoff does not apply to Homebrew/mise/Nix updates. ## Key Parameters - **Stable vs. preview channel** — controls which binaries you receive; set with `herdr channel set preview` / `herdr channel set stable`. - **Windows beta status** — native Windows support is experimental/preview-only. Herdr on Windows uses ConPTY and Windows process/runtime behavior instead of the Unix PTY model Herdr was built around, so some features map cleanly and some do not; this is not a commitment that every Linux/macOS feature reaches Windows. Windows beta builds are stored under `%USERPROFILE%\.herdr\packages\standalone\releases`, with `%LOCALAPPDATA%\Programs\Herdr\bin` pointed at the current release. `HERDR_MANIFEST_URL` can point the installer at a custom manifest for internal beta testing. - **Beta feature-support tiers** — per the Windows beta doc: capabilities are tracked as "beta" (e.g. local persistent sessions, native panes via ConPTY, Windows Terminal/PowerShell attach, `cmd.exe` panes, agent command discovery, agent process-tree detection, pane screen history), "preview" (plugins), "partial" (live cwd after shell `cd`, CJK IME composition anchoring, host cursor rendering), or "unverified" (clipboard image paste to agents, Kitty graphics rendering). Unsupported on Windows beta entirely: direct terminal attach, `herdr --remote` from the Windows binary, live server handoff, Unix file-descriptor handoff, Unix foreground process groups, remote clipboard image bridge, prefix input-source switching, and signed-binary/SmartScreen avoidance. - **Reporting Windows beta issues** should include: Herdr version, Windows version, terminal app, shell (PowerShell/cmd), whether a named `HERDR_SESSION` was used, relevant Herdr logs, and exact repro steps. ## When To Use Use the curl/PowerShell installer for a normal first install; use Homebrew, mise, or Nix if you already manage tools that way (their updates then flow through that package manager, not `herdr update`); use manual binary download when you need a specific pinned asset or air-gapped install. On Windows, expect beta-quality behavior and prefer SSHing into a Linux/macOS host and running `herdr` there for remote work, since native `herdr --remote` is not part of the Windows beta (see [[concepts/panes-and-keyboard]] and [[concepts/persistence-and-remote]] for the SSH-based remote paths). ## Risks & Pitfalls - Windows `herdr channel set stable` is rejected until stable Windows releases exist — don't expect to pin Windows to stable today. - Homebrew/mise/Nix installs silently ignore `herdr update`/`herdr update --handoff`/channel switching; you must update through the original package manager or these commands have no effect on that install. - Windows clipboard-image paste (`alt+v`) is explicitly unverified, and Kitty graphics is experimental — leave `experimental.kitty_graphics = false` (see [[concepts/configuration]]) unless actively testing. - Stopping the old server after a protocol-changing update exits pane processes — know this before running `herdr server stop` mid-work. ## Related Concepts - [[concepts/herdr-overview]] — the underlying workspace/tab/pane/agent model and client-server thesis. - [[concepts/panes-and-keyboard]] — full keyboard surface referenced during quick start. - [[concepts/configuration]] — config file location and `herdr --default-config`. - [[concepts/cli-reference]] — `herdr update`, `herdr channel`, `herdr completion`, and other launch/status commands verbatim. - [[concepts/agents-and-integrations]] — supported agent list referenced by "Run an agent". - [[concepts/persistence-and-remote]] — SSH-based remote workflows relevant to Windows beta limitations. - [[concepts/troubleshooting]] — where install/update failures get diagnosed. - [[summaries/release-digest]] — how stable vs. preview releases map to versions. ## Sources - raw/github_doc-docs-next-website-src-content-docs-install-mdx.md - raw/github_doc-docs-next-website-src-content-docs-quick-start-mdx.md - raw/github_doc-docs-next-website-src-content-docs-windows-beta-mdx.md <!-- ===== herdr/wiki/concepts/panes-and-keyboard.md ===== --> --- title: "Panes and Keyboard" type: concept tags: [panes, agents, beginner, intermediate, foundational, well-established] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_doc-docs-next-website-src-content-docs-how-to-work-mdx.md", "raw/github_doc-docs-next-website-src-content-docs-keyboard-mdx.md"] confidence: high herdr_version: v0.7.5 --- ## Definition This page covers two tightly related surfaces: the **pane model** for working across agents (running Herdr locally, over plain SSH, on a phone, or as a remote thin client), and the **full keyboard surface** Herdr exposes — the prefix system, the default bindings worth learning first, copy mode, and how to go prefix-free. ## How It Works **Working across contexts.** Herdr is a background session server plus one or more terminal clients; panes keep running in the server, and clients attach, detach, and render the session. Four ways to work: 1. **Local work** — start from the project directory: ```bash herdr ``` Herdr starts or attaches to your local background session automatically; no socket management. Detach with `ctrl+b q`; panes keep running. Reattach with `herdr` again. Stop the session and its panes entirely with `herdr server stop`. 2. **Remote work through normal SSH** — SSH to the machine with the code and credentials, then run Herdr there: ```bash ssh you@server herdr ``` This behaves like a normal terminal multiplexer: the shell, the Herdr server, and the agents/panes are all remote. Detach with `ctrl+b q`, disconnect, then SSH back and run `herdr` again. Use this when already inside an SSH shell, on a phone/tablet SSH client, or for the simplest setup. 3. **Work from your phone** — no Herdr mobile app or web dashboard needed; any SSH client works: ```bash ssh you@server herdr ``` The same persistent session opens in the phone terminal; the TUI adapts to narrow screens. On iPhone, apps like moshi work well. 4. **Remote work from your local terminal** — attach through SSH without opening a shell first, using Herdr as a thin client: ```bash herdr --remote workbox herdr --remote ssh://you@server:2222 ``` The local Herdr connects over SSH and starts or attaches to the remote server, streaming the UI back locally. This path lets local desktop features (such as image clipboard paste) bridge to the remote server — something SSH-then-`herdr` cannot do, since in that mode Herdr runs entirely on the remote host and cannot read the local desktop clipboard. For repeat targets, add the host to `~/.ssh/config`: ```text Host workbox HostName server.example.com User you Port 2222 ``` then `herdr --remote workbox`. **Which path to use:** plain `herdr` for local work; `ssh you@server` then `herdr` for tmux-like remote behavior or phone SSH clients; `herdr --remote <host>` for a local thin client with local clipboard image bridging. See [[concepts/persistence-and-remote]] for named remote sessions, custom binaries, direct terminal attach, and `--no-session`. **The keyboard surface.** Herdr is mouse-native — click panes/tabs/workspaces/agents, drag borders, use right-click menus — with keyboard as an optional layer. A multiplexer sits between the terminal and the programs inside it, and those programs already claim most keys (`ctrl+c` interrupts, `ctrl+r` searches history, editors claim the rest). The **prefix** solves this: press the prefix key (default `ctrl+b`), release, then press an action key — `prefix+c` means press `ctrl+b`, release, then `c`. Press `prefix+?` at any time to see every active binding. Learn these five first: | Action | Key | | --- | --- | | New tab | `prefix+c` | | Split right / down | `prefix+v` / `prefix+minus` | | Move between panes | `prefix+h/j/k/l` | | Workspace navigation | `prefix+w` | | Detach, leave everything running | `prefix+q` | Panes: | Action | Key | | --- | --- | | Zoom the focused pane | `prefix+z` | | Close pane | `prefix+x` | | Swap panes | `prefix+shift+h/j/k/l` | | Resize mode | `prefix+r` | | Copy mode | `prefix+[` | Tabs: | Action | Key | | --- | --- | | Next / previous tab | `prefix+n` / `prefix+p` | | Jump to tab 1–9 | `prefix+1..9` | | Rename tab | `prefix+shift+t` | | Close tab | `prefix+shift+x` | Workspaces and session: | Action | Key | | --- | --- | | New workspace | `prefix+shift+n` | | Rename workspace | `prefix+shift+w` | | Close workspace | `prefix+shift+d` | | Goto picker | `prefix+g` | | Toggle sidebar | `prefix+b` | The full keymap and binding syntax live in the config reference (see [[concepts/configuration]]). **Copy mode**: `prefix+[` enters copy mode for the focused pane. Move with `h/j/k/l`, tmux-style `w/b/e`, `{`/`}`, `PageUp`/`PageDown`, `ctrl+b`/`ctrl+f`, `ctrl+u`/`ctrl+d`. Press `/` or `?` for forward/backward literal search, then `n`/`N` to repeat; search is case-insensitive unless the query contains an uppercase letter. Use `v` or Space to start a selection, `y` or Enter to copy, `q` or Esc to leave without copying (Esc first clears an active selection or search). Copy mode does not pause the pane process — output stays live, follows at the bottom, and stays pinned when navigating into history. The configured prefix keeps its normal meaning in copy mode, so with the default prefix `ctrl+b` enters prefix mode rather than paging up — use a different prefix if you want `ctrl+b` for copy-mode page-up. Mouse drag-select copies without entering copy mode at all. Change the prefix itself: ```toml [keys] prefix = "ctrl+a" ``` **Going prefix-free.** Any chord can be bound directly with no prefix (`ctrl+j`, `alt+k`, etc.), but a chord must survive three layers — OS, outer terminal, and the pane program — before Herdr sees it. `ctrl+j` reaches Herdr fine, but shells/editors treat it as Enter; `alt+k` is free on Linux but macOS composes it into a special character in most terminals. Herdr's docs mapped default keybindings across Ghostty, iTerm2, Terminal.app, kitty, WezTerm, Alacritty, Warp, Windows Terminal, GNOME Terminal, and Konsole, plus GNOME/KDE global shortcuts, and found `ctrl+alt` almost universally free — it's the recommended safe family (not affected by macOS's alt-composing behavior, and transmits even without a modern keyboard protocol). Example dual-binding setup: ```toml [keys] focus_pane_left = ["prefix+h", "ctrl+alt+h"] focus_pane_down = ["prefix+j", "ctrl+alt+j"] focus_pane_up = ["prefix+k", "ctrl+alt+k"] focus_pane_right = ["prefix+l", "ctrl+alt+l"] previous_tab = ["prefix+p", "ctrl+alt+["] next_tab = ["prefix+n", "ctrl+alt+]"] new_tab = ["prefix+c", "ctrl+alt+c"] split_vertical = ["prefix+v", "ctrl+alt+d"] split_horizontal = ["prefix+minus", "ctrl+alt+shift+d"] zoom = ["prefix+z", "ctrl+alt+z"] ``` A few `ctrl+alt` chords are already owned elsewhere: | Chord | Owned by | | --- | --- | | `ctrl+alt+arrows` | GNOME workspace switching, Ghostty and Konsole defaults | | `ctrl+alt+t` | "Launch terminal" on Ubuntu and Fedora | | `ctrl+alt+l` / `ctrl+alt+a` | KDE lock screen / attention window | | `ctrl+alt+s` / `ctrl+alt+u` | Konsole | | `ctrl+alt+f1..f12` | Linux virtual console switching | If a direct chord does nothing, the terminal or desktop environment consumed it before Herdr saw it — free it in the terminal's settings or pick another chord. ## Key Parameters - **`[keys] prefix`** — the single reserved key, default `ctrl+b`. - **Chord families** — prefixed (`prefix+x`), direct modified (`ctrl+alt+x` recommended, `alt+x` risky on macOS, `ctrl+x` mostly claimed by terminal programs), and mouse actions, which need no chord at all. - **Attach mode** — plain `herdr`, SSH-then-`herdr`, or `herdr --remote <host>` — chosen based on whether you need local-desktop bridging (clipboard image paste) versus simplest setup. ## When To Use Use plain `herdr` locally; SSH-then-`herdr` for phone/tablet SSH clients or when you're already in a remote shell; `herdr --remote <host>` when you want the remote session to feel local, including clipboard image bridging. Learn the five core prefix bindings immediately; add `ctrl+alt` direct chords once mouse-plus-five-keys starts to feel slow. Use copy mode's `/`/`?` search for scrollback navigation in place of the mouse when working over a laggy SSH link. ## Risks & Pitfalls - macOS composes plain `alt+key` into special characters in most terminals — don't build a prefix-free layout on the `alt` family there. - With the default prefix, `ctrl+b` inside copy mode still enters prefix mode rather than paging up — a frequent point of confusion for tmux users expecting `ctrl+b` to page. - `herdr --remote` from the Windows binary is unsupported (see [[concepts/install-and-quickstart]]); Windows users needing true remote work should SSH into a Linux/macOS host and run `herdr` there. - Running Herdr entirely on a remote host (SSH-then-`herdr`) cannot bridge your local desktop clipboard — only `herdr --remote` can. ## Related Concepts - [[concepts/herdr-overview]] — workspace/tab/pane/agent model and client-server split. - [[concepts/install-and-quickstart]] — first-run quick-start keybinding table and mouse basics. - [[concepts/configuration]] — full `[keys]` config syntax, indexed jumps, and custom command keybindings. - [[concepts/cli-reference]] — `herdr terminal attach`, `--remote`, and pane/agent CLI commands. - [[concepts/persistence-and-remote]] — named remote sessions, direct terminal attach, `--no-session`. - [[concepts/agents-and-integrations]] — the agents you interact with inside panes. - [[concepts/troubleshooting]] — keyboard/terminal compatibility issues reported by the community. ## Sources - raw/github_doc-docs-next-website-src-content-docs-how-to-work-mdx.md - raw/github_doc-docs-next-website-src-content-docs-keyboard-mdx.md <!-- ===== herdr/wiki/concepts/persistence-and-remote.md ===== --> --- title: "Persistence and Remote Access" type: concept tags: [persistence, remote, panes] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_doc-docs-next-website-src-content-docs-persistence-remote-mdx.md", "raw/github_doc-docs-next-website-src-content-docs-session-state-mdx.md"] confidence: high herdr_version: "v0.7.5" --- ## Definition Herdr runs panes inside a background server process, separate from the terminal client attached to it. Detaching the client leaves panes, shells, and agents running; reattaching (locally or over SSH) reconnects to that same live state. What actually survives depends on *which* interruption happens: a client detach, a full server restart, an update, or a live handoff — each has a different persistence guarantee, described precisely in Herdr's session-state model. ## How It Works **Live persistence (detach/reattach).** `ctrl+b q` detaches the client only; the server and every pane process keep running. Running `herdr` again reattaches. This is the strongest guarantee because the original processes never stop. **Snapshot restore (server restart).** If the server itself stops and restarts (e.g. `herdr server stop` then `herdr`), the original pane processes are gone, but Herdr restores the saved session *shape*: workspaces, tabs, panes, cwd, layout, and focus. Panes that cannot use a stronger restore path come back as new shells in their saved directories — it does not preserve running shells, servers, tests, or arbitrary processes. **Pane screen history replay.** Off by default (because pane output can contain secrets/tokens), this restores recent terminal *contents* — not the process — after a full server restart. Enable it with: ```toml [experimental] pane_history = true ``` When enabled, Herdr stores history in `session-history.json` next to `session.json`; treat that directory like shell history. **Native agent session restore.** Enabled by default, this lets Herdr use officially-integrated agents' own session references to resume their conversation (not just their pane shape) after a restart, using each agent's resume command (see [[concepts/agents-and-integrations]] for the version table and resume commands, e.g. `claude --resume <id>`, `codex resume <id>`). Disable with: ```toml [session] resume_agents_on_restore = false ``` If a pane's native session restore applies, Herdr resumes the agent session instead of replaying saved pane history for that pane. Unsupported, missing, invalid, duplicated, or stale references fall back to a normal shell in the saved directory. **Live handoff.** An experimental, opt-in path for updates and remote attach that need to replace a running server: the old server transfers live panes to the new one so processes survive the replacement, unlike the other three paths which all reconstruct state *after* the old server has already stopped. It protects pane PTYs/processes, agent identity, and plugin/session state, but does not preserve in-flight requests, waits, subscriptions, client sockets, or pane-to-pane messages across the boundary — those must reconnect/retry. ```bash herdr update --handoff herdr --remote workbox --handoff ``` `herdr update --handoff` only applies to installs managed by Herdr's own updater; Homebrew/mise/Nix installs update via their package managers and cannot handoff. **Named sessions.** Independent Herdr servers with their own panes, tabs, workspaces, sockets, and runtime state, sharing only the global config file: ```bash herdr session list herdr session attach work herdr session attach side-project herdr session stop work herdr session delete side-project ``` **Remote attach over SSH.** Two modes. SSH into the server and run `herdr` there for the tmux-style path (runs entirely on the server; no local desktop clipboard bridging). Or attach as a thin client from the local machine: ```bash herdr --remote workbox herdr --remote ssh://you@server:2222 ``` Because the client runs locally in this mode, Herdr can bridge local desktop features such as image clipboard paste (copying the image to a remote temp file and pasting that path). By default `--remote` uses local Herdr keybindings, snapshotted at attach time; use `--remote-keybindings server` for the remote config instead. Remote attach supports Linux/macOS hosts on x86_64/aarch64; native Windows `herdr --remote` is not part of the Windows beta (SSH in and run `herdr` there instead). Attach a named session remotely with `--session`: ```bash herdr --remote workbox --session agents ``` **Direct terminal/agent attach.** Attaches one server-owned terminal (not the whole workspace UI) to the current terminal: ```bash herdr agent attach reviewer herdr terminal attach term_abc123 ``` Detach with `ctrl+b q`; send a literal `ctrl+b` with `ctrl+b ctrl+b`; use `--takeover` to replace an existing direct-attach owner. Unix-only in the Windows beta. Read-only observers and writable controllers exist for bridging: ```bash herdr terminal session observe w1:p1 --cols 120 --rows 40 herdr terminal session control w1:p1 --takeover --cols 120 --rows 40 ``` **Single-process escape hatch.** `herdr --no-session` runs without the background server/client split — mainly for debugging or compatibility; the default persistent mode is the normal path. ## Key Parameters - `[experimental] pane_history = true` — enable screen history replay. - `[session] resume_agents_on_restore = false` — disable native agent session restore. - `[remote] manage_ssh_config = false` — use plain `ssh` instead of Herdr's generated config/control socket. - `HERDR_REMOTE_BINARY=target/release/herdr` — point remote attach at a local/custom binary. - `--handoff` — opt into live handoff for update or remote-attach server replacement. - `--remote-keybindings server` — use remote config's keybindings instead of the local snapshot. ## When To Use Use plain detach/reattach for day-to-day work — it's the only path that keeps arbitrary processes (tests, dev servers) alive. Reach for pane screen history or native agent session restore only when you specifically need continuity across a full server restart, weighing the secrets-in-history tradeoff. Use `--remote` from a laptop when you want local clipboard/keybinding behavior; SSH in directly when you just want the tmux-style server-side experience. Use `--handoff` only for supported running servers where you're willing to accept experimental behavior in exchange for not dropping live panes during an update. ## Risks & Pitfalls - Pane screen history can leak secrets/tokens/command output into `session-history.json` — it's off by default for that reason. - Live handoff is experimental and does not preserve in-flight CLI/API requests, waits, subscriptions, or pane-to-pane messages; callers must reconnect and retry. - A passphrase-protected SSH key in a non-interactive shell/CI/mobile terminal will not show a passphrase prompt — load it into `ssh-agent` first (`ssh-add`) before `herdr --remote`. - Native Windows remote attach isn't available in the Windows beta; only SSH-in-and-run-`herdr` works there. ## Related Concepts - [[concepts/agents-and-integrations]] — the integration versions and resume commands that back native agent session restore. - [[concepts/troubleshooting]] — diagnosing a stale running session after an update, and remote-attach authentication failures. - [[concepts/agent-automation-and-socket-api]] — terminal session observe/control primitives used for scripted bridges. ## Sources - raw/github_doc-docs-next-website-src-content-docs-persistence-remote-mdx.md - raw/github_doc-docs-next-website-src-content-docs-session-state-mdx.md <!-- ===== herdr/wiki/concepts/plugins-and-marketplace.md ===== --> --- title: "Plugins, Marketplace, and the Agent Skill" type: concept tags: [plugins, agents, config] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_doc-docs-next-website-src-content-docs-plugins-mdx.md", "raw/github_doc-docs-next-website-src-content-docs-marketplace-mdx.md", "raw/github_doc-docs-next-website-src-content-docs-agent-skill-mdx.md", "raw/github_doc-skill-md.md"] confidence: high herdr_version: "v0.7.5" --- ## Definition Herdr has three distinct extension surfaces that are easy to conflate: **plugins** (shareable executable workflow packages Herdr hosts and launches), the **marketplace** (an automatic GitHub-topic index for discovering community plugins), and **the agent skill** (`SKILL.md`, a markdown instruction file that teaches a coding agent how to *operate* Herdr from inside a pane — not a plugin at all). ## How It Works **Plugins.** A plugin is a directory with a `herdr-plugin.toml` manifest plus any commands Herdr can launch — Bash, JS, Lua, Rust, or anything else `argv`-runnable. Herdr owns the host surface (install, manifest validation, keybindings, panes, events, invocation context, socket access); the plugin owns its language, dependencies, and durable state. There is no separate plugin SDK — the entire Herdr CLI is the plugin API, and plugins typically call back through `HERDR_BIN_PATH` (portable across Unix sockets and Windows named pipes) rather than raw socket JSON. Runtime action registration and native non-terminal plugin UI are **not** part of plugin v1; actions, event hooks, panes, and link handlers are all declared in the manifest. Manifest shape (required top-level: `id`, `name`, `version`, `min_herdr_version`): ```toml id = "example.layout" name = "Layout" version = "0.1.0" min_herdr_version = "0.7.0" description = "Apply project layouts" platforms = ["linux", "macos", "windows"] [[build]] command = ["npm", "ci"] [[build]] command = ["npm", "run", "build"] platforms = ["linux", "macos"] [[startup]] command = ["node", "dist/restore.js"] [[actions]] id = "apply" title = "Apply layout" contexts = ["workspace"] command = ["node", "dist/apply.js"] [[events]] on = "worktree.created" command = ["herdr", "workspace", "list"] [[panes]] id = "board" title = "Project board" placement = "overlay" command = ["herdr-board"] [[link_handlers]] id = "github-issue" title = "Open GitHub issue" pattern = "^https://github\\.com/[^/]+/[^/]+/(issues|pull)/[0-9]+$" action = "apply" ``` Herdr refuses to link/install a plugin whose `min_herdr_version` is newer than the running binary. Runtime commands get injected env: `HERDR_SOCKET_PATH`, `HERDR_BIN_PATH`, `HERDR_ENV=1`, `HERDR_PLUGIN_ID`, `HERDR_PLUGIN_ROOT`, `HERDR_PLUGIN_CONFIG_DIR`, `HERDR_PLUGIN_STATE_DIR`, `HERDR_PLUGIN_CONTEXT_JSON`, plus available workspace/tab/pane IDs. Put user-editable config under `HERDR_PLUGIN_CONFIG_DIR` and runtime state under `HERDR_PLUGIN_STATE_DIR` — never in `HERDR_PLUGIN_ROOT`, since GitHub-installed roots are managed checkouts. Install from GitHub shorthand (`owner/repo/subdir`), or link a local working directory for authoring: ```bash herdr plugin install ogulcancelik/herdr-plugin-examples/agent-telegram-notify herdr plugin config-dir examples.agent-telegram-notify herdr plugin list herdr plugin action list --plugin examples.agent-telegram-notify herdr plugin link /path/to/plugin herdr plugin action invoke example.layout.apply herdr plugin pane open --plugin example.layout --entrypoint board ``` `plugin install` shows a preview of the source and commands before confirming (`--yes` skips this for trusted sources); `--ref` pins a revision. Build commands run only for GitHub installs, after confirmation, before registration; a failed build aborts install. `[[startup]]` hooks run once per enabled plugin after session restore, again on live handoff, but not on client attach/config reload/link. There is no plugin storage API in v1 — plugins own their own files. **Trust model.** A plugin runs as your user with your environment and the full Herdr CLI at its disposal — the same trust level as any editor/shell/agent extension. Herdr validates the manifest and isolates config/state directories per plugin, but does not review or sandbox plugin behavior. **Marketplace.** herdr.dev/plugins is an automatic, unreviewed index of public GitHub repositories tagged with the topic `herdr-plugin`, refreshed every 30 minutes. Listing shows repo name/owner, description, stars, primary language, and last-push time pulled from GitHub's repo search — it does **not** parse `herdr-plugin.toml`, so plugin `id`, `platforms`, and `min_herdr_version` aren't shown in v1. To get listed: add the `herdr-plugin` GitHub topic to a public, non-fork, non-archived repo. Installing still goes through the same command regardless of discovery source: ```bash herdr plugin install owner/repo[/subdir...] ``` **Agent skill.** `SKILL.md` ships in the Herdr repo root and teaches a coding agent to *drive* Herdr — inspect panes/agents, split panes, run commands without stealing focus, wait for things to finish, start helper agents — using the `herdr` CLI when `HERDR_ENV=1` is set (proof it's running inside a Herdr-managed pane). It is a plain instruction file, not an app or plugin. Install it with: ```bash npx skills add ogulcancelik/herdr --skill herdr -g ``` (`-g` installs globally for supported agents; omit for project-only). The manual fallback/source of truth is `https://github.com/ogulcancelik/herdr/blob/master/SKILL.md`. Its first rule is a guardrail: if `HERDR_ENV=1` isn't set, the agent must say it isn't running inside a Herdr pane and stop — preventing an agent outside Herdr from controlling a session it doesn't own. The skill covers pane IDs, `pane split`/`run`/`read`/`wait-output`, `agent wait`, workspace/tab commands, and coordination recipes (see [[concepts/agent-automation-and-socket-api]]). Herdr also serves a *different* file, `herdr.dev/agent-guide.md`, for the opposite job: an agent helping a **human** learn/set up/troubleshoot Herdr, rather than an agent operating it. ## Key Parameters - Plugin manifest required fields: `id`, `name`, `version`, `min_herdr_version`; `platforms` list; item-level `platforms` override the plugin-level list. - `HERDR_BIN_PATH` — preferred portable way for plugins to call back into Herdr. - `herdr-plugin` — the exact GitHub topic that drives marketplace listing. - `HERDR_ENV=1` — the precondition the agent skill checks before issuing any control command. ## When To Use Reach for a **plugin** when you want a reusable, installable workflow package with its own manifest, build step, and lifecycle (startup hooks, actions, panes, link handlers). Use the **marketplace** purely for discovery — installation is identical whether you found a plugin there or from a README link. Install the **agent skill** into any coding agent (Claude Code or otherwise) that should be able to drive Herdr itself — split panes, launch sibling agents, wait on output — as opposed to a plugin, which extends Herdr's own UI/behavior. ## Risks & Pitfalls - Plugins are unsandboxed and unreviewed by Herdr, whether installed directly or discovered via the marketplace (which is just a tagged-repo index, not a vetted catalog) — vet the manifest and scripts before installing, especially anything with `[[startup]]` hooks that run automatically. - Installing over a locally linked plugin is refused — unlink or uninstall the local copy first. - There's no `plugin update` in v1; reinstalling from GitHub is how a managed plugin gets refreshed. - The agent skill's `HERDR_ENV=1` guardrail is a safety boundary, not just a convenience check — don't bypass it when adapting the skill. ## Related Concepts - [[concepts/agent-automation-and-socket-api]] — the CLI/socket surface plugins and the agent skill both call into. - [[concepts/agents-and-integrations]] — OpenCode and Kilo integrations are themselves shipped as plugins. - [[concepts/configuration]] — plugin keybindings live in the same `[[keys.command]]` config surface as other bindings. ## Sources - raw/github_doc-docs-next-website-src-content-docs-plugins-mdx.md - raw/github_doc-docs-next-website-src-content-docs-marketplace-mdx.md - raw/github_doc-docs-next-website-src-content-docs-agent-skill-mdx.md - raw/github_doc-skill-md.md <!-- ===== herdr/wiki/concepts/troubleshooting.md ===== --> --- title: "Troubleshooting" type: concept tags: [troubleshooting, config, install] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_doc-docs-next-website-src-content-docs-troubleshooting-mdx.md"] confidence: high herdr_version: "v0.7.5" --- ## Definition This page covers Herdr's own official troubleshooting guidance for installation, terminal-input, session, keybinding, and remote-access problems. For a broader, community-sourced catalog of real bug reports and workarounds beyond this official list, see the separate [[syntheses/issues-casebook]]. ## How It Works Start every investigation with version and status: ```bash herdr -V herdr status ``` Also record OS, outer terminal name/version, whether the session is local or remote, and whether tmux is involved — these four facts explain most of the issues below. **CJK IME window misplaced / cursor flickers on Windows.** Herdr defaults to a cell-drawn cursor on native Windows and WSL because native cursors can flicker or show stale positions while ConPTY-based multiplexers repaint the screen — but a cell-drawn cursor can't provide the native cursor anchor IME composition UI needs. Fix: ```toml [ui] host_cursor = "native" ``` This restores the IME anchor but may reintroduce cursor movement artifacts during active output; revert with `host_cursor = "drawn"` or remove the setting for the Windows default. **Enter, Tab, or Backspace fires twice.** Older terminal versions can emit the release of these keys as the same bytes as the press when Kitty keyboard event reporting is enabled; Herdr cannot distinguish the duplicate bytes once sent. Update the outer terminal: | Terminal | Minimum fixed version | | --- | --- | | kitty | 0.33.0 | | foot | 1.20.0 | | Alacritty | 0.15.0 | Especially common on long-term-support Linux distro terminal packages. See Herdr issue #1116 for confirmed boundary captures; if it persists on a current version, report the exact terminal version and whether it also happens outside Herdr. **Option+Left/Right inserts `;3D`/`;3C`.** Terminals send Alt+Left/Right as `ESC[1;3D`/`ESC[1;3C`. On macOS, Option must first be configured as Alt in the outer terminal; if the shell doesn't bind these, zsh may print the leftover characters. Herdr and tmux both pass the original modified-arrow sequence through unchanged — this is deliberate, since terminal apps may use Alt+Left/Right directly. Fix in zsh: ```zsh bindkey $'\e[1;3D' backward-word bindkey $'\e[1;3C' forward-word ``` kitty's automatic zsh integration only binds these for shells kitty starts directly, not shells started by a multiplexer — follow kitty's manual shell-integration instructions, or map the keys before they reach the shell: ```text map alt+left send_text all \x1bb map alt+right send_text all \x1bf ``` See Herdr issue #1370 for the investigation. **Herdr updated but the running session is still old.** Updating the binary doesn't always replace a compatible server already running. Check `herdr status`; to force the update: ```bash herdr server stop herdr ``` This exits pane processes — named sessions use `herdr session stop <name>` instead. See [[concepts/install-and-quickstart]] for updater/package-manager/live-handoff behavior. **`herdr` command not found.** Restart the terminal to reload its environment, then confirm the install directory is on `PATH`; package-manager installs must be updated and exposed via that package manager. **A direct keybinding does nothing.** The OS or outer terminal may be consuming the chord before Herdr sees it — free the chord at that layer or choose another binding. See [[concepts/panes-and-keyboard]] for known conflicts and prefix-free defaults. **Remote attach cannot authenticate.** First confirm plain `ssh <host>` works. For a passphrase-protected key in a non-interactive shell, CI job, or mobile terminal, load it into `ssh-agent` before `herdr --remote` (see [[concepts/persistence-and-remote]]). **Diagnostic logs.** Herdr logs live in `~/.config/herdr/` by default: ```text herdr.log herdr-client.log herdr-server.log ``` Set `HERDR_LOG=herdr=debug` for more detail; include the current log plus rotated siblings when reporting a problem. See [[concepts/configuration]] for the logs config surface. ## Key Parameters - `[ui] host_cursor = "native" | "drawn"` — IME anchor vs. flicker-free cursor tradeoff on Windows/WSL. - `HERDR_LOG=herdr=debug` — verbose logging. - `herdr server stop` / `herdr session stop <name>` — force a stale server to exit before relaunching. ## When To Use Work through this page before filing a bug report or digging into the community issue tracker: most reported oddities trace back to one of these five categories (IME/cursor, double keypress, modified-arrow encoding, stale running server, PATH). If the symptom doesn't match anything here, or you want prior-art on a specific bug signature, check [[syntheses/issues-casebook]] next. ## Risks & Pitfalls - `[ui] host_cursor = "native"` trades away the visually stable cursor for a working IME anchor — don't leave it on if you don't need CJK IME composition. - Herdr deliberately does not rewrite modified-arrow sequences, so "fixing" Option+Left/Right requires terminal- or shell-side configuration, not a Herdr setting. - Stopping a server to force-update it terminates that server's pane processes — use the named-session variant to avoid taking down the wrong session. ## Related Concepts - [[concepts/persistence-and-remote]] — remote-attach authentication and stale-server-after-update both stem from the persistence model. - [[concepts/agents-and-integrations]] — `herdr agent explain` is the analogous diagnostic tool for agent-state problems, covered there rather than here. - [[syntheses/issues-casebook]] — the deeper, community-sourced bug catalog this page defers to. ## Sources - raw/github_doc-docs-next-website-src-content-docs-troubleshooting-mdx.md <!-- ===== herdr/wiki/log.md ===== --> --- title: "Activity Log" type: log --- # Activity Log Append-only record of all wiki changes. ## Format Each entry follows this format: ``` ### YYYY-MM-DD HH:MM — [Action Type] - **Source/Trigger**: what initiated the action - **Pages created**: list of new pages - **Pages updated**: list of updated pages - **Notes**: any contradictions flagged, decisions made ``` --- ### 2026-04-08 00:00 — Setup - **Source/Trigger**: Repository initialized - **Pages created**: index.md, log.md, dashboard.md, analytics.md, flashcards.md - **Pages updated**: none - **Notes**: Empty knowledge base ready for first source ingestion <!-- ===== herdr/wiki/summaries/release-digest.md ===== --> --- title: "Release Digest" type: summary tags: [install, config, cli, troubleshooting] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_release-v0-7-5.md", "raw/github_release-v0-7-4.md", "raw/github_release-v0-7-3.md", "raw/github_release-v0-7-2.md", "raw/github_release-v0-7-1.md", "raw/github_release-v0-7-0.md", "raw/github_release-v0-6-10.md", "raw/github_release-v0-6-9.md", "raw/github_release-preview-build-2026-07-21-0f10e1453a7f.md", "raw/github_release-preview-build-2026-07-17-813fec141faa.md", "raw/github_release-preview-build-2026-07-16-e907e6a36646.md", "raw/github_release-preview-build-2026-07-15-50aaa2ec046e.md", "raw/github_release-preview-build-2026-07-07-f5354780e4ef.md", "raw/github_release-preview-build-2026-07-06-4dae557eefd9.md", "raw/github_release-preview-build-2026-06-30-3459798b606d.md", "raw/github_release-preview-build-2026-06-25-7811d84f15f1.md", "raw/github_release-preview-build-2026-06-22-24c7377de01c.md", "raw/github_release-preview-build-2026-06-15-517ca8163f7c.md", "raw/github_release-preview-build-2026-06-12-7ba4bfe90e7a.md", "raw/github_release-preview-build-2026-06-10-7d6eaf5f26d1.md", "raw/github_doc-changelog-md.md"] confidence: high herdr_version: "v0.7.5" --- # Release Digest ## Key Points ### Current version The current **stable** release is **v0.7.5**, published 2026-07-21. The current **preview** build on top of it is **preview-2026-07-21-0f10e1453a7f** (published the same day, base stable `v0.7.5`), which at this writing only carries a docs-sidebar fix — no functional changes queued yet beyond stable. All version/build numbers in this digest come directly from the fetched release mirrors and `raw/github_doc-changelog-md.md`; treat `0.7.5` as the wiki's baseline `herdr_version` for pages describing current behavior. ### The release model: two channels, different cadences Herdr ships two parallel tracks, confirmed directly from the mirrors: - **Stable channel** — versioned tags (`vX.Y.Z`) on GitHub Releases, matching entries in `CHANGELOG.md`. These are the default install target and the only channel most users see. Cadence over the fetched window (2026-06-10 through 2026-07-21) was roughly **one stable release every 4–10 days**, with three exceptions that shipped as same-day or next-day **hotfixes** for a severe regression (see below). - **Preview channel** — opt-in via `herdr channel set preview` (introduced v0.6.7). Preview releases are **date-stamped, commit-stamped builds cut directly from `master`** (e.g. `preview-2026-07-21-0f10e1453a7f`, named `preview-<date>-<short-commit>`), not semantic versions. Each preview release mirror explicitly declares its **`Base stable:` tag** and a GitHub `compare` URL against either the previous stable tag or the previous preview build. Preview builds appeared far more often than stable ones — sometimes multiple times in the same week (e.g. three preview builds in the 11 days between v0.7.4 and v0.7.5: 2026-07-15, 2026-07-16, 2026-07-17) — functioning as a rolling integration/staging channel where individual fixes land and get user-tested before being bundled into the next stable tag. - Individual GitHub issues are frequently annotated with bot comments like `herdr:pending-release`, `herdr:preview-released:<tag>`, and `herdr:released:<version>`, which is how a fix's actual shipping status can be traced across the two channels (see [[syntheses/issues-casebook]] for many examples of fixes that reached preview well before — or in a few cases only reached — a stable tag). - This cadence itself changed over the project's life: v0.6.7's changelog explicitly frames the preview channel as part of a deliberate move "toward less frequent, more stable releases" — i.e. the preview channel exists specifically so stable tags could slow down without slowing down user access to fixes. ### Hotfix pattern Three stable releases in the fetched window were explicit, narrowly-scoped hotfixes for a single severe regression in the immediately preceding release, shipped same-day or within ~24h rather than on the normal cadence: - **v0.6.4** (hotfix for v0.6.3) — macOS server startup failures (`dup of fd N failed` / "Too many open files") once restored sessions crossed the default 256 `RLIMIT_NOFILE` ceiling around 40 live panes. - **v0.6.8** (hotfix for v0.6.7) — a server crash (segfault / integer overflow) triggered by pane output or persisted scrollback containing complex Unicode, emoji, or decomposed-accent graphemes. - **v0.6.10** (hotfix for v0.6.9) — a lifecycle-authority detection-reset loop (Pi/OpenCode) that flooded logs and drove high CPU/UI lag. Each hotfix release note explicitly says "This is a hotfix release for vX.Y.Z. See the vX.Y.Z notes for the full feature release," and each also correlates with a same-topic GitHub issue documented in [[syntheses/issues-casebook]] (#327, #453, #560 respectively). ### Breaking-change patterns Two recurring shapes of breaking change appear across the release history: 1. **Client/server protocol version bumps.** Herdr's client and server negotiate a protocol version; a bump means a running server from the old version must be stopped and restarted (or live-handed-off) before a new client can attach. Observed bumps: protocol 5 (v0.5.9), 7 (v0.5.11), 8 (v0.6.0), 9 (v0.6.1), 10 (v0.6.2), 11 (v0.6.3), 14 (v0.7.0, for `pane.move`). Release notes for each of these explicitly warn "Stop and restart any running vX.Y.Z server before attaching with this release." 2. **Keybinding/config semantics changes**, called out under a dedicated "Breaking Changes" heading: - v0.6.0 (**keybinding v2**) — removed the standalone `keys.quit` binding (folded into `keys.detach`), and introduced explicit trigger syntax (`prefix+c` vs `ctrl+alt+c`) that rejects bare printable direct bindings like `new_tab = "c"`. - v0.5.9 — moved `advanced.allow_nested` to `experimental.allow_nested`. - **v0.7.5** — plugins (including enabled state) became **global to the current user** instead of scoped per named Herdr session; anyone who installed a plugin only inside a named session on 0.7.3 has to reinstall/relink it. No other stable release in the fetched window carried a "Breaking Changes" heading — most releases are purely additive/fix-only, which is consistent with the "less frequent, more stable" cadence goal stated in v0.6.7. ## Digest of notable changes (newest first) - **v0.7.5** (2026-07-21) — Breaking: plugins are now user-global, not session-scoped. Added a live-agent CLI facade (`agent start` / `agent prompt` / `agent send-keys` / `agent wait` / `pane wait-output`, replacing the old top-level `wait` and `agent send`), declarative Agent view queries (`agent.view.set/clear`), plugin `[[startup]]` hooks, per-token sidebar row styling, `ui.sidebar_start_collapsed`, `ui.prompt_new_workspace_name`, macOS support for `HERDR_AGENT=<agent>`. Fixed: machine-readable `protocol_mismatch` CLI errors, orphaned `mpg123` sound processes, oversized-paste disconnects, 5s `agent_prompt_stalled` timeout, unknown-config-key reporting, several agent-status-detection bugs (Codex static titles, Grok working/blocked, OpenCode out-of-order events, Kimi question prompts, Pi settled-events), Windows named-pipe support for Pi/OMP/OpenCode/Kilo Code, `new_cwd = "follow"` correctness, Ceph/network-filesystem sidebar slowness, Windows idle-CPU sharing, scrollback-scroll wave effect, plugin live-handoff registry preservation (closes #893). See [[syntheses/issues-casebook]] for issues #1471, #1158, #943 resolved here. - **v0.7.4** (2026-07-15) — Added session-modal popup floating panes for plugins/custom commands (closes #1125), `ui.copy_on_select`, configurable sidebar row layouts + `row_gap`, copy-mode search (`/`, `?`, `n`/`N`), Maki agent support, a versioned config reference + troubleshooting guide. Fixed: collapsed-sidebar ordering, shifted indexed bindings, plugin-driven tab renames, Amp/Codex/Claude Code active-turn detection, Pi/OMP lifecycle races, WSL cursor default, live-handoff socket-path preservation, Windows installer config duplication, zombie custom-command children, several Windows input/console fixes (BrokenPipe on named pipes, non-POSIX login shells via `xonsh`). - **v0.7.3** (2026-07-08) — Fix-only release: session-navigator search-focus retention, socket-API done-status refresh, Windows cyclic-process-snapshot memory growth (closes #1083-adjacent pattern), cursor-hide-during-synchronized-redraw (closes #967), headless render URL-scan overhead, workspace-picker navigate-mode keys. - **v0.7.2** (2026-07-07) — Added MastraCode integration, `ui.sidebar_collapsed_mode = "hidden"`, `herdr completion(s) <shell>`, `session.snapshot`, `herdr api schema`, `layout.updated` events, pane scroll-metrics API, `herdr terminal session observe/control`, `ui.hide_tab_bar_when_single_tab` (closes #448), Japanese/Simplified Chinese docs. Fixed: Windows shifted-punctuation Kitty-mode input, Alt-Shift chords, Antigravity background-task detection, `herdr --remote` SSH error formatting, Windows named-pipe server stop, Grok Build detection (closes #1017), GitHub Copilot Esc-interrupt detection, undercurl rendering (closes #895, partially — color still lost), clipboard-image bridge scoping (closes #986), many Windows input-path fixes. - **v0.7.1** (2026-06-24) — Added independent `[update].version_check`/`manifest_check` toggles, Linux `HERDR_AGENT=<agent>` hint, `ui.pane_borders`/`ui.pane_gaps`. Changed: removed the Agents-panel workspace/all filter, keybinding-override displacement, worktree branch-checkout reuse, deferred worktree Git work off the render loop, scoped OMP/OpenCode/Pi/Devin lifecycle reports to the intended root process. Fixed: Windows Terminal multiline bracketed paste (closes part of #670/#556), local `Ctrl+V` vs clipboard-image-paste conflict, OSC 10/11 light/dark refresh, hook sequence-guard re-anchoring, OMP native session resume (closes #614's first pass), Copilot CLI blocked-prompt detection. - **v0.7.0** (2026-06-15) — Added local plugin v1 (`plugin.link/list/unlink/enable/disable`, manifest actions, event hooks, managed plugin panes), `herdr plugin install <owner>/<repo>`, Devin CLI detection (closes #606), `pane.move` + `herdr pane move`, zoomed-pane tab-bar marker. Changed: bumped client/server protocol to 14; public workspace/tab/pane ids became short stable handles (`w1`, `w1:t1`, `w1:p1`) that don't retarget after closure. Fixed: key-combo strings for `pane.send_keys`, unknown-config-section warnings, Claude Code `/clear`/`/resume` session-restore accuracy, F1–F4 and kitty-protocol numeric-keypad forwarding, pane-resize shrink direction, Windows cursor stability (closes #556's cursor half). - **v0.6.10** (2026-06-11, hotfix for v0.6.9) — Fixed the Pi/OpenCode lifecycle-authority detection-reset loop that flooded logs and drove high CPU (closes #560). - **v0.6.9** (2026-06-10) — Added remote agent-detection-manifest auto-updates, `herdr agent explain`, Kimi/Droid/Kilo/Cursor integration installs, directional pane swap (`prefix+shift+h/j/k/l`), `herdr pane zoom`, toast ergonomics + `notification.show`. Fixed: copy-mode scroll boundaries, stale clipboard-copy feedback, live workspace labels in the navigator, bare-repo worktree actions, flag-emoji/grapheme rendering, default-workspace-on-empty-start, libghostty-vt resize-reflow crash, mouse-click naming-prompt parity. - **v0.6.8** (2026-06-04, hotfix for v0.6.7) — Fixed the Unicode/emoji/decomposed-accent server crash (closes #453's initial report); mise-managed install updates; Claude Code thinking/streaming false-blocked flicker (closes part of #409); OpenCode-via-pnpm detection. - Earlier history (from `CHANGELOG.md`, v0.6.7 down to v0.5.3): introduction of the preview channel itself (v0.6.7) explicitly framed around slowing stable cadence; native agent session restore behind `[session] resume_agents_on_restore` (v0.6.3); session navigator at `prefix+g` (v0.6.3); vi-style copy mode (v0.6.5, closes #231); named persistent sessions and `herdr status` (v0.5.3); mobile layout for phone SSH (v0.5.5); `herdr --remote <ssh-target>` thin-client mode (v0.5.6). ## Relevant Concepts - [[concepts/herdr-overview]] - [[concepts/install-and-quickstart]] - [[concepts/configuration]] - [[concepts/cli-reference]] - [[concepts/agents-and-integrations]] - [[concepts/persistence-and-remote]] - [[concepts/plugins-and-marketplace]] - [[concepts/agent-automation-and-socket-api]] - [[concepts/troubleshooting]] - [[syntheses/issues-casebook]] ## Source Metadata - **Type**: GitHub Releases (20 mirrors: 8 stable tags v0.6.9 through v0.7.5, 12 date-stamped preview builds 2026-06-10 through 2026-07-21) + one GitHub doc mirror (`CHANGELOG.md`, covering v0.5.3 through v0.7.5) - **Project**: `ogulcancelik/herdr` - **Fetched**: 2026-07-22 - **Identifiers**: see the `sources` frontmatter list above for exact mirror filenames; each release mirror carries its own `source_url`, `tag`/`title`, and `published` timestamp in its own frontmatter. <!-- ===== herdr/wiki/syntheses/issues-casebook.md ===== --> --- title: "Issues Casebook" type: synthesis tags: [troubleshooting, agents, panes, remote, persistence, config, install] created: 2026-07-23 updated: 2026-07-23 sources: ["raw/github_issue-agent-status-latches-on-working-and-never-returns-to-idle-af.md", "raw/github_issue-relicensing-herdr-from-agpl-3-0-to-apache-2-0-i-need-your-pe.md", "raw/github_issue-windows-support.md", "raw/github_issue-omp-lifecycle-hook-may-not-reacquire-after-exit-and-rerun-in.md", "raw/github_issue-windows-herdr-fires-curl-cmd-windows-periodically.md", "raw/github_issue-omp-oh-my-pi-integration-says-it-s-always-idle-grounding-wit.md", "raw/github_issue-image-support.md", "raw/github_issue-spurious-characters-written-to-command-line-of-new-workspace.md", "raw/github_issue-nothing-works-when-starting-herdr-in-remote-session.md", "raw/github_issue-improve-agent-panel-row-layout.md", "raw/github_issue-option-to-hide-the-tab-bar-when-a-workspace-has-only-one-tab.md", "raw/github_issue-pasting-multiline-strings-auto-submits-each-line.md", "raw/github_issue-macos-switch-ascii-input-source-in-prefix-switches-the-wrong.md", "raw/github_issue-cursor-flickers-rapidly-across-the-whole-ui-while-any-agent-.md", "raw/github_issue-connecting-to-two-separate-remote-sessions-without-name-conf.md", "raw/github_issue-enter-backspace-still-double-under-kitty-keyboard-protocol-o.md", "raw/github_issue-temporary-floating-popup-panes-for-plugins.md", "raw/github_issue-server-crashes-with-sigabrt-in-headlessserver-render-and-str.md", "raw/github_issue-keys-not-registering-under-ghostty-over-ssh.md", "raw/github_issue-crash-with-exception-code-0xc0000409.md", "raw/github_issue-macos-nix-build-fails.md", "raw/github_issue-bug-mouse-movement-leaks-raw-ansi-escape-sequences-coordinat.md", "raw/github_issue-copy-on-select-false-disables-text-selection-entirely-instea.md", "raw/github_issue-stuttering-or-even-freezing-when-scrolling-window-history-he.md", "raw/github_issue-agent-status-flickers-working-blocked-while-claude-code-is-t.md", "raw/github_issue-ctrl-click-to-open-urls-in-panes.md", "raw/github_issue-cpu-usage-higher-than-expected-esp-on-idle.md", "raw/github_issue-grok-panes-show-done-idle-while-working-blocked-on-user-inpu.md", "raw/github_issue-mouse-click-to-switch-tabs-workspaces-does-not-update-ui-on-.md", "raw/github_issue-herdr-remote-not-detecting-already-installed-on-server.md", "raw/github_issue-windows-idle-server-cpu-scales-with-pane-count-0-15-0-2-core.md", "raw/github_issue-alt-screen-tui-full-viewport-repaints-stall-the-child-s-pty-.md", "raw/github_issue-back-and-forth.md", "raw/github_issue-wsl2-clipboard-history-win-v-does-not-work-when-copying-from.md", "raw/github_issue-copying-text-does-not-work-in-ampcode.md", "raw/github_issue-shift-enter-for-newline-doesn-t-work-in-pi.md", "raw/github_issue-v0-6-3-new-pane-spawns-fail-with-dup-of-fd-n-failed-after-re.md", "raw/github_issue-cursor-flashing-in-windows-and-pasting-multi-line-auto-submi.md", "raw/github_issue-unfocused-panes-don-t-update-status-agent-status-stays-stale.md", "raw/github_issue-codex-integration-v6-does-not-restore-session-after-server-r.md", "raw/github_issue-focused-pane-cursor-flickers-whenever-a-sidebar-agent-spinne.md", "raw/github_issue-pane-keeps-a-previous-agent-s-session-forever-when-that-agen.md", "raw/github_issue-add-native-agent-detection-for-kiro-cli.md", "raw/github_issue-chinese-ime-composition-causes-pane-rendering-artifacts.md", "raw/github_issue-claude-code-workflow-runs-show-idle-while-sub-agents-are-sti.md", "raw/github_issue-feature-request-add-tmux-style-double-click-word-copy.md", "raw/github_issue-bug-opencode-integration-falsely-reports-idle-state-while-ag.md", "raw/github_issue-feature-request-showing-the-process-title-from-claude.md", "raw/github_issue-server-segfaults-on-unicode-pane-output-in-0-6-7.md", "raw/github_issue-add-a-vi-style-copy-mode-for-scrollback-selection-similar-to.md", "raw/github_issue-idea-support-devin-cli-as-a-first-class-agent-in-herdr.md", "raw/github_issue-massive-lag-and-high-cpu-usage-in-v0-6-9.md", "raw/github_issue-new-space-doesn-t-synchronize-with-shell.md", "raw/github_issue-wrong-status-for-opencode-agents.md", "raw/github_issue-terminal-freezes-on-agent-exit-ctrl-c-exit-and-workspace-is-.md", "raw/github_issue-undercurl-renders-as-plain-underline-in-herdr.md", "raw/github_issue-windows-backspace-does-not-delete-inside-pi-prompt.md", "raw/github_issue-live-handoff-drops-installed-plugin-registry-and-later-plugi.md", "raw/github_issue-local-clipboard-image-paste-is-broken-after-ctrl-v-was-unbou.md", "raw/github_issue-windows-arrows-and-esc-in-pi-not-working.md"] confidence: high herdr_version: "v0.7.5" --- # Issues Casebook This page is the wiki's community troubleshooting layer: every GitHub issue mirror in `raw/` (60 issues), read in full and organized by symptom area. For each solved or partially-solved case it gives **symptom → root cause → fix (verbatim where the maintainer or a contributor stated one) → citing issue number**. For open/unresolved patterns it says so plainly — "reported, not resolved" — rather than implying a fix exists. A compact "requested features" paragraph closes the page for pure feature requests that carried no diagnostic content. Case count: **48 diagnosed bug/behavior cases** (symptom→cause→fix write-ups below) + **11 feature requests** (compact closing paragraph) + **1 governance/licensing thread** (noted separately, not a bug) = **60 issues covered**, matching every mirror in `raw/github_issue-*.md`. A cross-cutting theme worth stating up front: Herdr's agent-status detection is fundamentally **screen-based** (it reads what's rendered in the pane) layered with **hook/lifecycle-based** reporting from official per-agent integrations (Claude Code, Codex, OMP, OpenCode, Pi, Kimi, Droid, Kilo Code, Cursor, MastraCode, Devin). Nearly every case in the "agent status & detection" group below is a variant of these two systems disagreeing, racing, or losing information — this is the single most repeated failure shape in the whole issue history. See [[concepts/agents-and-integrations]] for the underlying design this section documents empirically. ## Comparison The table below is the fast-lookup index into the detailed write-ups; "Status" reflects what the issue thread itself shows, not a later release note this KB couldn't cross-check. | # | Symptom (short) | Area | Status per thread | |---|---|---|---| | #198 | Status latches on `working`, never returns to idle | agent status | Fixed on master, queued (unconfirmed shipped) | | #614 | OMP doesn't reacquire lifecycle authority after exit/rerun | agent status | Root cause found; fix proposed, not confirmed merged | | #1310 | OMP integration always shows idle | agent status | Fixed (stale extension file); pending release | | #409 | Claude Code flickers working↔blocked while thinking | agent status | Partially fixed; user-specific recurrence reported | | #1017 | Grok panes show done/idle while working/blocked | agent status | Fixed; released to preview | | #846 | Unfocused pane status frozen at stale value | agent status | Root cause: scroll position hides state from screen-detector; open engine gap | | #856 | Codex v6 doesn't restore session after restart | agent status | Open; diagnosing hook environment | | #943 | Pane keeps stale prior agent's session forever | agent status | Fixed, then an asymmetry follow-up fixed too | | #509 | Claude Code workflow parent shows idle while sub-agents run | agent status | Open; maintainer rebuilding detection system | | #351 | OpenCode falsely reports idle while working | agent status | Fixed; partial recurrence reported afterward | | #560 | Massive lag/high CPU in v0.6.9 (event storm) | agent status/perf | Fixed (hotfix v0.6.10) | | #765 | Wrong status for OpenCode sub-agents (false "done") | agent status | Fixed; separate stuck-working recurrence noted | | #306 | Spurious `11;rgb:...` chars in new workspace | panes/rendering | Fixed (released v0.6.3) | | #670 | Multiline paste auto-submits each line | panes/rendering | Fixed on master; Windows-specific case lingered | | #930 | Cursor flickers UI-wide while any agent works | panes/rendering | Fixed (v0.7.2); reproduced again in v0.7.3 | | #276 | Server SIGABRT / invalid free of `FrameData` | panes/rendering | Fixed on master after long forensic thread | | #1382 | Mouse movement leaks raw SGR escape sequences | panes/rendering | Open; debug capture requested | | #1471 | `copy_on_select = false` disables selection entirely | panes/rendering | Fixed (released v0.7.5) | | #512 | Stuttering/freezing scrolling long pane history | panes/rendering | Partially herdr, partially Ghostty itself; mixed | | #1295 | Alt-screen TUI full-viewport repaint stalls PTY write | panes/rendering | Open; DECSET 2026 pass-through requested | | #29 | Copying text broken in Amp / some terminals | panes/rendering | Open; terminal-specific (Terminator, Konsole) | | #8 | Shift+Enter newline doesn't work in Pi | panes/rendering | Resolved — user's own Ghostty config artifact | | #967 | Focused-pane cursor flickers with sidebar spinner | panes/rendering | Fixed (released v0.7.3) | | #229 | Chinese IME composition causes rendering artifacts | panes/rendering | Reproduced; not IME-specific; no fix confirmed in thread | | #453 | Server segfault/panic on Unicode pane output | panes/rendering | Hotfixed (v0.6.8); partial recurrence on long sessions | | #895 | Undercurl renders as plain underline | panes/rendering | Shape fixed (v0.7.2); underline color still broken | | #986 | Local clipboard image paste broken after Ctrl+V unbound | panes/rendering | Clarified as expected behavior, not a bug | | #919 | New space/tab doesn't follow shell cwd | panes/rendering | Fixed on master; released to preview | | #312 | Nothing works starting herdr in remote SSH session | persistence/remote | Resolved — remote keybinding config mismatch | | #598 | Two unnamed `--remote` sessions collide | persistence/remote | Resolved — use explicit `--session` names | | #628 | Keys not registering under Ghostty over SSH | persistence/remote | Resolved — outdated remote binary | | #1201 | `herdr --remote` can't detect already-installed server binary | persistence/remote | Fixed on master; pending release | | #333 | WSL2 clipboard history (Win+V) empty after copy | persistence/remote | Fixed — prefer OSC 52 on WSL | | #893 | Live handoff drops installed plugin registry | persistence/remote | Fixed; released to preview | | #796 | Mouse click tab-switch doesn't update UI (macOS+Ghostty) | persistence/remote | Root cause: Mosh session interaction, not herdr | | #1468 | Windows: herdr fires curl.exe windows periodically | platform (Windows) | Partially fixed; occasional recurrence noted | | #774 | macOS ASCII-input-source switch hits wrong input source | platform (macOS) | Fixed for stale-cache case; IME edge case persists | | #1083 | Crash with exception code 0xc0000409 (Windows) | platform (Windows) | Open; awaiting crash-dump analysis | | #830 | macOS Nix build fails (`DarwinSdkNotFound`) | platform (Nix/macOS) | Fixed via upstream Nixpkgs PR | | #327 | New panes fail to spawn: `dup of fd N failed` (macOS) | platform (macOS) | Fixed (hotfix v0.6.4) | | #556 | Windows cursor always block-shaped + multiline paste | platform (Windows) | Cursor fixed (v0.7.0); paste bug persisted separately | | #907 | Windows: Backspace doesn't delete inside Pi prompt | platform (Windows) | Workaround confirmed; root fix pending | | #860 | Windows: terminal freezes + workspace deleted on agent exit | platform (Windows) | Fixed for one path; a second UI-close path still froze | | #1158 | Windows: idle server CPU scales with pane count | platform (Windows) | Fixed (foreground-snapshot sharing) | | #726 | CPU usage higher than expected, esp. idle | platform (perf, cross-OS) | Partially fixed; follow-on optimization continued | | #1533 | Windows: arrows/Esc don't work inside Pi | platform (Windows) | Root cause is upstream in Pi, not herdr | | #1116 | Enter/Backspace double under Kitty keyboard protocol | platform (terminal protocol) | Root cause found (Kitty legacy-key release bytes); fix branch offered | ## Analysis — cases by symptom area ### Agent status & detection (12 cases) **#198 — Agent status latches on `working` and never returns to idle.** Symptom: after a Claude Code turn completes cleanly (Stop hook fires, no process running), the pane stays `working` indefinitely; a control pane in the same workspace correctly shows `idle`. Root cause (maintainer, comment 2): a Claude Code hooks race condition where `PostToolUse` can arrive *after* the turn-ending `Stop` event, re-pinning the state to `working`. Fix: "Implemented on master and queued for the next release" — not confirmed shipped in the mirror itself. *Cite: `raw/github_issue-agent-status-latches-on-working-and-never-returns-to-idle-af.md`.* **#614 — OMP lifecycle hook may not reacquire after exit and rerun in same pane.** Symptom: after exiting and restarting `omp` in the same pane, OMP can fail to reappear in the Agents panel even though the extension is installed and reporting. Root cause (community-traced, confirmed by author in final comment): `release_agent_with_mutation` adds a permanent suppression entry keyed on `(None, None)` when OMP's `session_shutdown` hook calls `releaseAgent()`; because OMP is not in `is_official_agent_source`, it never carries a session id that would let the suppression clear on the next `report_agent`, so it stays suppressed until a full server restart. Fix path proposed by the extension author: server-side, either clear suppression on a fresh `report_agent` for non-official sources, or add OMP to `is_official_agent_source` and have it send a session id (preferred — keeps OMP's lifecycle authority intact). Two client-side workarounds were tried and found incomplete: dropping `releaseAgent()` (partially worked, one user reported it did not) and renaming the source to `omp:lifecycle` (avoids suppression but drops OMP out of `full_lifecycle_hook_authority`, since OMP ships no screen manifest to fall back on). Not confirmed merged in the mirror. *Cite: `raw/github_issue-omp-lifecycle-hook-may-not-reacquire-after-exit-and-rerun-in.md`.* **#1310 — OMP integration says it's always idle.** Symptom: OMP panes read `idle` regardless of actual activity; `herdr agent explain` even shows the integration-reported state (`working`) conflicting with the screen/rule fallback state (`idle`, `fallback_reason: default_known_agent_idle_fallback`). Root cause (maintainer): a versioning bug — the OMP extension was fixed in an earlier PR (#984) and the fixed asset shipped in v0.7.2/v0.7.3, but the integration-version bump was missed, so `herdr integration status` reported "current" while the stale `.ts` file stayed installed. Fix: re-run `herdr integration install omp`, then `/reload` or restart `omp` (install unconditionally overwrites). One user reported the fix didn't resolve it even after a clean reinstall on 0.7.3 — "Implemented on master and queued for the next release" is the final status. *Cite: `raw/github_issue-omp-oh-my-pi-integration-says-it-s-always-idle-grounding-wit.md`.* **#409 — Agent status flickers working↔blocked while Claude Code is thinking/streaming.** Symptom: polling during a thinking phase showed `blocked` in 277 of 390 samples (~71%) while nothing was actually blocked. Root cause: the bundled Claude Code integration (hooks v4) had no working-signal for the thinking-spinner UI (`✽ Transmuting… (2m 21s · …)`), so the screen-state fallback misread it. Maintainer response: "please for now uninstall claude integration until next release" — then a release removed reliance on Claude's "broken hooks." One user still saw the same symptom after upgrading, traced to a company status-line plugin interfering with detection. *Cite: `raw/github_issue-agent-status-flickers-working-blocked-while-claude-code-is-t.md`.* **#1017 — Grok panes show `done/idle` while working/blocked on user input.** Symptom: Grok Build (0.2.82) panes flip back to `done` after a few seconds during long subagent/shell-command turns, and permission/question prompts read as `idle` instead of `blocked`. Root cause/fix: a contributor (@TonyxSun) built a verified local fix and opened PR #1055 after maintainer approval; `<!-- herdr:preview-released:preview-2026-06-22-24c7377de01c -->` confirms it shipped to preview. *Cite: `raw/github_issue-grok-panes-show-done-idle-while-working-blocked-on-user-inpu.md`.* **#846 — Unfocused panes don't update status; approval shows idle until focused.** This is the casebook's clearest example of a genuinely reported-not-resolved engine gap layered under a user misconfiguration. First pass: the reporter traced their own symptom to a *local* custom detection rule (`skip_state_update` keyed on the "Jump to bottom" scroll overlay, added to stop flicker) that froze publishing before an out-of-band OSC idle signal could override it — their own bug, not stock herdr. But a follow-up comment reproduced the **underlying pattern on stock herdr with zero overrides**: scrolling a Claude pane's transcript up moves the live status/approval region out of the screen area herdr scans, so `herdr agent explain` returns `matched_rule: null` → `default_known_agent_idle_fallback`, i.e. a pane genuinely waiting on an approval reads as `idle`/done purely because of scroll position. Maintainer's final comment confirms this is "expected for claude code's newer tui/alt-screen style" — screen-based detection cannot see state that the agent's own alt-screen UI has scrolled out of view. **No fix shipped in the thread; this is an acknowledged limitation of screen-based detection**, not a bug slated for a patch. *Cite: `raw/github_issue-unfocused-panes-don-t-update-status-agent-status-stays-stale.md`.* **#856 — Codex integration v6 does not restore session after server restart.** Symptom: the Codex pane's `agent_session` field never populates in `session.json`, so server restarts always start a fresh Codex session (unlike Claude/OpenCode, which restore correctly). Root cause under active diagnosis at thread's end: the maintainer is checking whether `codex /hooks` shows `SessionStart` as trusted/active (confirmed yes) and whether the hook subprocess can actually reach herdr — specifically whether `HERDR_SOCKET_PATH`/`HERDR_PANE_ID`/`python3` are present in the Codex pane's environment (the hook exits silently if any is missing). Multiple users confirmed the same symptom; env-var dumps were in progress. **Open — no fix confirmed at time of the mirror.** *Cite: `raw/github_issue-codex-integration-v6-does-not-restore-session-after-server-r.md`.* **#943 — Pane keeps a previous agent's session forever when that agent's exit was never observed.** Symptom: a pane that ran Codex, then had the server restarted mid-session (so Codex's exit was never observed), then ran Claude for hours — kept reporting the *stale Codex* `agent_session`; `pane.release-agent` returned `ok` but changed nothing. Fix (maintainer): implemented and closed quickly ("congrats on finding a very good edge case"). A follow-up from another user found the fix was **asymmetric**: a freshly-launched Claude couldn't displace a stale Codex session because Claude's `SessionStart` source is `startup`, which the fix's `session_start_source_allows_session_replacement` gate excluded (Codex allows `startup`, Claude didn't) — so the different-owner takeover worked one direction but not the other. Maintainer shipped a second fix (commit `797981c`) gating the takeover on "genuine session start + foreground confirmation" instead of the same-owner replacement matrix, confirmed released to preview `2026-07-06-4dae557eefd9`. *Cite: `raw/github_issue-pane-keeps-a-previous-agent-s-session-forever-when-that-agen.md`.* **#509 — Claude Code "workflow" runs show idle while sub-agents are still working.** Symptom: a Claude Code parent that spawns long-running sub-agents and goes passive between them (no PTY output) decays to `idle` because the integration (`herdr-agent-state.sh` v5) binds `SessionStart` but ignores `SubagentStop`, and the fallback PTY-output heuristic has nothing to key on. A contributor identified the exact spinner-detection gap that causes this class of miss (Claude's live spinner glyph `●` + `…` + token counter isn't matched by `has_working_chrome`) and offered a tested fix (closed/reopened as PR #513 due to a contributing-guide mixup). Maintainer's final stance: "i'm working on a different agent detection system for now" — i.e. **acknowledged as an open, actively-being-redesigned problem**, not patched in place. *Cite: `raw/github_issue-claude-code-workflow-runs-show-idle-while-sub-agents-are-sti.md`.* **#351 — OpenCode integration falsely reports idle state while agent is working.** Root cause (reporter, with a working fix branch): the OpenCode plugin mapped `session.updated` → `idle`, but `session.updated` is a sync/projection event that fires on *any* session metadata patch (touch, title generation, summary, revert, permission) during an active run — it repeatedly overrode the authoritative `session.status` busy signal. Fix: ignore `session.created`/`session.updated` entirely and rely solely on `session.status` (and the deprecated `session.idle`). Released in v0.6.6. Multiple users reported the underlying flakiness persisted afterward, specifically around sub-agent detection ("done" showing while a sub-agent is still running), which the maintainer asked to be filed as a separate issue rather than reopening this one. *Cite: `raw/github_issue-bug-opencode-integration-falsely-reports-idle-state-while-ag.md`.* **#560 — Massive lag and high CPU usage in v0.6.9.** Symptom: herdr server spikes to 100% CPU and the whole UI freezes for about a minute whenever a new agent session starts, especially with Pi/pi-fff loading large repos; server logs show an `agent changed … previous_agent=None agent=Some(...)` line repeating thousands of times per second. Root cause (community-traced by @dzevs): `sync_full_lifecycle_authority_detection_pauses()` called `set_full_lifecycle_authority_active(true)` on every app event; the setter reset-notified even on a no-op `true → true` transition, rebuilding `AgentDetectionPresence` from `None`, and the PTY-first process probe then re-ran *before* the lifecycle-authority gate, re-detecting the agent and emitting another spurious `None → Some(agent)` change — an infinite thrash loop. Fix (verbatim from the patch description): "make the lifecycle-authority setter idempotent; skip routine pty/process probing while full lifecycle hook authority is active; preserve process-exit and release/reacquire probes." Released as the same-day hotfix v0.6.10. *Cite: `raw/github_issue-massive-lag-and-high-cpu-usage-in-v0-6-9.md`.* **#765 — Wrong status for OpenCode agents (false "done" on sub-agent completion, stuck loading).** Symptom: herdr sends a "task completed" notification when only one OpenCode sub-agent finishes (not the whole job), and separately OpenCode panes sometimes load forever. Fix: the sub-agent-completion false-positive was reproduced and fixed, released in v0.7.1. The reporter confirmed sub-agents were fixed but "it still gets stuck in the working status forever (sometimes)" — an **unresolved recurrence** with no confirmed root cause at thread's end. *Cite: `raw/github_issue-wrong-status-for-opencode-agents.md`.* ### Panes, rendering & PTY (16 cases) **#306 — Spurious characters written to command line of new workspaces.** Symptom: creating a new workspace deposits literal text like `11;rgb:2828/2a2a/3636^C` at the shell prompt. Root cause: an OSC 11 (background-color query) reply from the pane's pager/tool (`jj` in the reporter's case) arriving in a way herdr didn't fully absorb, leaking the raw escape reply as text. Fixed, released in v0.6.3. *Cite: `raw/github_issue-spurious-characters-written-to-command-line-of-new-workspace.md`.* **#670 — Pasting multiline strings auto-submits each line.** Symptom: pasting multiple lines into Oh My Pi (and other REPLs/agents) submits the first line immediately and queues the rest as separate "prompt steers" instead of one paste. Fixed on master for the general case; a related but separately-tracked Windows case (Windows Terminal specifically, see #556) needed its own fix. Workaround offered in-thread: press `ctrl+g` to open an external editor, paste there, save and close. *Cite: `raw/github_issue-pasting-multiline-strings-auto-submits-each-line.md`.* **#930 — Cursor flickers rapidly across the whole UI while any agent is working.** Symptom: the terminal cursor flickers/disappears rapidly in *every* workspace/tab/pane — not just the one running the agent — for as long as any agent shows `working`; `cursor_blink_rate = 0` in WezTerm does not stop it. Fixed, released to preview `2026-07-06-4dae557eefd9` then to stable v0.7.2. One user reproduced the same symptom again in v0.7.3 — a related-but-distinct root cause was later isolated and fixed under #967 (below), which the maintainer's v0.7.3 fix only partially covered. *Cite: `raw/github_issue-cursor-flickers-rapidly-across-the-whole-ui-while-any-agent-.md`.* **#276 — Server crashes with SIGABRT in `HeadlessServer::render_and_stream` (invalid free of `FrameData`).** One of the longest forensic threads in the whole set. Symptom: deterministic `SIGABRT` from libmalloc reporting "pointer being freed was not allocated," always inside `drop_in_place::<FrameData>` called from `render_and_stream`, after 24–73h of uptime with ~45 panes and heavy Unicode/emoji/OSC-8 pane output. The reporter tracked **six crashes across three binaries (v0.5.10, v0.6.2, v0.6.5)** with identical crash signatures (module path moved `server::protocol`→`protocol::wire` across the v0.6.x reorg, but the `drop_in_place` inner offset stayed at +68 throughout) — conclusive evidence of one specific buggy `Drop` site rather than ambient heap corruption. Fixed on master; the reporter offered to test a pre-release build to confirm. *Cite: `raw/github_issue-server-crashes-with-sigabrt-in-headlessserver-render-and-str.md`.* **#1382 — Mouse movement leaks raw ANSI escape sequences/coordinates into the active terminal session.** Symptom: moving the mouse over an SSH-attached herdr session floods the shell prompt with raw XTerm mouse-tracking SGR fragments. Diagnosis narrowed via client logs to a recurring `WARN herdr::raw_input: flushing lone escape after input timeout` — a standalone `ESC` that arrives without its full mouse-report tail within the input timeout gets flushed as plain text, and the following SGR bytes then leak in as literal characters. Confirmed across Windows Terminal and PowerShell, in both connection orders (herdr-then-ssh and ssh-then-herdr). **Open at thread's end** — maintainer requested a `HERDR_LOG=herdr::raw_input=debug` capture of the exact bytes following the timed-out escape. *Cite: `raw/github_issue-bug-mouse-movement-leaks-raw-ansi-escape-sequences-coordinat.md`.* **#1471 — `copy_on_select = false` disables text selection entirely instead of just suppressing clipboard copy.** Root cause (traced precisely by a contributor): commit `46174563` gated `Selection::anchor()` itself on `copy_on_select` in `src/app/input/mouse.rs`, so no anchor was ever set on `MouseDown` and nothing could be extended on drag — the clipboard-write guard downstream was never reached because there was no selection to copy. Fix (verbatim diff from the issue): move the guard from the anchor call to the copy call — ```rust // Before: } else if !was_already_copied { self.copy_selection(...); } // After: } else if !was_already_copied && self.copy_on_select { self.copy_selection(...); } ``` and make `Selection::anchor()` unconditional again. Released in v0.7.5. A follow-up comment noted the double-click-copy path and manual Ctrl+C/Cmd+C copy still had incomplete behavior per a linked discussion — flagged, not necessarily fully closed. *Cite: `raw/github_issue-copy-on-select-false-disables-text-selection-entirely-instea.md`.* **#512 — Stuttering or freezing when scrolling window history; herdr CPU spikes to 100%.** Notable for how it resolved: the maintainer reproduced the *same* CPU spike scrolling plain `ls` output directly in raw Ghostty with no herdr involved at all, and asked the reporter to run a controlled `seq 1 50000` + scroll test outside herdr. The reporter's result (13% max CPU, recorded on video) showed the effect was much smaller outside herdr than inside it — so the underlying scroll-rendering cost is **partly a Ghostty/macOS-Tahoe-generic cost and partly a herdr-specific scrollback-rendering cost layered on top** (the maintainer cross-references #283's "ANSI diff path treating scrollback movement as many changed cells," the same mechanism implicated in #1295 below). Maintainer's close: "found some problems regarding macos tahoe problems with scroll/ghostty and some more optimizations herdr can have" — a mixed, partially-external finding rather than a single clean herdr bug. *Cite: `raw/github_issue-stuttering-or-even-freezing-when-scrolling-window-history-he.md`.* **#1295 — Alt-screen TUI full-viewport repaints stall the child's PTY write (40–500ms/frame).** Symptom: a ratatui-based pane app repainting its whole viewport during fast mouse-wheel scrolling stalls its own PTY write for 40–500ms per frame inside a herdr pane, while the identical binary flushes in under 1ms in iTerm2/Terminal.app directly. Diagnosis (reporter, with instrumented render-vs-flush timing): render time is microseconds; the stall is entirely in the flush (the write returning), and it scales with the number of distinct SGR runs in the changed region, not just cell count. This is framed as the same underlying compositor cost as #283 and #512 but manifesting as PTY backpressure to the *child* rather than a visible "wave." Two plugin-pane authors corroborated the exact stall independently and both requested Herdr **honor `DECSET 2026` (synchronized output)** pass-through from child PTYs so well-behaved TUIs could batch a worst-case frame atomically. Maintainer could not reproduce with the reporter's own tool at first (max 2.6ms observed); the reporter then supplied a stripped reproducer branch with the coalescing workaround reverted, isolating the exact stall. **Open at thread's end**, reopening requested. *Cite: `raw/github_issue-alt-screen-tui-full-viewport-repaints-stall-the-child-s-pty-.md`.* **#29 — Copying text does not work in Amp (ampcode).** Symptom: selecting text and waiting for or triggering copy (toast, Cmd+C) does nothing; the same problem was found to affect the plain console (no agent at all) on Terminator and Konsole, where selection auto-clears the instant it's made and double-click-drag is required instead of double-click alone. Maintainer said a fix should be included in a later update; the reporter (who lacked reopen permission) confirmed it was **still broken** on the latest version they could test, on Terminator and Konsole specifically. **Open/terminal-specific — not confirmed resolved.** *Cite: `raw/github_issue-copying-text-does-not-work-in-ampcode.md`.* **#8 — Shift+Enter for newline doesn't work in Pi.** Root cause, found via a byte-level probe script the maintainer had the reporter run inside vs. outside herdr and inside vs. outside tmux: Ghostty's *own* config had `keybind = shift+enter=text:\\n` — the reporter didn't know this had been silently added, and traced it (with the maintainer) to Claude Code's own "terminal setup" routine, which auto-inserts that Ghostty keybinding as a hidden side effect. Not a herdr bug at all — removing the injected Ghostty keybinding fixed it. The maintainer also fixed an unrelated parsing bug Claude Code's setup routine had incidentally surfaced, in the same release. *Cite: `raw/github_issue-shift-enter-for-newline-doesn-t-work-in-pi.md`.* **#967 — Focused-pane cursor flickers whenever a sidebar agent spinner is animating.** Symptom: the hardware cursor in the *focused* pane flickers in lockstep with an unrelated sidebar agent-status spinner, even though tmux with synchronized-output support (`terminal-features 'xterm*:sync'`) shows a steady cursor under equivalent load. Root cause (traced precisely by a second reporter with a byte-level capture in a synchronized-output-aware pty harness): herdr's own repaint sequence emitted `ESC[?25l` (hide cursor) **before** `ESC[?2026h` (begin synchronized-output region) — so the cursor-hide instruction fell *outside* the atomic update, and an eager-repainting terminal (WezTerm) could legitimately paint a frame with the cursor hidden whenever the frame body arrived in a separate PTY read. Windows Terminal coalesces output before painting and didn't show it, which matched the symptom being terminal-specific. Fix: emit `?2026h` first and hide the cursor *inside* the synchronized region, dropping the redundant `?25h` right before the hide. Released to preview `2026-07-07-f5354780e4ef`, then stable v0.7.3. *Cite: `raw/github_issue-focused-pane-cursor-flickers-whenever-a-sidebar-agent-spinne.md`.* **#229 — Chinese IME composition causes pane rendering artifacts.** Symptom: composing Chinese text in a Codex pane shows stray vertical-bar/cursor artifacts near the pane boundary while the IME candidate window is visible. A Chinese-speaking community member reproduced it too, on macOS's built-in Terminal, and explicitly concluded "复现了,和输入法应该没有关系" (reproduced, and it doesn't seem related to the input method) — narrowing the cause away from IME-specific handling but **without a confirmed root cause or fix landing in the thread**. *Cite: `raw/github_issue-chinese-ime-composition-causes-pane-rendering-artifacts.md`.* **#453 — Server segfaults on Unicode pane output in 0.6.7.** Symptom: certain emoji/Unicode output (`README 👨‍👩‍👧‍👦 🧑‍💻 ✅ ⚡ 漢字 café é 🏳️‍🌈 🚀`) reliably crashes the server (`SIGSEGV` in `__libc_free`). A second reporter found a related-but-distinct crash on the *restore* path: an `integer overflow` panic reading persisted `session-history.json` containing 100+ emoji/ZWJ/variation-selector sequences, causing a crash-loop on every server start until the file was manually removed. Root cause (maintainer): a recently-updated libghostty API introduced the bug; fix reverted that usage. Hotfixed in v0.6.8. One user reported a **recurrence** on long-running sessions afterward with the restore/session-history experimental feature enabled, suggesting the fix didn't cover every code path. *Cite: `raw/github_issue-server-segfaults-on-unicode-pane-output-in-0-6-7.md`.* **#895 — Undercurl renders as plain underline in Herdr.** Symptom: `printf '\033[4:3mcurly?\033[4:0m\n'` should render a curly/wavy underline (as Ghostty itself does) but rendered flat. Fixed the shape, released to preview `2026-06-30-3459798b606d` then stable v0.7.2. A follow-up from a contributor with a working local branch found the fix was **incomplete for colored** diagnostic underlines (as used by Neovim's LSP diagnostics): the underline *shape* now transports correctly (encoded into `modifier`), but underline *color* (`\033[4:3;58:2::R:G:Bm`) is still lost because it only exists in the local Ratatui/terminal style and isn't carried through herdr's semantic-frame/ANSI-blit protocol. Contributor's branch (`snirt/herdr@issue/895-undercurl-sidebranch`) adds explicit underline-color transport; not confirmed merged. *Cite: `raw/github_issue-undercurl-renders-as-plain-underline-in-herdr.md`.* **#986 — Local clipboard image paste is broken after Ctrl+V was unbound (0.7.x regression, no replacement keybinding).** This one resolved as a **clarification, not a bug fix**: the reporter believed the removal of local Ctrl+V clipboard-image interception (done in #646/#647 to stop it from breaking Vim/Neovim block-visual mode) had regressed local image paste. Maintainer's final answer: "it's not a regression. herdr was falsely trying to capture your clipboard in local mode to scan for images, which is a solution for ssh… codex or claude code on mac don't accept cmd+v to paste images, ctrl+v is required. You can try out of herdr." I.e. raw Ctrl+V passthrough to the agent, which reads the OS clipboard itself, is the intended and correct behavior; the image bridge is remote-only by design. A related earlier fix (`6f14858`) made Unix local clients stop treating empty bracketed paste as an image-bridge trigger. Released across v0.7.2/v0.7.4. *Cite: `raw/github_issue-local-clipboard-image-paste-is-broken-after-ctrl-v-was-unbou.md`.* **#919 — New space doesn't synchronize with shell (cwd tracking).** Symptom: after an update, a new space/workspace inherits the *previous* active space's directory rather than following the shell's actual current directory; related reports showed new tabs also not following cwd correctly, and (macOS) `herdr pane current` showing a stale `cwd` alongside a correct `foreground_cwd` after a plain `cd`. Fixed on master, released to preview `2026-07-06-4dae557eefd9`. *Cite: `raw/github_issue-new-space-doesn-t-synchronize-with-shell.md`.* ### Persistence, SSH & remote (7 cases) **#312 — Nothing works when starting herdr in a remote SSH session.** Symptom: over SSH, only `q` (detach) and `?` (help) respond; prefix combos like `ctrl+b shift+n` (new workspace) appear to do nothing. Root cause (maintainer): **not a broken prefix key** — it was entering prefix mode correctly. The remote session used the *remote machine's* keybinding config (its own defaults), not the user's customized local keybindings, so their custom bindings simply weren't defined remotely. A second, distinct bug was found in the same thread: Shift+letter chords over legacy (non-enhanced) terminal reporting arrived as an uppercase char with no SHIFT modifier, which didn't match bindings parsed from `"shift+n"` syntax — fixed by folding uppercase-no-modifier input to lowercase+SHIFT during key-combo normalization (patch included verbatim in the thread). The keybinding-source mismatch itself was later fixed properly: "remote attach uses the client/local keybindings by default" became the default in a subsequent release (see also `--remote-keybindings local|server` in v0.6.1). *Cite: `raw/github_issue-nothing-works-when-starting-herdr-in-remote-session.md`.* **#598 — Connecting to two separate remote sessions without a name confuses herdr.** Symptom: `herdr --remote server1` then `herdr --remote server2` connects to the wrong server. Root cause (maintainer, after ruling out SSH multiplexing): `herdr --remote <target>` without `--session` attaches to the **default session in the remote environment**, not a session scoped to the SSH target — if two hosts share the same `$HOME`/config/socket namespace (as these VMs did, differing only by SSH port), they share the same default herdr session state. Fix/guidance: use explicit named sessions, `herdr --remote server1 --session server1` / `--remote server2 --session server2`, or give each host a separate `XDG_CONFIG_HOME`. This is a **usage/config resolution, not a code fix**. *Cite: `raw/github_issue-connecting-to-two-separate-remote-sessions-without-name-conf.md`.* **#628 — Keys not registering under Ghostty over SSH.** Symptom: after `herdr --remote` or a plain SSH + `herdr`, no keys register except `q`; on exit, a fragment like `;1:3u` leaks into the shell. Root cause (maintainer): the remote herdr binary was outdated — a nav-mode screen and its associated bugfix existed in a newer version than what was actually running remotely (nix-installed, stuck on an old build). Guidance: `--remote` should prompt to update and offer to stop the running server so the new binary takes over; if declined, run `herdr server stop` on the remote host manually. The reporter's final comment shows they were still on the old version via their Nix install path, so **resolution requires the user to actually update the remote binary** — not fully confirmed closed in-thread. *Cite: `raw/github_issue-keys-not-registering-under-ghostty-over-ssh.md`.* **#1201 — `herdr --remote` not detecting herdr already installed on the server.** Symptom: both client and server have the same herdr version installed, but `--remote` insists it isn't installed remotely. Root cause, narrowed across two data points: (1) an `xonsh` shell environment shape where interactive vs. non-interactive SSH don't share `PATH` (same class as #1203); (2) a `mise`-managed remote install where `mise activate` only runs for interactive shells, so non-interactive SSH `PATH` never sees the shims, **and** herdr's remote-discovery code explicitly filters out mise shims while its fallback "known mise location" check assumes a `bin/` subdirectory that a specific mise install layout didn't have (with an exact source-line citation to `src/remote/unix.rs`). Fixed on master, not confirmed released in the mirror. *Cite: `raw/github_issue-herdr-remote-not-detecting-already-installed-on-server.md`.* **#333 — WSL2 clipboard history (Win+V) doesn't work when copying from herdr.** Symptom: mouse-copied text pastes fine with Ctrl+V but never appears in Windows' Win+V clipboard history. Root cause (community-traced, with a linked fix commit): herdr detected WSLg's `DISPLAY`/`WAYLAND_DISPLAY` and used `wl-copy`/`xclip`, which write to WSL's *internal* Linux clipboard rather than the Windows clipboard — bypassing the OSC 52 path that *does* populate Win+V history. Fix: prefer OSC 52 on WSL. Maintainer confirmed: "herdr prefers osc52 on wsl now, it seems the best path for wsl." *Cite: `raw/github_issue-wsl2-clipboard-history-win-v-does-not-work-when-copying-from.md`.* **#893 — Live handoff drops installed plugin registry; a later install then clobbers `plugins.json`.** Symptom: after `herdr server live-handoff --import-exe ...`, `herdr plugin list` reports no plugins even though `plugins.json` had them; installing any new plugin afterward rewrites the file with *only* that plugin, discarding the rest. A community PR was offered as a working fix. Maintainer confirmed reproduction and fixed it; released to preview `2026-07-16-e907e6a36646` (and per the release digest, folded into stable as part of v0.7.5's "Live handoff now preserves installed plugins" fix). *Cite: `raw/github_issue-live-handoff-drops-installed-plugin-registry-and-later-plugi.md`.* **#796 — Mouse click to switch tabs/workspaces doesn't update UI on macOS + Ghostty (`cell_width_px=0`).** Symptom: clicks register in the server log (`tab.focus outcome="ok"`) but the UI doesn't visually update; rapid clicking sometimes free-runs tabs cycling at ~17ms intervals with no input; server logs consistently show `cell_width_px=0 cell_height_px=0` on every client connect/resize. Maintainer initially couldn't reproduce and suspected a local terminal/input-device issue. The reporter isolated it to Ghostty specifically (Terminal.app on the same machine worked fine) and then found the actual trigger: **connecting through Mosh** — "once I connect with moshi, that's when the mouse events stop working in ghostty!" Disconnecting the Mosh session and restarting herdr on the laptop resolved it. Root cause is a Mosh↔Ghostty interaction exposed through herdr, not a herdr-native bug. *Cite: `raw/github_issue-mouse-click-to-switch-tabs-workspaces-does-not-update-ui-on-.md`.* ### Platform quirks (12 cases) Windows support itself began as a large, deliberately incremental undertaking (tracked in issue #134, "Windows support?" — not a bug report but useful context): the maintainer and a contributor (`@samuelpatro`, PR #138) built native Windows support on top of Microsoft's ConPTY, explicitly flagged as "windows beta" with known ConPTY quirks (latency, incomplete VT sequence support, alternate-screen edge cases, and Unicode-width-table differences from POSIX causing TUI layout corruption in tools like `lazygit`/`superfile`/`vim`). Most of the platform-specific cases below are downstream of that ConPTY boundary. *Cite: `raw/github_issue-windows-support.md`.* **#1468 — [Windows] herdr fires curl.exe windows periodically.** Symptom: visible `curl.exe` console windows flash periodically (measured: a burst of 19 spawns landing in the same second, repeating every 30 minutes), fetching `herdr.dev/agent-detection/*.toml` manifests. Root cause: noninteractive subprocess spawns (agent-detection-manifest checks, update/version checks) weren't suppressing their console windows on Windows. Workaround offered immediately: `manifest_check = false` and `version_check = false` under `[update]` in `config.toml` (needs a server restart). Fixed on preview `2026-07-16-e907e6a36646` for the periodic case; maintainer noted the startup-only flash needed a further fix. One user reported flashes "still are happening occasionally" after the preview fix — **partial**. *Cite: `raw/github_issue-windows-herdr-fires-curl-cmd-windows-periodically.md`.* **#774 — macOS: `switch_ascii_input_source_in_prefix` switches the wrong input source.** Root cause (self-diagnosed by the reporter, then implemented by them): `TISCopyCurrentKeyboardInputSource()` returns a **per-process cached value** that only refreshes via a CFRunLoop-delivered notification — but herdr's server is a background daemon that never runs a CFRunLoop, so its cached read of "current input source" is frozen at roughly its own startup time, and prefix restore writes that stale value onto the foreground. Fix: move the switch/restore to the **client** (forwarded like clipboard writes) instead of the server. Landed with a caveat the same contributor found while implementing it: an event-consumption race where `App::handle_api_request`'s exhaustive internal-event drain could consume the forwarding-only `PrefixInputSource`/`ClipboardWrite` events inside the server before the intended forwarding path saw them, guarded per-event as an interim measure pending a deeper client/server-boundary migration. A separate user later reported a related-but-distinct case (Ukrainian keyboard layout, prefix key typed on non-Latin layout not translating to ASCII) that the client-side fix did not cover, worked around by rebinding prefix to a non-character key (`f12`). *Cite: `raw/github_issue-macos-switch-ascii-input-source-in-prefix-switches-the-wrong.md`.* **#1083 — Crash with exception code 0xc0000409 (Windows).** Symptom: herdr crashes instantly with "lost connection to server: server closed connection"; Windows Event Viewer shows a stack-overflow/buffer-security-check-style exception (`0xc0000409`) with no reproducible trigger. Maintainer walked the reporter through enabling Windows Error Reporting local dumps (`LocalDumps` registry keys) to capture an actual `.dmp` file, since log files alone only showed the *effect* (unexpected close), not the *cause*. Reporter also hit a second, distinct crash ("socket closed: exit 232") during the same investigation. Multiple `.dmp` files were eventually collected and shared. **Open at thread's end — no root cause confirmed**, dump analysis pending. *Cite: `raw/github_issue-crash-with-exception-code-0xc0000409.md`.* **#830 — macOS Nix build fails (`DarwinSdkNotFound`).** Root cause: Herdr's vendored `libghostty-vt` build shells out to Zig, which asks Darwin for its SDK via `xcode-select`/`xcrun`; the Nixpkgs `herdr` derivation didn't expose those tools inside its Darwin build sandbox. Fix: maintainer prepared a tentative Nixpkgs branch adding Xcode-select script + cctools; a community member confirmed it worked and independently opened `NixOS/nixpkgs#536015` (validated with `nixpkgs-review` on `aarch64-darwin`), which the maintainer's own duplicate PR (`#536027`) was closed in favor of. This is a **Nixpkgs packaging fix, not a Herdr source change**. *Cite: `raw/github_issue-macos-nix-build-fails.md`.* **#327 — v0.6.3: new pane spawns fail with `dup of fd N failed` after restoring many panes on macOS.** Root cause (reporter's own precise diagnosis, confirmed by maintainer): macOS's default per-process soft `RLIMIT_NOFILE` is 256; a restored session of 8 workspaces/40 panes holds ~243 PTY character-device FDs on startup alone, leaving no headroom to spawn more. This became visible specifically because v0.6.3's new restore path (protocol v11, pane history, `resume_agents_on_restore`) eagerly re-spawns every pane's PTY on startup, unlike earlier versions. Immediate workaround: `ulimit -n 8192 && herdr server &`, or `sudo launchctl limit maxfiles 8192 unlimited`. Fix: raise the server's own soft `RLIMIT_NOFILE` toward the hard limit on startup. Hotfixed same-day/next-day as v0.6.4. *Cite: `raw/github_issue-v0-6-3-new-pane-spawns-fail-with-dup-of-fd-n-failed-after-re.md`.* **#556 — Cursor flashing in Windows and pasting multi-line auto-submits text.** Two bundled symptoms: (1) panes always show a block cursor on Windows regardless of the terminal's configured bar/other shape; (2) pasting 2–3 lines into a bracketed-paste-aware app submits at the first newline. The cursor-shape fix released to preview `2026-06-12-7ba4bfe90e7a` then stable v0.7.0. The **multiline-paste bug was explicitly still present** in 0.7.0 per the reporter's follow-up ("Is pasting multiline also fixed in 0.7.0, or just the cursor flashing? … I can still repro") — tracked further under #670 above. *Cite: `raw/github_issue-cursor-flashing-in-windows-and-pasting-multi-line-auto-submi.md`.* **#907 — Windows: Backspace does not delete inside Pi prompt.** Symptom: Backspace works in a plain Herdr pane but stops deleting once `pi` is launched in that same pane; Delete still functions. A related-but-distinct symptom (Backspace deleting a whole word instead of one character in the general TUI, not Pi-specific) was also reported on the same build. Fix/workaround, confirmed by three separate users: set **both** environment variables together — ```powershell $env:HERDR_WINDOWS_INPUT_PROBE="off"; $env:HERDR_WINDOWS_INPUT_BACKEND="crossterm"; herdr ``` — note that neither variable alone fixed it for the Pi-prompt case; only the combination did. Released to preview `2026-07-06-4dae557eefd9`, but the reporter explicitly left the issue open "in case you want to track the default Windows Backspace behavior" beyond the workaround. *Cite: `raw/github_issue-windows-backspace-does-not-delete-inside-pi-prompt.md`.* **#860 — Terminal freezes on agent exit (Ctrl+C / `/exit`) and workspace is deleted on Windows.** Symptom: exiting OpenCode (or forks: mimocode, kilocode, cline) via Ctrl+C or `/exit` freezes the Herdr client entirely and deletes the whole workspace instead of falling back to a shell. Fixed and released to preview `2026-06-30-3459798b606d` for the agent-exit trigger. A second reporter on the *same* preview build found a **different trigger for the identical freeze symptom**: closing a pane via the tab-bar `+`/right-click "Close pane" context menu, or via `ctrl+b x`, froze the terminal the same way — suggesting a shared ConPTY-close code path (possibly `TileLayout::close_focused()` or the context-menu handler) that the original fix didn't cover. **Partially fixed** — the agent-exit path was addressed, the UI-close path was reported as a likely-related but distinct gap. *Cite: `raw/github_issue-terminal-freezes-on-agent-exit-ctrl-c-exit-and-workspace-is-.md`.* **#1158 — Windows: idle server CPU scales with pane count (~0.15–0.2 cores per pane, even for empty shell panes).** One of the most rigorously quantified performance threads in the set. Reporter's A-B-A methodology (add/remove 4 empty panes, measure server CPU + `IO Other Operations/sec` deltas) showed a consistent ~0.12–0.19 core marginal cost per *completely idle* pane and ~50,000 IO-other-ops/s server-wide, persisting across three separate preview builds (0.7.1-preview through 0.7.4-preview) despite ~30% overall improvement between measurements. Root cause (a second contributor, `@Pimpmuckl`): Windows foreground-process polling enumerated every process separately per pane on every tick; sharing one process snapshot for 250ms across all panes (except live-agent-validation and process-lifecycle paths, which still use fresh snapshots) dropped the same 13→17→13-pane test from `1.070→1.858→0.964` cores to `0.099→0.092→0.099` cores on an independent machine. Fixed on master; per the release digest this is the fix credited in v0.7.5's changelog entry for issue #1158. *Cite: `raw/github_issue-windows-idle-server-cpu-scales-with-pane-count-0-15-0-2-core.md`.* **#726 — CPU usage higher than expected, esp. on idle (cross-platform, follow-up to #300/#439).** Reporter (with a rebased experimental patch already running for a week) identified three concrete unfixed idle-wake sources: agent detection waking every 300/500ms per pane and re-reading `/proc` even on an unchanged grid; the client-writer thread busy-polling `recv_timeout(5ms)` on two channels (~200 wakes/s per attached client); and idle agent panes forcing a full re-render every ~800ms regardless of screen changes. Measured on 30 idle zsh panes: detached CPU dropped from 2.3%→0.08% and attached (250×64) from 11.7%→0.33% with the patch; `poll()` syscalls dropped from 434/15s to zero. Maintainer could not reproduce the same magnitude on their own 4-vCPU VPS but implemented optimizations anyway; released to preview `2026-06-22-24c7377de01c`. Follow-on Windows-specific idle-CPU work continued separately under #1158 above. *Cite: `raw/github_issue-cpu-usage-higher-than-expected-esp-on-idle.md`.* **#1533 — [Windows] Arrows and ESC in pi not working.** Symptom: inside a `pi` pane on Windows, typing and Backspace work but arrow keys and Escape do nothing; the same keys work fine in Codex panes and in a plain shell. Root cause (community-diagnosed, confirmed with `herdr pane send-text` round-tripping a raw arrow escape sequence successfully while the physical arrow key did nothing): Pi enables Windows VT input plus Kitty/`modifyOtherKeys` enhanced keyboard modes *inside Herdr's ConPTY*, and ConPTY itself consumes the arrow/Esc sequences before Pi ever receives them — disabling the enhanced modes when `HERDR_PANE_ID` is present fixed it. **This is a bug in Pi's own Windows terminal-capability negotiation, not in Herdr** — the fix landed as a patch to Pi (`earendil-works/pi`), not to Herdr, and the reporter explicitly noted "PR should target earendil-works/pi, not Herdr." A later comment also floated bundling a newer ConPTY (from Microsoft's NuGet package) as an alternative mitigation, since Windows 10's system ConPTY behaves differently from the one shipped with Windows Terminal/Windows 11 — but the confirmed working fix is the upstream Pi patch. *Cite: `raw/github_issue-windows-arrows-and-esc-in-pi-not-working.md`.* **#1116 — Enter/Backspace still double under Kitty keyboard protocol on v0.7.1 (fix for #769 didn't fully land).** Symptom: every Enter and Backspace registers twice under Alacritty (and also reproduced on foot and kitty), doubling typed commands and Backspace deletions; a prior fix (#769) had landed a partial mitigation ("prevent release key fallback from doubling input") that didn't cover this case. Root cause, precisely diagnosed by a community contributor with a byte-level, keyboard-free reproduction script: herdr enables `CSI > 7 u` (Kitty protocol disambiguation + **report event types**) on the host terminal; with *report event types* on but *report all keys as escape codes* off, several terminals (kitty, foot) encode the **release** of modifierless Enter/Tab/Backspace as the *same legacy byte* as the press (`\r`, `\t`, `\x7f`) — so press and release are byte-identical on the wire and nothing downstream can distinguish them; the "double" is the release event being mistaken for a second press. Alacritty happens to suppress these releases client-side, which is why it didn't reproduce there. Fix (contributor's tested branch): drop `REPORT_EVENT_TYPES` from `ime_compatible_keyboard_enhancement_flags`, since herdr only used release events to clear `suppressed_repeat_keys` and never forwarded them to panes anyway — verified to produce the correct single-byte sequence across 5/5 runs, full test suite/fmt/clippy passing. A second community member independently corroborated the exact same root cause with `evtest` proof that physical key events were single down/up pairs (ruling out hardware). **Fix identified and offered as a branch; not confirmed merged in the mirror.** *Cite: `raw/github_issue-enter-backspace-still-double-under-kitty-keyboard-protocol-o.md`.* ## Recommendations - **When agent status looks wrong**, check which of the two systems is authoritative first: run `herdr agent explain <target> --json` (added in v0.6.9 specifically because of threads like these) before assuming a bug — several "bugs" in this casebook (#846, part of #1310) turned out to be a local detection-manifest override, a scrolled-out-of-view screen region, or a stale integration file, all visible in `explain` output. - **When a Windows input/rendering bug appears only in one terminal host**, try the `HERDR_WINDOWS_INPUT_BACKEND=crossterm` / `HERDR_WINDOWS_INPUT_PROBE=off` combination (both together, per #907) before filing a new report — it resolved several independently-reported Windows keyboard symptoms. - **When a "herdr bug" involves flicker, stutter, or leaked escape sequences on a specific terminal/multiplexer combination**, test the same operation in that terminal with herdr removed from the loop first (#512, #796, #1295 all resolved or narrowed this way) — a meaningful fraction of "herdr" reports in this set turned out to be the underlying terminal, IME, or a chained tool (Mosh) exposing latent behavior that herdr merely surfaces. - **Protocol-version and plugin-scope breaking changes** (documented in [[summaries/release-digest]]) are the most common cause of "it worked yesterday" reports after an update — check `herdr status` for protocol mismatch before deep-diagnosing a fresh regression. - **Reinstall integrations after every update**, not just after installing them once: at least three cases here (#1310, #856, #1017-adjacent) trace back to a stale or unversioned integration script left behind after a herdr binary update. ## Requested features (not diagnostic — roadmap signal only) Eleven issues in this set were pure feature requests with no operational/diagnostic content of their own; all but one shipped. **Implemented**: hide the tab bar when a workspace has one tab (`ui.hide_tab_bar_when_single_tab`, #448, v0.7.2); redesigned Agent-panel row layout with custom status lines and configurable tokens (#222, culminating in v0.7.4's row-layout system); temporary floating popup panes for plugins (#1125, v0.7.4); tmux-style "last pane/workspace" back-and-forth navigation (#287, v0.6.3); a vi-style copy mode for scrollback (`v`/`y`/`h j k l`, #231, v0.6.5); tmux-style double-click word/token copy with brief highlight feedback (#142, implemented, release not confirmed in the mirror); Ctrl+Click to open OSC-8/plain-text URLs in panes (#307, v0.6.3, with a macOS/Ghostty-specific follow-up bug reported afterward); native Kiro CLI agent detection (#185, v0.6.0, built from community-supplied screen-state captures); showing the current agent's process/session title in the pane border or sidebar (#36, v0.6.3); and full first-class Devin CLI support — detection, state inference, and native session resume via `devin --resume` (#606, implemented with explicit guidance to keep session-id-only hooks from falsely claiming full lifecycle authority). The one exception that surfaced diagnostic content of its own rather than staying a pure request was **Kitty Image Protocol / inline image rendering in panes** (#136), which resolved not as a shipped feature but as a **support/config clarification**: the experimental `[experimental] kitty_graphics = true` toggle already existed and had to be set on *both* the local and remote (`herdr --remote`) config sides, with a server restart, before images would render — the reporter had only set it locally. ## Pages Compared - [[summaries/release-digest]] - [[concepts/agents-and-integrations]] - [[concepts/panes-and-keyboard]] - [[concepts/persistence-and-remote]] - [[concepts/plugins-and-marketplace]] - [[concepts/agent-automation-and-socket-api]] - [[concepts/configuration]] - [[concepts/cli-reference]] - [[concepts/troubleshooting]] - [[concepts/install-and-quickstart]] - [[concepts/herdr-overview]] ## Source Metadata - **Type**: GitHub Issues (60 mirrors, `ogulcancelik/herdr`), comments included - **Fetched**: 2026-07-22 - **Coverage**: every `raw/github_issue-*.md` file present in this KB as of the ingest date (see `sources` frontmatter for the exact 60 filenames) - **Not covered as a diagnostic case**: issue #1340, "Relicensing herdr from AGPL-3.0 to Apache-2.0" — a governance/licensing consent thread (contributor relicensing sign-off to move from AGPL-3.0 to Apache-2.0), not a bug or feature request; noted here for completeness since its mirror is part of the 60 but it carries no operational content for this casebook.