aboutsummaryrefslogtreecommitdiff
path: root/docs/versions/0.7.0/website
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-22 14:58:26 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-22 14:59:09 +0300
commitc234f221f9be698bc0501c60459e1ae8e67df6c3 (patch)
tree944b4dec10fada8d93456dc5a85e6bfdb36a8b8b /docs/versions/0.7.0/website
parentef85fa0c7ebb48bb59fe7593af5a67f3e02ff3d4 (diff)
feat(docs): publish versioned release documentation
Diffstat (limited to 'docs/versions/0.7.0/website')
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/agent-skill.mdx57
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/agents.mdx159
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/cli-reference.mdx369
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/concepts.mdx85
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/configuration.mdx502
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/how-to-work.mdx103
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/index.mdx77
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/install.mdx151
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/integrations.mdx286
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/keyboard.mdx112
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/marketplace.mdx37
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/persistence-remote.mdx132
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/plugins.mdx294
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/quick-start.mdx69
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/session-state.mdx105
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/socket-api.mdx702
-rw-r--r--docs/versions/0.7.0/website/src/content/docs/windows-beta.mdx100
17 files changed, 3340 insertions, 0 deletions
diff --git a/docs/versions/0.7.0/website/src/content/docs/agent-skill.mdx b/docs/versions/0.7.0/website/src/content/docs/agent-skill.mdx
new file mode 100644
index 00000000..af7fa7bf
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/agent-skill.mdx
@@ -0,0 +1,57 @@
+---
+title: Agent skill file
+description: Install Herdr instructions for Claude Code or another coding agent.
+---
+
+Herdr ships a reusable agent skill file at [`SKILL.md`](https://github.com/ogulcancelik/herdr/blob/master/SKILL.md).
+
+Install that file into any coding agent that supports reusable skills or custom instructions. The skill teaches the agent how to control Herdr from inside a Herdr pane.
+
+Herdr also serves a separate guide at [`herdr.dev/agent-guide.md`](https://herdr.dev/agent-guide.md) for a different job: an agent helping a human learn, set up, or troubleshoot Herdr. The skill is for an agent operating Herdr; the guide is for an agent teaching a human.
+
+## What the skill does
+
+The skill tells an agent to use the `herdr` CLI when `HERDR_ENV=1` is set. That means the agent is running inside a Herdr-managed pane and can safely talk to the local Herdr socket.
+
+With the skill installed, an agent can:
+
+- inspect workspaces, tabs, panes, and neighboring agents
+- split panes and run commands without stealing focus
+- read pane output and recent logs
+- wait for servers, tests, or another agent to finish
+- start helper agents in sibling panes
+
+The skill is not a separate app or service. It is a markdown instruction file for agents.
+
+## Install it
+
+Use the repository copy as the source of truth:
+
+```text
+https://github.com/ogulcancelik/herdr/blob/master/SKILL.md
+```
+
+For agents with a skill system, install that file as a skill named `herdr`. For agents without a skill system, paste the file into the agent's project or user instructions.
+
+After installation, start the agent inside Herdr:
+
+```bash
+herdr
+claude
+```
+
+Or use any other coding agent in a Herdr pane. The important part is that the agent process runs inside Herdr, so `HERDR_ENV=1` is available.
+
+## Safety rule
+
+The skill starts with one guardrail: if `HERDR_ENV=1` is not set, the agent should stop and say it is not running inside a Herdr-managed pane.
+
+This prevents an agent outside Herdr from trying to control a session it does not own.
+
+## Agent-facing reference
+
+The full command guide lives in the skill file itself. It covers pane IDs, `pane split`, `pane run`, `pane read`, `wait output`, `wait agent-status`, workspace and tab commands, and coordination recipes.
+
+Read the source file here:
+
+[Open `SKILL.md` on GitHub →](https://github.com/ogulcancelik/herdr/blob/master/SKILL.md)
diff --git a/docs/versions/0.7.0/website/src/content/docs/agents.mdx b/docs/versions/0.7.0/website/src/content/docs/agents.mdx
new file mode 100644
index 00000000..3215f64f
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/agents.mdx
@@ -0,0 +1,159 @@
+---
+title: Agents
+description: See what Herdr can detect, how agent state works, and how integrations improve it.
+---
+
+Herdr is built for running more than one coding agent at a time. Each agent stays in a real terminal pane with its shell, logs, prompts, and running processes intact. Herdr tracks which panes contain agents, rolls their state up to tabs and workspaces, and lets you jump straight to the pane that needs attention instead of polling every terminal by hand.
+
+## Supported agents
+
+Automatic detection works out of the box for common coding agents. The important difference is not whether Herdr can see an agent. It is which signal is allowed to author `idle`, `working`, and `blocked`.
+
+| Agent | State authority | Integration role |
+| --- | --- | --- |
+| Pi | lifecycle hooks when installed; otherwise screen manifest | state and session |
+| OMP | lifecycle hooks when installed | state |
+| GitHub Copilot CLI | screen manifest | session |
+| Devin CLI | screen manifest | session |
+| Kimi Code CLI | lifecycle hooks when installed; otherwise screen manifest | state and session |
+| Hermes Agent | lifecycle hooks when installed; otherwise screen manifest | state and session |
+| Qoder CLI | screen manifest | session |
+| Droid | screen manifest | session |
+| OpenCode | lifecycle plugin when installed; otherwise screen manifest | state and session |
+| Kilo Code CLI | lifecycle plugin when installed; otherwise screen manifest | state and session |
+| Claude Code | screen manifest | session |
+| Codex | screen manifest | session |
+| Cursor Agent CLI | screen manifest | session |
+| Amp | screen manifest | none |
+| Grok CLI | screen manifest | none |
+| Antigravity CLI | screen manifest | none |
+| Kiro CLI | screen manifest | none |
+
+Detected but less thoroughly tested: Gemini CLI and Cline. Unsupported agents still run normally as terminal processes. They just may not get rich state unless you add an integration or report state over the socket API.
+
+## Status authority
+
+Herdr first detects the foreground process in each pane. After that, each pane has one status authority.
+
+For agents with complete lifecycle hooks, the integration is authoritative when it is installed and actively reporting for the running pane. Herdr uses those hook reports for `idle`, `working`, `blocked`, and session identity. It does not also run screen manifest fallback for that same lifecycle authority. This avoids two competing sources of truth.
+
+For agents without complete lifecycle hooks, Herdr identifies the foreground process and reads the live bottom-buffer screen snapshot. It evaluates TOML manifests against that snapshot to classify `idle`, `working`, and `blocked`. For agents that emit them, manifests can also match terminal title and progress (OSC) sequences as detection evidence; when that evidence is absent, screen rules carry detection on their own.
+
+The screen snapshot comes from the recent bottom of the pane buffer, not the scrolled viewport. If you scroll back in Herdr, detection still follows the live agent UI at the bottom.
+
+Claude Code, Codex, GitHub Copilot CLI, Droid, Qoder CLI, and Cursor Agent CLI integrations are intentionally not lifecycle authorities. They provide native session identity for restore, but their hooks do not cover the whole lifecycle. They can miss permission approval results, escape interrupts, or other transitions. For those agents, Herdr still uses screen manifest detection.
+
+## Blocked state
+
+Blocked detection is deliberately strict for screen-manifest agents. Herdr only marks `blocked` when the live bottom-buffer snapshot matches known visible approval, question, or permission UI. If no manifest rule matches for a known agent, Herdr falls back to `idle` and labels that fallback as `default_known_agent_idle_fallback` in explain output.
+
+This means unusual new agent prompts may initially show as `idle` instead of `blocked` until Herdr learns that screen shape. Those interactions should not make Herdr send input or take destructive action; they only affect the visible status and waits.
+
+## Detection manifests
+
+Bundled manifests live inside Herdr. Herdr also checks herdr.dev for remote manifest updates and applies valid per-agent rule updates automatically without requiring a Herdr restart. Remote manifests are stored in Herdr's state directory.
+
+Local overrides can replace a remote or bundled manifest from the platform config directory:
+
+```text
+~/.config/herdr/agent-detection/<agent>.toml
+```
+
+Local overrides always win. Without a local override, Herdr uses the newer compatible manifest between the cached remote manifest and the bundled manifest in the running binary. On debug builds, the same config helper may use a development directory such as `herdr-dev`. Invalid override files are ignored with a warning and Herdr falls back to the cached remote or bundled manifest for that agent.
+
+Remote manifests patch detection rules for agents Herdr already knows how to identify. Adding a completely new agent still requires a Herdr binary update for process detection, labels, and integration behavior.
+
+The running server loads active manifests into memory on startup. Automatic remote manifest updates reload that in-memory cache after new rules are written. Run `herdr server update-agent-manifests` to fetch remote manifest updates immediately and reload the running server. After editing a local override manually, restart Herdr or run `herdr server reload-agent-manifests` to apply the file to the running server.
+
+Use `herdr agent explain` when a pane shows the wrong state:
+
+```bash
+herdr agent explain <target>
+herdr agent explain --file screen.txt --agent codex --json
+```
+
+Live explain is evaluated by the running server, so it reflects the active manifest cache. The explain output shows the agent, final state, whether screen detection was skipped by a full lifecycle authority, manifest source and version, cached remote version, local override shadowing, remote update status, matched rule, visible evidence flags, matcher and region evidence for evaluated rules, skipped-update reason for transcript viewers, and the idle fallback reason when no rule matched.
+
+Herdr can run inside tmux as the outer terminal environment. Agent detection does not inspect tmux sessions launched inside a Herdr pane. If a shell framework auto-enters tmux inside Herdr, Herdr sees `tmux` as the pane process instead of the agent behind it.
+
+## State rollups
+
+The sidebar rolls state upward.
+
+A blocked agent makes its pane, tab, and workspace look blocked. A working agent makes the workspace look active. A done agent stays visible until you view it.
+
+This is the main Herdr workflow: start several agents, let them work in parallel, and use the sidebar to see which project needs a decision, which one is still running, and which one is ready to review.
+
+## Direct integrations
+
+Install the integration for each agent you use; it gives Herdr hook or plugin reports instead of screen detection alone:
+
+```bash
+herdr integration install claude
+herdr integration status
+```
+
+Each supported agent has its own integration name and behavior. See [Integrations](/docs/integrations/) for the per-agent details and the full install list.
+
+## Custom agent labels
+
+You can rename an agent target for display:
+
+```bash
+herdr agent rename w1:p1 reviewer
+herdr agent rename reviewer --clear
+```
+
+Targets accept terminal IDs, unique agent names, detected or reported agent labels, and legacy pane IDs.
+
+## Custom status labels
+
+Integrations can report a visual status label without changing semantic state.
+
+```bash
+herdr pane report-agent w1:p1 \
+ --source custom:indexer \
+ --agent docs-bot \
+ --state working \
+ --custom-status indexing
+```
+
+`state` controls waits, notifications, and rollups. `custom-status` is only display text.
+
+## Start agents from the CLI
+
+Use `herdr agent ...` commands when you want a terminal to be treated as an agent target. Agent targets show up in `agent list`, can be read or sent input by agent name, can be waited on by agent state, and can be directly attached.
+
+Spawn an agent into Herdr from a script:
+
+```bash
+herdr agent start reviewer --cwd ~/project --split right -- pi
+```
+
+You can place that agent in a specific workspace or tab:
+
+```bash
+herdr agent start docs --workspace w1 --tab w1:t1 -- claude
+```
+
+Use `herdr pane ...` commands for ordinary terminals, servers, tests, shells, and low-level terminal input. For example, use `pane split` and `pane run` for `cargo test`, not `agent start`, unless that terminal is intentionally being treated as an agent target.
+
+## Attach directly to an agent
+
+Attach your current terminal to one agent terminal instead of the full Herdr UI:
+
+```bash
+herdr agent attach reviewer
+```
+
+Detach with `ctrl+b q`. Send a literal `ctrl+b` with `ctrl+b ctrl+b`.
+
+Scroll with the mouse wheel or plain page up/page down. Normal input jumps back to the bottom.
+
+Use `--takeover` if another direct attach client already owns input:
+
+```bash
+herdr agent attach reviewer --takeover
+```
+
+Use `herdr terminal attach <terminal_id>` when you want the same direct attach behavior for a non-agent terminal.
diff --git a/docs/versions/0.7.0/website/src/content/docs/cli-reference.mdx b/docs/versions/0.7.0/website/src/content/docs/cli-reference.mdx
new file mode 100644
index 00000000..f1079995
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/cli-reference.mdx
@@ -0,0 +1,369 @@
+---
+title: CLI reference
+description: Herdr commands for sessions, workspaces, tabs, panes, notifications, agents, waits, integrations, and status.
+---
+
+Herdr’s CLI talks to the running server over the same local socket API used by integrations and agents.
+
+Most commands print JSON responses. Use them from scripts when you want deterministic automation.
+
+## 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 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 commands:
+
+```bash
+herdr status
+herdr status server
+herdr status client
+```
+
+## 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. Use it for supervised or service-style setups. `reload-config` applies reloadable settings without restarting panes. `agent-manifests` shows the active agent detection manifest sources, cached remote versions, and last remote update results. `update-agent-manifests` fetches remote manifest updates immediately, reloads them into the running server, and prints the updated manifest status; pass `--json` for the raw status response. `reload-agent-manifests` reloads agent detection manifests into the running server after local override edits.
+
+## Notifications
+
+```bash
+herdr notification show <title> [--body TEXT] [--position top-left|top-right|bottom-left|bottom-right] [--sound none|done|request]
+```
+
+`notification show` uses the configured `[ui.toast]` delivery. `--position` only affects in-app Herdr toasts. `--sound` defaults to `none`; `done` and `request` play the existing finished and needs-attention sounds only when the notification is shown.
+
+## 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 when you need 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 close <workspace_id>
+```
+
+Create a workspace without stealing focus:
+
+```bash
+herdr workspace create --cwd ~/project --label api --no-focus
+```
+
+## 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]
+```
+
+Worktrees are normal Herdr workspaces with Git checkout provenance. `worktree create` creates a Git worktree checkout, opens it as a workspace, and groups it with the parent repo workspace. Without `--path`, Herdr creates the checkout under `<worktrees.directory>/<repo>/<branch-slug>`.
+
+`workspace close` closes Herdr state only. `worktree remove` is the explicit checkout deletion path; it runs `git worktree remove`, never deletes the branch, and requires `--force` when Git refuses 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>
+```
+
+## 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>
+```
+
+Read output:
+
+```bash
+herdr pane read <pane_id> [--source visible|recent|recent-unwrapped|detection] [--lines N]
+herdr pane read <pane_id> --source visible --ansi
+herdr pane read <pane_id> --source recent-unwrapped --lines 120
+```
+
+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>` uses Herdr key-combo syntax: plain printable keys such as `a`,
+special keys such as `enter`, `tab`, `esc`, `backspace`, `left`, `right`,
+`up`, and `down`, modifier chords such as `ctrl+h`, `control+j`, `alt+x`,
+and `shift+tab`, function keys such as `f1`, and named punctuation such as
+`minus`, `plus`, and `backtick`. Legacy `C-c` and `c-c` are accepted as
+aliases for `ctrl+c`.
+
+`pane run` submits text plus Enter atomically. Prefer it over `send-text` plus `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] \
+ [--custom-status TEXT] \
+ [--seq N] \
+ [--agent-session-id ID] \
+ [--agent-session-path PATH]
+```
+
+`pane get`, `pane list`, `agent get`, and `agent list` include a read-only `agent_session` object when an official integration has reported a native session reference. If no native session reference is stored, the field is omitted.
+
+Those commands include `foreground_cwd` when Herdr can resolve the cwd of the foreground process controlling the pane. The existing `cwd` field remains the pane/workspace cwd used for labels and follow-cwd behavior.
+
+Report display-only pane metadata without taking over semantic state:
+
+```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] \
+ [--custom-status TEXT|--clear-custom-status] \
+ [--state-label STATUS=TEXT] \
+ [--clear-state-labels] \
+ [--seq N] \
+ [--ttl-ms N]
+```
+
+`STATUS` is one of `idle`, `working`, `blocked`, `done`, or `unknown`. `--agent` is a guard for the authoritative agent label. `--applies-to-source` is a guard for the active lifecycle authority source. Use `--display-agent` to change the visible name.
+
+Metadata text is normalized before storage. Herdr trims surrounding whitespace, removes control characters, caps `--custom-status` at 32 characters, and caps `--title`, `--display-agent`, and each `--state-label` value at 80 characters. Empty normalized values are ignored.
+
+`--source` and `--applies-to-source` must be 80 characters or fewer and may contain only ASCII letters, digits, colon, dot, underscore, and hyphen. `--ttl-ms` makes metadata expire automatically and must be between `1` and `86400000` milliseconds. Omit it for metadata that should stay until replaced, cleared, or the pane closes. `--seq` lets Herdr ignore stale reports from the same `--source`; stale reports are accepted by the API but ignored by pane state.
+
+## Agents
+
+```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 <target> <text>
+herdr agent rename <target> <name>|--clear
+herdr agent focus <target>
+herdr agent wait <target> --status <idle|working|blocked|unknown> [--timeout MS]
+herdr agent attach <target> [--takeover]
+herdr agent start <name> [--cwd PATH] [--workspace ID] [--tab ID] [--split right|down] [--env KEY=VALUE] [--focus|--no-focus] -- <argv...>
+herdr agent explain <target> [--json|--verbose]
+herdr agent explain --file PATH --agent LABEL [--json|--verbose]
+```
+
+Agent targets can be terminal IDs, unique agent names, detected or reported agent labels, or legacy pane IDs. Names and labels are agent identities. Terminal IDs and legacy pane IDs are low-level escape hatches.
+
+`agent read` reads the resolved terminal stream. `agent send` writes literal text to that stream. `agent get`, `agent focus`, `agent wait`, and `agent attach` require the resolved terminal to have agent identity. `agent rename` can assign that identity.
+
+`agent explain` asks the running server to classify the same bottom-buffer detection snapshot used by screen detection, so live output reflects the server's active manifest cache. Because this uses the `agent.explain` socket method, restart or hand off to an updated server after upgrading Herdr before using live explain. Use `--file PATH --agent LABEL` to explain a saved fixture locally instead. The default output shows the agent, final state, manifest source and version, matched rule with its region evidence, and any fallback, skip, or warning reasons. Add `--verbose` for visible evidence flags, cached remote version, local override shadowing, remote update status, and the full evaluated-rules list with matcher and region evidence. Add `--json` for issue reports or 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` when you want to submit a command with Enter.
+
+## Direct terminal attach
+
+```bash
+herdr terminal attach <terminal_id> [--takeover]
+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 title clear` restores Herdr's default outer terminal window title.
+
+## Waits
+
+Wait for output in a pane:
+
+```bash
+herdr wait output <pane_id> --match <text> [--source visible|recent|recent-unwrapped] [--lines N] [--timeout MS] [--regex] [--raw]
+```
+
+Wait for pane agent state:
+
+```bash
+herdr wait agent-status <pane_id> --status <idle|working|blocked|done|unknown> [--timeout MS]
+```
+
+Use `wait output` for normal commands and servers. Use `wait agent-status` for coding agents.
+
+## 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 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 status [--outdated-only]
+```
+
+## Plugins
+
+Plugin commands install and run local executable workflow plugins. A plugin is a manifest plus out-of-process commands; Herdr owns the host surface and plugins own their implementation language.
+
+Install, list, and remove plugins:
+
+```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, such as `ogulcancelik/herdr-plugin-examples/worktree-bootstrap`. It uses `git`, shows a trust preview in interactive terminals, runs supported manifest build commands, and stores GitHub installs in a Herdr-managed directory. Use `--yes` for noninteractive installs. Reinstalling a GitHub-managed plugin replaces that managed checkout. Installing over a locally linked plugin is refused. Plugin manifests must declare `min_herdr_version`; install and link fail when the plugin requires a newer Herdr binary. `plugin list` is human-readable by default; pass `--json` for the raw API response.
+
+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. It is still the right command while authoring or testing a plugin from a local checkout. `plugin unlink` unregisters the plugin and leaves files alone. `plugin uninstall` unregisters a plugin and also removes Herdr-managed GitHub checkout files. For GitHub installs, uninstall accepts either the plugin id or the same `owner/repo[/subdir...]` shorthand used by install. Actions, event hooks, panes, and link handlers are declared in the manifest; runtime action registration is not part of v1.
+
+Config directory:
+
+```bash
+herdr plugin config-dir <plugin_id>
+```
+
+`plugin config-dir` prints the plugin's config directory, creating it (and seeding it from legacy plugin config locations when present) if needed. Use it in setup docs and shell scripts to point users at a stable path for `.env` files and other user-editable config, separate from the managed plugin 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 plugin action and prints the started command log record in
+the JSON response. Use the qualified action id (`plugin.id.action`) when more
+than one plugin uses the same action id. Local action ids cannot contain dots,
+so qualified ids remain unambiguous even when plugin ids contain dots.
+
+Logs:
+
+```bash
+herdr plugin log list [--plugin ID] [--limit N]
+```
+
+Managed terminal panes:
+
+```bash
+herdr plugin pane open --plugin ID --entrypoint ID [--placement overlay|split|tab|zoomed] [--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 to be linked, enabled, and compatible
+with the current platform. It starts a manifest-declared `[[panes]]` command as
+a Herdr-managed terminal pane. The manifest default is `overlay`, which opens a
+temporary zoomed overlay over the active pane. It can also open as a split, a
+new tab, or a zoomed pane. Native non-terminal plugin panes are a later surface.
+
+`--env KEY=VALUE` can be repeated on process-launching commands. It applies to the newly launched process only. Herdr-managed variables such as `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`, and `HERDR_PLUGIN_CONTEXT_JSON` stay authoritative when they conflict with caller-provided env.
+
+## Read sources
+
+| 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. |
+
+## 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. |
diff --git a/docs/versions/0.7.0/website/src/content/docs/concepts.mdx b/docs/versions/0.7.0/website/src/content/docs/concepts.mdx
new file mode 100644
index 00000000..2ac32cc9
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/concepts.mdx
@@ -0,0 +1,85 @@
+---
+title: Concepts
+description: Understand Herdr workspaces, tabs, panes, agents, sessions, and modes.
+---
+
+Herdr is a terminal workspace manager. It keeps real terminal processes running and adds structure around them.
+
+## Workspace
+
+A workspace is the top-level project container. Use one workspace per repo, task, or investigation.
+
+A workspace owns tabs and panes. Its sidebar state rolls up from the agents inside it, so you can see which project needs attention.
+
+## Tab
+
+A tab is a layout inside a workspace. Use tabs to separate views like `agents`, `logs`, `server`, or `review`.
+
+Tabs are addressable from the CLI and socket API.
+
+## Pane
+
+A pane is a real terminal. Herdr renders the terminal output, sends input back to the process, and preserves the pane across client detach.
+
+Panes can be split right or down. They can be renamed manually, read from the CLI, sent input, and closed.
+
+## Mouse UI
+
+Herdr is mouse-native. You can click panes, tabs, workspaces, and agents. You can drag split borders, select text, and use right-click menus. Everything below is also reachable by mouse; keyboard bindings are an optional layer.
+
+If you prefer keyboard-only control, or you want Herdr to stop capturing mouse input, disable mouse capture:
+
+```toml
+[ui]
+mouse_capture = false
+```
+
+## Agent
+
+An agent is a process Herdr recognizes inside a pane. Herdr detects agents from foreground processes, screen manifests, and optional integrations.
+
+Agent states are:
+
+| State | Meaning |
+| --- | --- |
+| `blocked` | The agent needs input, approval, or a decision. |
+| `working` | The agent is actively running. |
+| `done` | The agent finished and you have not looked at it yet. |
+| `idle` | The agent is finished or waiting and has been seen. |
+| `unknown` | Herdr cannot confidently classify the state. |
+
+## Session
+
+A session is a persistent Herdr server namespace. The default `herdr` command attaches to the default session.
+
+Named sessions are separate runtime namespaces:
+
+```bash
+herdr session list
+herdr session attach work
+herdr session attach side-project
+```
+
+Use workspaces first. Use named sessions when you need completely separate panes, sockets, and persisted runtime state.
+
+## Client and server
+
+By default, Herdr runs as a background server plus one or more attached clients.
+
+The server owns panes and process state. The client is the terminal UI attached to that server.
+
+Detach the client with `ctrl+b q`. The server and agents continue running.
+
+If you want to end the session and stop its panes, stop the server:
+
+```bash
+herdr server stop
+```
+
+## Modes
+
+Herdr has terminal mode, prefix mode, and navigate mode.
+
+Terminal mode sends keys to the focused pane. Prefix mode waits for one Herdr action after the prefix key. Navigate mode is the persistent workspace navigation surface.
+
+Press the prefix key, default `ctrl+b`, then an action key such as `c` for a new tab or `w` for workspace navigation. New to the prefix idea? See [Keyboard](/docs/keyboard/).
diff --git a/docs/versions/0.7.0/website/src/content/docs/configuration.mdx b/docs/versions/0.7.0/website/src/content/docs/configuration.mdx
new file mode 100644
index 00000000..188d1237
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/configuration.mdx
@@ -0,0 +1,502 @@
+---
+title: Configuration
+description: Configure Herdr keybindings, themes, sidebar behavior, notifications, and advanced options.
+---
+
+Herdr works without a config file. Add one when you want custom keys, themes, sidebar settings, notifications, or advanced behavior.
+
+## Config file
+
+Herdr reads config from:
+
+```text
+~/.config/herdr/config.toml
+```
+
+Print the full default config:
+
+```bash
+herdr --default-config
+```
+
+Save it as your config if you want a complete 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 setup when `onboarding` is missing or true. Continuing from onboarding writes `onboarding = false` and opens settings on the integrations tab. Set it when you want to skip that flow after setup.
+
+```toml
+onboarding = false
+```
+
+## Update channel
+
+Linux and macOS direct installs use the stable update channel by default. Windows beta installs default to preview and cannot switch to stable until stable Windows releases are available.
+
+```toml
+[update]
+channel = "stable"
+```
+
+Set `channel = "preview"` to make `herdr update` install manually published preview builds from the current development branch. Homebrew, mise, and Nix installs ignore the preview channel and update through their package managers.
+
+## Reload config
+
+Reload a running server after editing `config.toml`:
+
+```bash
+herdr server reload-config
+```
+
+You can also open the global menu in Herdr and choose `reload config`.
+
+Reload applies most UI settings without restarting panes. Startup-only settings still need a restart.
+
+## Terminal defaults
+
+Set the executable Herdr uses for newly created interactive panes:
+
+```toml
+[terminal]
+default_shell = "nu"
+```
+
+When unset or empty, Herdr uses `$SHELL`, then `/bin/sh`. This is an executable name or path, not a shell command line. Existing panes keep their current shell until they are recreated. Command panes still run through `/bin/sh -c`; detached custom command keybindings use Herdr's existing `/bin/sh -lc` path.
+
+Set how Herdr starts newly created interactive pane shells:
+
+```toml
+[terminal]
+shell_mode = "auto"
+```
+
+`shell_mode = "auto"` starts login shells on macOS so login-only PATH setup such as `/usr/libexec/path_helper` and Homebrew shell initialization runs in new panes. On other platforms, it keeps the existing non-login shell behavior. Use `"login"` to force login-shell startup, or `"non_login"` to opt out. Command panes, detached custom command keybindings, and explicit argv launches keep their existing command execution paths.
+
+Set the working directory policy for new panes, tabs, and workspaces:
+
+```toml
+[terminal]
+new_cwd = "follow"
+```
+
+`new_cwd = "follow"` keeps the default behavior and inherits the source pane or workspace. When there is no source workspace, Herdr starts in `$HOME`. Use `"home"` to always start in `$HOME`, `"current"` to use Herdr's process directory, or a fixed path such as `"~/Projects"`. Explicit `--cwd` values from the CLI or socket API still take precedence.
+
+## Worktrees
+
+Set the root directory Herdr uses for Git worktree checkouts created from the sidebar:
+
+```toml
+[worktrees]
+directory = "~/.herdr/worktrees"
+```
+
+Herdr creates checkouts under `<directory>/<repo>/<branch-slug>`. For sibling-style checkouts, set this to a directory such as `~/Projects/herdr-worktrees`. Relative values are resolved to an absolute path when the app applies the config.
+
+Worktree actions are available from Git workspace rows. `New worktree` creates a branch and checkout, opens it as a new Herdr workspace, and groups it under the source workspace. `Open worktree...` lists existing Git worktree checkouts for that repo; choosing an already-open checkout focuses it, and choosing a closed checkout opens it in the same group.
+
+Grouped worktrees still behave like normal Herdr workspaces: they can be focused, renamed, closed, and contain their own tabs and panes. The parent row is the original workspace. Closing the parent row closes the whole Herdr group, but it does not delete checkout folders or branches.
+
+Deleting a worktree checkout is explicit. Use `Delete worktree checkout...` on a grouped child workspace to run `git worktree remove`. Herdr first asks Git to remove safely. If Git refuses because the checkout has modified or untracked files, Herdr asks again before running the forced remove. Branches are not deleted.
+
+## Remote attach
+
+Remote attach manages its SSH bridge with a temporary keepalive fallback by default.
+
+```toml
+[remote]
+manage_ssh_config = true
+```
+
+When enabled, `herdr --remote` writes a private temporary SSH config that includes your `~/.ssh/config` and `/etc/ssh/ssh_config` first, then adds fallback `ServerAliveInterval` and `ServerAliveCountMax` values. Your own SSH keepalive settings win. Set `manage_ssh_config = false` to run the bridge through plain `ssh` without Herdr's generated config.
+
+## Keybindings
+
+For a guided introduction to the prefix and a vetted prefix-free setup, see [Keyboard](/docs/keyboard/).
+
+Herdr has a prefix mode similar to tmux. The default prefix is `ctrl+b`. Keybinding strings are explicit: `prefix+n` means press the configured prefix and then `n`; `ctrl+alt+n` is a direct terminal-mode shortcut.
+
+A small keybinding override looks like this:
+
+```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 and avoids direct shortcuts that can steal input from shells, editors, tmux, or terminal apps. Common defaults include:
+
+```toml
+[keys]
+detach = "prefix+q"
+workspace_picker = "prefix+w"
+goto = "prefix+g"
+new_workspace = "prefix+shift+n"
+new_worktree = "prefix+shift+g"
+rename_workspace = "prefix+shift+w"
+close_workspace = "prefix+shift+d"
+navigate_workspace_up = "up"
+navigate_workspace_down = "down"
+navigate_pane_left = "h"
+navigate_pane_down = "j"
+navigate_pane_up = "k"
+navigate_pane_right = "l"
+new_tab = "prefix+c"
+previous_tab = "prefix+p"
+next_tab = "prefix+n"
+switch_tab = "prefix+1..9"
+rename_tab = "prefix+shift+t"
+close_tab = "prefix+shift+x"
+copy_mode = "prefix+["
+focus_pane_left = "prefix+h"
+focus_pane_down = "prefix+j"
+focus_pane_up = "prefix+k"
+focus_pane_right = "prefix+l"
+swap_pane_left = "prefix+shift+h"
+swap_pane_down = "prefix+shift+j"
+swap_pane_up = "prefix+shift+k"
+swap_pane_right = "prefix+shift+l"
+cycle_pane_next = "prefix+tab"
+cycle_pane_previous = "prefix+shift+tab"
+last_pane = ""
+split_vertical = "prefix+v"
+split_horizontal = "prefix+minus"
+close_pane = "prefix+x"
+zoom = "prefix+z"
+resize_mode = "prefix+r"
+toggle_sidebar = "prefix+b"
+```
+
+Optional actions are unset by default. Bind them with `prefix+` for prefix-mode behavior, or with an explicit modified chord when you intentionally want a direct shortcut:
+
+```toml
+[keys]
+previous_workspace = "prefix+shift+left"
+next_workspace = "prefix+shift+right"
+last_pane = "prefix+tab"
+open_worktree = "prefix+shift+o"
+remove_worktree = "prefix+alt+d"
+next_tab = ["prefix+n", "ctrl+alt+]"]
+```
+
+`last_pane` switches back to the last focused pane across workspaces and tabs. It is unset by default because the tmux-style pane binding `prefix+l` is already used for pane-right focus.
+
+Key strings accept plain keys, modifier combinations such as `ctrl+a`, `shift+n`, `alt+1`, `cmd+k`, and special keys such as `enter`, `tab`, `esc`, `left`, `right`, `up`, and `down`. Named punctuation such as `minus`, `comma`, `ampersand`, `plus`, and `backtick` is also accepted. Plain direct printable keys such as `n` are unsafe because they intercept typing; use `prefix+n` unless you intentionally want a direct binding. The `navigate_workspace_*` and `navigate_pane_*` fields are navigate-mode-only and may use plain keys such as `j` or `k`; they must not use `prefix+`, `esc`, `enter`, `tab`, `shift+tab`, `left`, `right`, or unmodified `1` through `9`. Left and right arrows are permanent aliases for pane-left and pane-right navigation. These navigate-mode shortcuts are independent from general action bindings such as `focus_pane_down = "prefix+j"`; when both use the same key, the navigate-mode shortcut wins while navigate mode is open. Alt, Cmd/Super, and punctuation with modifiers depend on your terminal and tmux settings.
+
+If you have old custom keybindings and want the new defaults, run `herdr config reset-keys`. Herdr backs up `config.toml`, removes `[keys]` and `[[keys.command]]`, and uses built-in v2 defaults after restart or `herdr server reload-config`.
+
+## Indexed jumps
+
+Indexed keybindings use `1..9` in normal keybinding 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 is still parsed for compatibility, but new configs should prefer the explicit action fields.
+
+## Custom command keybindings
+
+Custom commands use the same keybinding syntax.
+
+```toml
+[[keys.command]]
+key = "prefix+alt+g"
+type = "pane"
+command = "lazygit"
+description = "run lazygit"
+```
+
+`type = "pane"` opens a temporary 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 action ids are not globally unique:
+
+```toml
+[[keys.command]]
+key = "prefix+l"
+type = "plugin_action"
+command = "example.layout.apply"
+description = "apply layout"
+```
+
+An optional `description` can be provided. When specified, this description is displayed in the keybind help panel (opened with `prefix+?`) in place of the default `'custom command'` label.
+
+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 those values are available. Shell commands run from the focused pane's working directory when Herdr can detect it.
+
+## Theme
+
+Choose a built-in theme:
+
+```toml
+[theme]
+name = "catppuccin"
+```
+
+Built-in themes:
+
+`catppuccin`, `catppuccin-latte`, `terminal`, `tokyo-night`, `tokyo-night-day`, `dracula`, `nord`, `gruvbox`, `gruvbox-light`, `one-dark`, `one-light`, `solarized`, `solarized-light`, `kanagawa`, `kanagawa-lotus`, `rose-pine`, `rose-pine-dawn`, `vesper`.
+
+Use `terminal` when you want Herdr UI colors to follow your host terminal's ANSI palette.
+
+You can 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 like `reset`, `default`, `none`, and `transparent`.
+
+## UI and sidebar
+
+The sidebar is the main Herdr dashboard. It shows workspaces, tabs, panes, and agent state.
+
+Common options:
+
+```toml
+[ui]
+sidebar_width = 32
+sidebar_min_width = 18
+sidebar_max_width = 36
+mobile_width_threshold = 64
+mouse_capture = true
+right_click_passthrough_modifier = ""
+redraw_on_focus_gained = true
+mouse_scroll_lines = 3
+confirm_close = true
+prompt_new_tab_name = true
+show_agent_labels_on_pane_borders = false
+agent_panel_scope = "all"
+accent = "cyan"
+```
+
+`sidebar_min_width` and `sidebar_max_width` control the expanded sidebar's resize bounds in columns. The defaults are 18 and 36.
+
+`mobile_width_threshold` controls the terminal width at or below which Herdr uses the mobile single-column layout. The default is 64 columns; increase it for foldables, tablets, or wide phone terminals.
+
+`agent_panel_scope` can be `all` or `current`. Use `current` if you only want the agent panel to show agents in the active workspace.
+
+`confirm_close` controls whether closing a workspace asks for confirmation. `prompt_new_tab_name` controls whether new tabs ask for a label first.
+
+Set `mouse_capture = false` if you want your terminal to handle normal clicks, such as command-clicking URLs. With mouse capture enabled, Ctrl-click opens pane links when your terminal sends that modified click to Herdr. This includes macOS; Cmd-click is not reported separately from plain click while Herdr captures mouse input. Use Shift-Ctrl-click on Linux or Shift-Cmd-click on macOS for the terminal-native bypass path.
+
+Set `right_click_passthrough_modifier = "ctrl"` if you want Ctrl-right-click, hold, and drag gestures inside mouse-reporting pane apps to reach the app instead of opening Herdr's pane menu. The default is empty, which disables this passthrough. Supported modifiers are `ctrl`, `alt`, `cmd`, `super`, `meta`, and `hyper`; `shift` is rejected because many terminals reserve Shift+mouse for their own mouse bypass.
+
+Set `redraw_on_focus_gained = false` to avoid the visible full-screen refresh when switching back to Herdr. The default is `true` because a full redraw recovers from rare stale or dirty host terminal surfaces.
+
+Set `mouse_scroll_lines` to change how many pane scrollback lines each mouse wheel notch scrolls. The default is 3. Pane apps that request mouse reporting still receive wheel events directly. Alternate-screen apps have no scrollback to scroll; see [Scrollback](#scrollback).
+
+Set `show_agent_labels_on_pane_borders = true` if you want detected agent labels in split pane borders when no manual pane label is set.
+
+## Notifications
+
+Herdr can show popup notifications when agents finish or need input.
+
+```toml
+[ui.toast]
+delivery = "off"
+delay_seconds = 1
+
+[ui.toast.herdr]
+position = "bottom-right"
+
+[ui.toast.clipboard]
+enabled = true
+position = "bottom-center"
+```
+
+`delivery = "off"` disables popup notifications. This is the default.
+
+`delivery = "herdr"` shows a toast inside the Herdr UI. Click the toast, or bind `keys.open_notification_target`, to focus the target workspace, tab, and pane. Set `ui.toast.herdr.position` to `top-left`, `top-right`, `bottom-left`, or `bottom-right`; desktop positions are relative to the full Herdr frame.
+
+`delivery = "terminal"` asks the outer terminal to show a desktop notification. Herdr sends terminal notification escape sequences for Ghostty, iTerm2, Kitty, and WezTerm. This is useful over SSH because the local terminal owns the notification.
+
+`delivery = "system"` asks the local operating system directly. On macOS, Herdr uses `terminal-notifier` when available, then falls back to `/usr/bin/osascript`. `terminal-notifier` can activate the hosting terminal when you click the notification. On Linux, Herdr uses `notify-send` and requires `DISPLAY` or `WAYLAND_DISPLAY`.
+
+Popup notifications are for background attention. Herdr suppresses popups for the active tab.
+
+`delay_seconds` waits before sending finished or needs-input agent notifications. Herdr notifies only if the pane is still in the same state when the delay expires. Set it to `0` for instant notifications. Valid values are `0` through `3600`.
+
+Clipboard feedback is configured separately because it confirms a foreground copy action and is never sent through terminal or system delivery. Set `ui.toast.clipboard.enabled = false` to hide the copied-to-clipboard popup. Clipboard positions are `top-left`, `top-center`, `top-right`, `bottom-left`, `bottom-center`, and `bottom-right`.
+
+## Sound
+
+Sound notifications are enabled by default and are played by the local Herdr client.
+
+```toml
+[ui.sound]
+enabled = true
+```
+
+Herdr plays a done sound when an agent finishes and an attention sound when an agent needs input. Set `enabled = false` on shared machines or remote servers unless you explicitly want audio.
+
+On macOS, Herdr uses `afplay`. On Linux, Herdr tries mp3-capable players in order: `paplay`, `pw-play`, `ffplay`, `mpg123`, then `mpv`. If no player is available, sound playback is skipped and Herdr logs a warning.
+
+Custom sounds must be mp3 files. Relative paths are resolved from the config file's directory.
+
+```toml
+[ui.sound]
+path = "sounds/notification.mp3"
+done_path = "sounds/done.mp3"
+request_path = "sounds/request.mp3"
+```
+
+`path` sets one sound for all sound notifications. `done_path` and `request_path` override only the finished and needs-input sounds.
+
+Per-agent sound overrides accept `default`, `on`, or `off`. Use detected agent labels such as `claude`, `codex`, `devin`, or `droid` as keys. Droid is muted by default.
+
+```toml
+[ui.sound.agents]
+droid = "off"
+claude = "on"
+```
+
+## Scrollback
+
+Set the scrollback buffer size for newly created panes:
+
+```toml
+[advanced]
+scrollback_limit_bytes = 10485760
+```
+
+Existing panes keep their current buffer until they are recreated.
+
+Panes only show a scrollbar when the app writes to the primary screen. Full-screen apps that switch to the alternate screen (vim, htop, Claude Code with `CLAUDE_CODE_NO_FLICKER=1`) produce no scrollback, so no scrollbar appears and wheel events are routed to the app instead. Scroll with the app's own keys or UI.
+
+## Pane screen history
+
+By default, full session restart restores workspaces, tabs, panes, cwd, layout, and focus without saving pane contents.
+
+Pane screen history is off by default. Pane output can include secrets, tokens, prompts, and command output, so enable it only when you want Herdr to save recent pane contents across full server restarts:
+
+```toml
+[experimental]
+pane_history = true
+```
+
+You can also toggle it from Settings > Experiments > pane screen history.
+
+When enabled, Herdr stores saved pane history in `session-history.json` next to `session.json`.
+
+For how pane screen history differs from live persistence, snapshot restore, native agent session restore, and live handoff, see [Session state and restore](/docs/session-state/).
+
+## Nested launches
+
+Herdr normally protects you from launching Herdr inside Herdr.
+
+```toml
+[experimental]
+allow_nested = false
+```
+
+Only enable nested launches for testing.
+
+## Kitty graphics
+
+Kitty graphics support is experimental.
+
+```toml
+[experimental]
+kitty_graphics = false
+```
+
+Leave this off unless you are testing terminal image behavior.
+
+## Agent session restore
+
+Herdr can restart supported agent panes in their native conversation sessions after a Herdr server restart.
+
+```toml
+[session]
+resume_agents_on_restore = true
+```
+
+This is enabled by default. Herdr only resumes panes that reported a native session reference through an official Herdr integration. Supported resume targets are Claude Code, Codex, Cursor Agent CLI, GitHub Copilot CLI, Droid, Kimi Code CLI, Qoder CLI, Pi, Hermes Agent, OpenCode, and Kilo Code CLI. Unsupported, missing, invalid, duplicated, or stale session references restore as a normal shell in the saved pane directory.
+
+Session references are stored in the local Herdr session snapshot. They are not shown in normal pane, agent, status, or event output.
+
+For how native agent session restore differs from pane screen history and live handoff, see [Session state and restore](/docs/session-state/).
+
+## IME cursor tracking
+
+When the focused pane hides its cursor and paints its own — common in AI-agent TUIs like Claude Code, pi, codex, and Devin — macOS native input methods stop tracking the candidate window position because the outer terminal stops reporting the cursor.
+
+Set `reveal_hidden_cursor_for_cjk_ime = true` to expose the focused pane's cursor anchor to the outer terminal regardless of the pane's `?25l` request:
+
+```toml
+[experimental]
+reveal_hidden_cursor_for_cjk_ime = false
+cjk_ime_agents = []
+cjk_ime_cursor_shape = "steady_block"
+```
+
+When enabled, the cursor stays visible at the focused pane's reported position. If the pane reports no cursor position, the anchor falls back to the pane's top-left so a stable IME hint is always available.
+
+`cjk_ime_agents` is an optional allow-list. When empty, the reveal applies to any focused pane. When non-empty, the reveal only applies if the focused pane's detected agent matches one of the listed names — useful to enable the reveal only for AI-agent TUIs that paint their own cursor while leaving plain shells untouched. Accepted names: `pi`, `claude`, `codex`, `gemini`, `cursor`, `devin`, `agy`, `cline`, `opencode`, `copilot`, `kimi`, `kiro`, `droid`, `amp`, `grok`, `hermes`, `kilo`, `qodercli`, and `qoder`. Unknown names are ignored; if the list contains no valid names, the reveal does not apply.
+
+`cjk_ime_cursor_shape` controls the DECSCUSR shape rendered for the IME anchor. Accepted values: `block`, `steady_block` (default), `underline`, `steady_underline`, `bar`, `steady_bar`.
+
+Hot-reloads through the existing `[experimental]` block.
+
+The trade-off when enabled: an extra hardware cursor is visible in the outer terminal for apps that hide the cursor without painting a replacement (vim normal mode, etc.). Pair the reveal with `cjk_ime_agents` to scope it to specific TUIs.
+
+## Prefix input source switching
+
+On macOS, prefix-mode commands can be hard to use while a non-ASCII input source is active because prefix commands are still interpreted through the host input source.
+
+Set `switch_ascii_input_source_in_prefix = true` to switch the host input source to the system ASCII-capable input source while prefix mode is active:
+
+```toml
+[experimental]
+switch_ascii_input_source_in_prefix = false
+```
+
+When enabled, Herdr switches input sources only after prefix mode is entered, then restores the previous input source when prefix mode exits. The setting is macOS-only and is a no-op on other platforms or when the system input-source switch fails.
+
+You can also toggle it from Settings > Experiments > switch to ascii input source in prefix (macOS).
+
+## 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
+
+Logs are useful when diagnosing startup warnings, integration state, or socket API behavior.
+
+Common log files:
+
+```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.
diff --git a/docs/versions/0.7.0/website/src/content/docs/how-to-work.mdx b/docs/versions/0.7.0/website/src/content/docs/how-to-work.mdx
new file mode 100644
index 00000000..812aae9f
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/how-to-work.mdx
@@ -0,0 +1,103 @@
+---
+title: How to work with Herdr
+description: Run Herdr locally, inside SSH, or through remote attach.
+---
+
+Run Herdr where the work lives. Attach from wherever you are.
+
+Herdr is a background session server plus one or more terminal clients. Panes keep running in the server. Clients attach, detach, and render the session.
+
+## Local work
+
+Start Herdr from the project directory:
+
+```bash
+herdr
+```
+
+Herdr starts or attaches to your local background session automatically. You do not manage sockets. Run shells, servers, tests, and agents normally inside panes.
+
+Detach the client with `ctrl+b q`. Your panes keep running.
+
+Reattach later:
+
+```bash
+herdr
+```
+
+If you want to end the session and stop its panes, stop the server:
+
+```bash
+herdr server stop
+```
+
+## Remote work through normal SSH
+
+SSH to the machine that has the code and credentials, then run Herdr there:
+
+```bash
+ssh you@server
+herdr
+```
+
+This works like a terminal multiplexer. Your shell is remote. The Herdr server is remote. The agents and panes run on the remote machine. Detach with `ctrl+b q`, disconnect, then SSH back and run `herdr` again.
+
+Use this path when you already live inside an SSH shell, when you are on a phone or tablet SSH client, or when you want the simplest possible setup.
+
+## Work from your phone
+
+You do not need a Herdr mobile app or a web dashboard. Install any SSH client on your phone, connect to the machine where your agents run, and start Herdr there:
+
+```bash
+ssh you@server
+herdr
+```
+
+The same persistent Herdr session opens in your phone terminal. The TUI adapts to narrow screens, so you can inspect agents, switch workspaces, and check panes without leaving SSH.
+
+On iPhone, apps like [moshi](https://getmoshi.app/) work well.
+
+<div class="mobile-doc-shots">
+ <figure>
+ <img src="/assets/mobile-agent-session-v2.jpeg" alt="Herdr agent session over SSH on a phone" loading="lazy" />
+ <figcaption>agent session over SSH</figcaption>
+ </figure>
+ <figure>
+ <img src="/assets/mobile-switch-menu-v2.jpeg" alt="Herdr responsive switch menu on a phone" loading="lazy" />
+ <figcaption>responsive switch menu</figcaption>
+ </figure>
+</div>
+
+## Remote work from your local terminal
+
+Attach through SSH without opening a shell first:
+
+```bash
+herdr --remote workbox
+herdr --remote ssh://you@server:2222
+```
+
+Your local Herdr acts as a thin client. It connects over SSH, starts or attaches to the remote Herdr server, and streams the UI back to your local terminal.
+
+Use this path when you want the remote session to feel local. The client runs on your machine, so local desktop features such as image clipboard paste can be bridged to the remote server. If you SSH first and run `herdr` on the server, Herdr runs entirely on that server and cannot read your local desktop clipboard.
+
+For repeat targets, put the host in your SSH config:
+
+```text
+Host workbox
+ HostName server.example.com
+ User you
+ Port 2222
+```
+
+Then attach with:
+
+```bash
+herdr --remote workbox
+```
+
+## Which path to use
+
+Use `herdr` for local work. Use `ssh you@server` then `herdr` when you want Herdr to behave like tmux on that remote shell or when you are using a phone SSH client. Use `herdr --remote <host>` when you want a local thin client for a remote session, including local clipboard image paste bridging.
+
+For remote bootstrap details, named remote sessions, custom binaries, direct terminal attach, and `--no-session`, see [Persistence and remote access](/docs/persistence-remote/).
diff --git a/docs/versions/0.7.0/website/src/content/docs/index.mdx b/docs/versions/0.7.0/website/src/content/docs/index.mdx
new file mode 100644
index 00000000..1502462d
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/index.mdx
@@ -0,0 +1,77 @@
+---
+title: Herdr documentation
+description: Terminal workspace manager for AI coding agents.
+template: splash
+hero:
+ tagline: "Install, learn, and configure Herdr. Start on the path that matches you — no multiplexer experience required."
+ image:
+ file: ../../../public/assets/logo.svg
+ actions:
+ - text: Install Herdr
+ link: /docs/install/
+ - text: Quick start
+ link: /docs/quick-start/
+ variant: secondary
+---
+
+import { Card, CardGrid } from '@astrojs/starlight/components';
+
+## Pick your path
+
+<CardGrid>
+ <Card title="New to terminal multiplexers?">
+ You don't need to learn shortcuts to start. Herdr is mouse-first: click panes, drag borders, split and switch from right-click menus.
+
+ [Quick start →](/docs/quick-start/)
+ </Card>
+ <Card title="Coming from tmux or zellij?">
+ You already know the model. The prefix is `ctrl+b`, panes persist, detach and reattach work the way you expect.
+
+ [Concepts →](/docs/concepts/) · [Keybindings →](/docs/configuration/#keybindings)
+ </Card>
+</CardGrid>
+
+## Or let your agent introduce you
+
+Already running an AI coding agent? Let it do the onboarding. Paste this prompt:
+
+```text
+Help me understand and set up Herdr. Read https://herdr.dev/agent-guide.md first, then walk me through it step by step.
+```
+
+The guide teaches your agent Herdr's concepts, setup, configuration, and common fixes, so its answers stay accurate instead of improvised.
+
+## Core guides
+
+<CardGrid>
+ <Card title="Agents">
+ See supported agents, detection behavior, integrations, custom labels, and direct attach.
+
+ [Understand agents →](/docs/agents/)
+ </Card>
+ <Card title="Session state">
+ Understand detach, restart restore, pane history replay, native agent resume, and live handoff.
+
+ [Compare state paths →](/docs/session-state/)
+ </Card>
+ <Card title="Configuration">
+ Configure keybindings, themes, sidebar behavior, notifications, scrollback, and advanced options.
+
+ [Configure Herdr →](/docs/configuration/)
+ </Card>
+ <Card title="API">
+ Control Herdr from scripts, tools, and agents through the CLI and local socket API.
+
+ [Read the API guide →](/docs/socket-api/)
+ </Card>
+ <Card title="Plugins">
+ Author local executable workflow plugins with manifest actions and event hooks.
+
+ [Write a plugin →](/docs/plugins/)
+ </Card>
+ <Card title="Marketplace">
+ Share plugins from GitHub today and tag your repo to be listed when the marketplace launches.
+
+ [Publish a plugin →](/docs/marketplace/)
+ </Card>
+</CardGrid>
diff --git a/docs/versions/0.7.0/website/src/content/docs/install.mdx b/docs/versions/0.7.0/website/src/content/docs/install.mdx
new file mode 100644
index 00000000..e4223263
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/install.mdx
@@ -0,0 +1,151 @@
+---
+title: Install Herdr
+description: Install, update, and verify Herdr on Linux, macOS, and Windows beta.
+---
+
+Herdr ships stable binaries for Linux and macOS. Native Windows support is preview-only beta.
+
+## Install
+
+On Linux or macOS, run:
+
+```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"
+```
+
+The installer downloads the right release binary for your platform and places it on your PATH. The Windows installer defaults to preview, writes that channel to Herdr's config, uses versioned install folders, and updates a `current` junction, so updates do not need to overwrite a running `herdr.exe`.
+
+## Install with Homebrew
+
+If you already use Homebrew:
+
+```bash
+brew install herdr
+```
+
+## Install with mise
+
+If you already use mise:
+
+```bash
+mise use -g herdr
+```
+
+If mise reports `herdr not found in mise tool registry`, update mise and retry. Older mise versions predate the Herdr registry entry; `mise use -g github:ogulcancelik/herdr` works as a temporary fallback.
+
+## Install with Nix
+
+If you already use Nix, Herdr provides a flake that builds Herdr from source:
+
+```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
+```
+
+Replace `v0.x.y` with the latest release tag. You can omit the tag to track `master`, but release tags are recommended for normal installs.
+
+The flake also exposes a development shell:
+
+```bash
+nix develop github:ogulcancelik/herdr
+```
+
+Update through the same Nix workflow you used to install Herdr. For a profile install, list your profile entries and upgrade the Herdr entry:
+
+```bash
+nix profile list
+nix profile upgrade <index-or-name>
+```
+
+If Herdr is an input in your own flake, update that input and rebuild your system, Home Manager, or development environment:
+
+```bash
+nix flake update herdr
+```
+
+## Download manually
+
+You can also download a binary from [GitHub releases](https://github.com/ogulcancelik/herdr/releases).
+
+Choose the asset that matches your system:
+
+| System | Asset |
+| --- | --- |
+| Linux x86_64 | `herdr-linux-x86_64` |
+| Linux aarch64 | `herdr-linux-aarch64` |
+| macOS Intel | `herdr-macos-x86_64` |
+| macOS Apple silicon | `herdr-macos-aarch64` |
+
+On Linux or macOS, make it executable and move it somewhere on your PATH.
+
+```bash
+chmod +x herdr-linux-x86_64
+mv herdr-linux-x86_64 ~/.local/bin/herdr
+```
+
+### Windows beta downloads
+
+Windows binaries are published only on preview releases while native Windows support is in beta. Use the preview installer above for normal testing, or download the Windows asset from a preview GitHub prerelease:
+
+| System | Asset |
+| --- | --- |
+| Windows x86_64 beta | `herdr-windows-x86_64.exe` |
+
+## Verify
+
+Start Herdr:
+
+```bash
+herdr
+```
+
+If your shell cannot find `herdr`, restart the terminal or check that the install directory is on your PATH.
+
+## Update
+
+Herdr checks for new releases and notifies you in the app. You can update manually:
+
+```bash
+herdr update
+```
+
+`herdr update` is for installs managed by Herdr's own installer. Homebrew, mise, and Nix installs are updated through those package managers instead.
+
+On Linux and macOS, Herdr uses the stable update channel by default. To opt into preview builds from `master`, set the channel:
+
+```bash
+herdr channel set preview
+```
+
+Switch Linux and macOS direct installs back to stable the same way:
+
+```bash
+herdr channel set stable
+```
+
+For direct installs, changing channels also checks that channel and installs its latest binary. If that update fails, run `herdr update` to retry from the configured channel.
+
+Preview builds are manually published GitHub prereleases from the current development branch. They are useful when you want fixes before the next stable release, but they can regress. Homebrew, mise, and Nix installs do not use the preview channel.
+
+Windows beta builds are preview-only for now. `herdr channel set stable` is rejected on Windows until stable Windows releases are available.
+
+By default, `herdr update` installs the new binary and leaves compatible running sessions alone. If an update changes Herdr's client/server protocol, Herdr asks whether to stop the old server after installing. Stop the old server to use the new version. Stopping exits pane processes. For the default session, run `herdr server stop`, then run `herdr` again. For a named session, run `herdr session stop <name>`, then run `herdr session attach <name>` again.
+
+To opt into experimental live server handoff for supported running sessions, run:
+
+```bash
+herdr update --handoff
+```
+
+Live handoff does not apply to Homebrew, mise, or Nix package-manager updates. For those installs, update with the package manager, then restart that Herdr session when you are ready to use the new server. If a running session still uses the old server, stop it with `herdr server stop` or `herdr session stop <name>`, then run Herdr again.
+
+## Requirements
+
+Stable Herdr releases support Linux and macOS. Native Windows builds are preview-only beta releases; see [Windows beta](/docs/windows-beta/) for supported workflows and known limitations.
diff --git a/docs/versions/0.7.0/website/src/content/docs/integrations.mdx b/docs/versions/0.7.0/website/src/content/docs/integrations.mdx
new file mode 100644
index 00000000..797456e6
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/integrations.mdx
@@ -0,0 +1,286 @@
+---
+title: Integrations
+description: Install Herdr integrations for Pi, OMP, Claude Code, Codex, GitHub Copilot CLI, Devin CLI, Droid, Kimi Code CLI, OpenCode, Kilo Code CLI, Hermes Agent, Qoder CLI, and Cursor Agent CLI.
+---
+
+Herdr detects supported agents automatically. Official integrations can add native session identity for restore, lifecycle state reports, or both.
+
+Use integrations when you want native agent session restore from Claude Code/Codex/Copilot/Devin-style hooks, direct lifecycle reports from Pi/OMP/Kimi/OpenCode/Kilo/Hermes-style hooks or plugins, or both. See [Agents](/docs/agents/) for the full status authority model.
+
+## Install integrations
+
+Open settings inside Herdr and use the integrations tab to install recommended integrations for agents found on your `PATH`, or run commands manually:
+
+```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
+```
+
+## Uninstall integrations
+
+```bash
+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
+```
+
+## How Herdr uses integrations
+
+Herdr uses integrations in two different ways:
+
+| Integration type | Agents | Effect |
+| --- | --- | --- |
+| Lifecycle authority | Pi, OMP, Kimi Code CLI, OpenCode, Kilo Code CLI, Hermes Agent | When installed and actively reporting for the pane, hook or plugin events author `idle`, `working`, and `blocked`. Herdr does not also use screen manifest fallback for that same lifecycle authority. |
+| Session identity | Claude Code, Codex, GitHub Copilot CLI, Devin CLI, Droid, Qoder CLI, Cursor Agent CLI | The integration reports native session references for restore. State still comes from Herdr's screen manifest detection. |
+
+Custom socket integrations can also report state when they define state that is not visible in the native terminal UI.
+
+Some integrations report native agent session references. Herdr uses official session references to resume Claude Code, Codex, Devin CLI, Droid, Kimi Code CLI, Qoder CLI, Cursor Agent CLI, GitHub Copilot CLI, Pi, Hermes Agent, OpenCode, and Kilo Code CLI panes after a Herdr server restart unless `[session] resume_agents_on_restore = false` disables it.
+
+Native session restore requires current Herdr integrations: Pi integration version `2`, Claude Code version `6`, Codex version `5`, GitHub Copilot CLI version `2`, Devin CLI version `1`, Droid version `2`, Kimi Code CLI version `3`, Qoder CLI version `2`, Cursor Agent CLI version `1`, OpenCode version `5`, Kilo Code CLI version `1`, or Hermes Agent version `2`. OMP integration version `2` reports agent state only. Check installed versions with `herdr integration status`.
+
+## Pi
+
+Install the Pi integration:
+
+```bash
+herdr integration install pi
+```
+
+Herdr writes the bundled extension to:
+
+```text
+~/.pi/agent/extensions/herdr-agent-state.ts
+```
+
+If `PI_CODING_AGENT_DIR` is set, Herdr writes to `$PI_CODING_AGENT_DIR/extensions/herdr-agent-state.ts` instead. The extensions directory must already exist. Uninstall removes only that extension file.
+
+## OMP
+
+Install the OMP integration:
+
+```bash
+herdr integration install omp
+```
+
+Herdr writes the bundled extension to:
+
+```text
+~/.omp/agent/extensions/herdr-omp-agent-state.ts
+```
+
+If `PI_CODING_AGENT_DIR` is set, Herdr writes to `$PI_CODING_AGENT_DIR/extensions/herdr-omp-agent-state.ts` instead. The extensions directory must already exist. Uninstall removes only that extension file.
+
+The OMP integration reports `omp` as the agent label through Herdr's socket API. It does not require native process detection for the `omp` executable.
+
+## Claude Code
+
+Install the Claude Code hook:
+
+```bash
+herdr integration install claude
+```
+
+The hook reports Claude Code session identity to the local Herdr socket on session start. Claude Code state comes from Herdr's screen manifest detection.
+
+Herdr uses `~/.claude` by default, or `CLAUDE_CONFIG_DIR` when set. The Claude config directory must already exist. Install writes `hooks/herdr-agent-state.sh` and updates `settings.json` with Herdr hook entries. Uninstall removes the matching hook entries and deletes the hook script.
+
+## Codex
+
+Install the Codex hook:
+
+```bash
+herdr integration install codex
+```
+
+The Codex hook reports session identity through the same local socket API used by other integrations. Codex state comes from Herdr's screen manifest detection.
+
+Herdr uses `~/.codex` by default, or `CODEX_HOME` when set. The Codex config directory must already exist. Install writes `herdr-agent-state.sh`, updates `hooks.json`, and ensures `[features] hooks = true` in `config.toml`. It also removes the deprecated top-level `codex_hooks` flag when present. Uninstall removes Herdr entries from `hooks.json` and deletes the hook script, but leaves `config.toml` unchanged.
+
+## GitHub Copilot CLI
+
+Install the GitHub Copilot CLI hook:
+
+```bash
+herdr integration install copilot
+```
+
+The Copilot hook reports session identity through the same local socket API used by other integrations. Copilot state comes from Herdr's screen manifest detection.
+
+Herdr uses `~/.copilot` by default, or `COPILOT_HOME` when set. The Copilot config directory must already exist. Install writes `hooks/herdr-agent-state.sh` and updates `settings.json` with a `SessionStart` hook entry. Uninstall removes Herdr entries from `settings.json` and deletes the hook script.
+
+After Copilot emits a session-bearing event, Herdr can use the reported session id to resume the pane with `copilot --resume=<id>`.
+
+## Devin CLI
+
+Install the Devin CLI hook:
+
+```bash
+herdr integration install devin
+```
+
+The hook reports native session identity from Devin session, prompt, tool-use, permission, and stop events. Devin state still comes from Herdr's screen manifest and OSC detection because Devin hooks do not emit a reliable state transition after every permission cancellation or user interrupt.
+
+Herdr uses `~/.config/devin` by default, or `$XDG_CONFIG_HOME/devin` when `XDG_CONFIG_HOME` is set. The Devin config directory must already exist. Install writes `herdr-agent-state.sh` and updates `config.json` with Herdr hook entries. The hook refreshes the session reference while Devin runs. Uninstall removes Herdr entries from `config.json` and deletes the hook script.
+
+Herdr resumes stored Devin sessions with `devin --resume <id>`. Native screen manifest detection remains the state authority whether or not the hook is installed.
+
+## Kimi Code CLI
+
+Install the Kimi Code CLI hook:
+
+```bash
+herdr integration install kimi
+```
+
+The hook reports Kimi session identity and lifecycle state to Herdr for native restore and authoritative `idle`, `working`, and `blocked` status. It requires Kimi Code CLI `0.14.0` or newer.
+
+Herdr uses `~/.kimi-code` by default, or `KIMI_CODE_HOME` when set. The Kimi Code config directory must already exist. Install writes `hooks/herdr-agent-state.sh` and appends Herdr-managed `[[hooks]]` entries to `config.toml`. Uninstall removes the Herdr-managed config block and deletes the hook script.
+
+Herdr resumes stored Kimi sessions with `kimi --session <id>`.
+
+## Droid
+
+Install the Droid hook:
+
+```bash
+herdr integration install droid
+```
+
+The Droid hook reports session identity through the same local socket API used by other integrations. Lifecycle state still comes from Herdr's screen manifest detection because Droid hooks do not cover every lifecycle transition.
+
+Herdr uses `~/.factory` for Droid hooks. The Factory config directory must already exist. Install writes `hooks/herdr-agent-state.sh`, updates `settings.json` with a Herdr `SessionStart` hook entry, and removes older Herdr Droid hook entries from `hooks.json` if present. Uninstall removes Herdr entries from both config files and deletes the hook script.
+
+After Droid emits a session start event, Herdr can use the reported session id to resume the pane with `droid --resume <id>`.
+
+## OpenCode
+
+Install the OpenCode plugin:
+
+```bash
+herdr integration install opencode
+```
+
+Herdr writes the plugin to `~/.config/opencode/plugins/herdr-agent-state.js`. The OpenCode config directory must already exist. Uninstall removes only that plugin file.
+
+The plugin reports lifecycle state and session identity while OpenCode runs inside a Herdr pane. After OpenCode emits a session-bearing event, Herdr can use the reported session id to resume the pane with `opencode --session <id>`. Native screen manifest detection remains available when the plugin is not installed.
+
+## Kilo Code CLI
+
+Install the Kilo Code CLI plugin:
+
+```bash
+herdr integration install kilo
+```
+
+Herdr writes the plugin to `~/.config/kilo/plugin/herdr-agent-state.js`. The Kilo config directory must already exist. Uninstall removes only that plugin file.
+
+The plugin reports lifecycle state and session identity while Kilo runs inside a Herdr pane. After Kilo emits a session-bearing event, Herdr can use the reported session id to resume the pane with `kilo --session <id>`. Native screen manifest detection remains available when the plugin is not installed.
+
+## Hermes Agent
+
+Install the Hermes Agent plugin:
+
+```bash
+herdr integration install hermes
+```
+
+Herdr writes `~/.hermes/plugins/herdr-agent-state/` and enables `herdr-agent-state` in `~/.hermes/config.yaml`. The Hermes config directory must already exist. Restart Hermes after installing so the plugin loads. Uninstall removes the plugin directory and removes `herdr-agent-state` from `plugins.enabled`.
+
+The plugin reports lifecycle, tool, approval state, and session id while Hermes runs inside a Herdr pane. Herdr can use the reported session id to resume the pane with `hermes --resume <id>`. Native screen manifest detection remains available when the plugin is not installed.
+
+## Qoder CLI
+
+Install the Qoder CLI hook:
+
+```bash
+herdr integration install qodercli
+```
+
+The hook reports Qoder CLI session identity to Herdr for native restore. Lifecycle state still comes from Herdr's screen manifest detection because Qoder hooks do not cover every lifecycle transition.
+
+Herdr uses `~/.qoder` by default, or `QODER_CONFIG_DIR` when set. The Qoder config directory must already exist. Install writes `hooks/herdr-agent-state.sh` and updates `settings.json` with Herdr hook entries. Uninstall removes the matching hook entries and deletes the hook script.
+
+Herdr resumes stored Qoder CLI sessions with `qodercli --resume <id>`.
+
+Native screen manifest detection remains available when the hook is not installed.
+
+## Cursor Agent CLI
+
+Install the Cursor Agent CLI hook:
+
+```bash
+herdr integration install cursor
+```
+
+The hook reports session identity through Cursor's `sessionStart` hook while Cursor Agent CLI runs inside a Herdr pane. Cursor state comes from Herdr's screen manifest detection.
+
+Herdr uses `~/.cursor` by default, or `CURSOR_CONFIG_DIR` when set. The Cursor config directory must already exist. Install writes `herdr-agent-state.sh` and adds a Herdr `sessionStart` entry to `hooks.json`. Uninstall removes the matching hook entry and deletes the hook script.
+
+After Cursor emits a session start event, Herdr can use the reported session id to resume the pane with `cursor-agent --resume <id>`. The `cursor-agent` command must be on `PATH` when Herdr restores the pane; Herdr does not launch the generic `agent` command.
+
+## Custom status labels
+
+Integrations can report a short visual label without changing the semantic state.
+
+For example, an agent can remain semantically `working` while showing `indexing` in the UI.
+
+```bash
+herdr pane report-agent w1:p1 \
+ --source custom:docs \
+ --agent docs-bot \
+ --state working \
+ --custom-status indexing
+```
+
+User hooks that run next to a Herdr-managed integration should use metadata instead of `report-agent`. Metadata changes presentation without taking over the integration's `idle`, `working`, `blocked`, or session restore authority. `--agent` guards the report so it only applies while that authoritative agent is active. `--applies-to-source` guards the report so it only applies while that lifecycle authority source is active. `--display-agent` changes the visible name.
+
+```bash
+herdr pane report-metadata "$HERDR_PANE_ID" \
+ --source user:claude-title \
+ --agent claude \
+ --title "Refactor auth middleware" \
+ --display-agent "Claude: auth" \
+ --custom-status "refactor auth" \
+ --state-label working="refactoring auth" \
+ --ttl-ms 3600000
+```
+
+Custom status and state labels are visual-only. Waits, notifications, and workspace rollups still use the semantic state.
+
+## Debug integration state
+
+List known agents:
+
+```bash
+herdr agent list
+```
+
+Read a pane when you need to verify what Herdr can see:
+
+```bash
+herdr pane read w1:p1 --source recent --lines 50
+```
+
+If integration state looks wrong, first confirm the agent is running inside Herdr and that the relevant hook or plugin was installed for the same user account.
diff --git a/docs/versions/0.7.0/website/src/content/docs/keyboard.mdx b/docs/versions/0.7.0/website/src/content/docs/keyboard.mdx
new file mode 100644
index 00000000..07f11362
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/keyboard.mdx
@@ -0,0 +1,112 @@
+---
+title: Keyboard
+description: What the prefix is, which bindings to learn first, and how to go prefix-free.
+---
+
+:::tip[Coming from tmux or zellij?]
+You already know this model. Jump to the [keybinding reference](/docs/configuration/#keybindings) for the full default keymap and config syntax.
+:::
+
+Herdr is mouse-native. You can click panes, tabs, workspaces, and agents, drag split borders, and use right-click menus without learning a single keybinding. Keyboard control is an optional layer, not a requirement.
+
+## What the prefix is
+
+A terminal multiplexer sits between your terminal and the programs running inside it. Those programs already use most key combinations: `ctrl+c` interrupts, `ctrl+r` searches history, editors claim nearly everything else. If Herdr grabbed common keys directly, it would break the programs inside it.
+
+The prefix solves this. Press the prefix key, default `ctrl+b`, and the next keypress goes to Herdr instead of your terminal. `prefix+c` means: press `ctrl+b`, release, then press `c`. One reserved key instead of dozens.
+
+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` |
+
+These cover most daily movement. Everything else can stay on the mouse.
+
+## The rest, by task
+
+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 the binding syntax live in the [keybinding reference](/docs/configuration/#keybindings).
+
+## Copy mode
+
+Press `prefix+[` to enter copy mode for the focused pane. Use `h/j/k/l`, `w/b/e`, and `{`/`}` to move, `v` or Space to start a selection, `y` or Enter to copy it, and `q` or Esc to leave without copying. Mouse drag-select copies without entering copy mode at all.
+
+## Change anything
+
+Every binding is configurable, including the prefix itself:
+
+```toml
+[keys]
+prefix = "ctrl+a"
+```
+
+## Going prefix-free
+
+You can bind Herdr actions to direct chords that need no prefix at all. The hard part is knowing which chords are safe, because terminals, shells, and desktop environments already own most of the keyboard.
+
+Any chord works as a binding: `ctrl+j`, `alt+k`, whatever fits your hands. But a chord has to survive three layers before Herdr sees it: your operating system, your outer terminal (Ghostty, iTerm2, and others ship their own defaults), and the programs running inside the pane. `ctrl+j` reaches Herdr fine, but shells and editors treat it as enter. `alt+k` is free on Linux, but macOS composes it into a special character in most terminals. If you pick chords from these families, double-check them against your own terminal and OS shortcuts.
+
+We mapped the default keybindings of Ghostty, iTerm2, Terminal.app, kitty, WezTerm, Alacritty, Warp, Windows Terminal, GNOME Terminal, and Konsole, plus the global shortcuts of GNOME and KDE. One modifier family is almost untouched everywhere: `ctrl+alt`. Terminals leave it free, it is not affected by the macOS option-key composing behavior that blocks plain `alt` chords, and it transmits even in terminals without a modern keyboard protocol. It is the safe default recommendation; the choice stays yours.
+
+This setup keeps the prefix bindings working and adds direct chords on top:
+
+```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 taken elsewhere. Avoid these:
+
+| 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, your terminal or desktop environment consumed it before Herdr could see it. Rebind either side: free the chord in the terminal's settings, or pick another chord in Herdr.
diff --git a/docs/versions/0.7.0/website/src/content/docs/marketplace.mdx b/docs/versions/0.7.0/website/src/content/docs/marketplace.mdx
new file mode 100644
index 00000000..be662b8a
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/marketplace.mdx
@@ -0,0 +1,37 @@
+---
+title: Marketplace
+description: Publish and share Herdr plugins, and get listed when the marketplace launches.
+---
+
+The Herdr plugin marketplace is a discoverable index of installable plugins. It
+is not live yet. This page is how to be ready for it.
+
+## Share a plugin today
+
+The marketplace adds discovery on top of installation; it does not replace it.
+Anyone can already install your plugin straight from GitHub:
+
+```bash
+herdr plugin install owner/repo[/subdir...]
+```
+
+Publish a normal public GitHub repository with a `herdr-plugin.toml` manifest at
+its root, or in a subdirectory, and that command works now. See
+[Plugins](/docs/plugins/) for the manifest and authoring reference.
+
+## Get listed when it launches
+
+If you want your plugin to appear in the website marketplace when discovery
+launches, add the GitHub topic `herdr-plugin` to your repository now. That
+topic is the signal the future index will use for discovery, so tagging a
+public plugin today means it can be listed when the marketplace goes live.
+
+## What a listing will show
+
+A marketplace card will surface your plugin's `id`, `name`, `description`,
+declared `platforms`, and a link back to the source repository. Getting that
+manifest metadata right today is what makes your listing accurate later. Declare
+`platforms` honestly, because the index will use it to show where a plugin runs.
+
+Plugins stay ordinary GitHub repositories. The marketplace is a discovery and
+trust layer on top of the same `herdr plugin install` path you can use now.
diff --git a/docs/versions/0.7.0/website/src/content/docs/persistence-remote.mdx b/docs/versions/0.7.0/website/src/content/docs/persistence-remote.mdx
new file mode 100644
index 00000000..80cf19d3
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/persistence-remote.mdx
@@ -0,0 +1,132 @@
+---
+title: Persistence and remote access
+description: Detach from Herdr, reattach later, use named sessions, and connect over SSH.
+---
+
+Herdr keeps panes running in a background server. Your terminal client can detach and reconnect later.
+
+For the local, SSH, and `herdr --remote` workflows, see [How to work with Herdr](/docs/how-to-work/).
+
+## Detach and reattach
+
+Detach the client with `ctrl+b q`; panes and agents keep running. Reattach by running `herdr` again. Stop the session and its panes with `herdr server stop`.
+
+When Herdr starts again after a full server stop, it restores the saved session shape. For what survives detach, server restart, screen history replay, native agent session restore, and live handoff, see [Session state and restore](/docs/session-state/).
+
+## Named sessions
+
+Use named sessions when you want independent Herdr servers.
+
+```bash
+herdr session list
+herdr session attach work
+herdr session attach side-project
+herdr session stop work
+herdr session delete side-project
+```
+
+A named session has its own panes, tabs, workspaces, sockets, and runtime state. It still shares the same global config file.
+
+Use `--json` for scripts:
+
+```bash
+herdr session list --json
+herdr session stop work --json
+herdr session delete side-project --json
+```
+
+## Remote attach over SSH
+
+There are two remote modes; [How to work with Herdr](/docs/how-to-work/) compares them. SSH to the server and run `herdr` there for the tmux-style path. Or attach through SSH from your local machine:
+
+```bash
+herdr --remote workbox
+herdr --remote ssh://you@server:2222
+```
+
+In this mode your local Herdr is a thin client. It connects over SSH, starts or attaches to the remote Herdr server, and streams the UI back to your local terminal. Because the client runs locally, Herdr can bridge local desktop features such as image clipboard paste into the remote session by copying the image to a remote temp file and pasting that path.
+
+By default, `herdr --remote` uses your local Herdr keybindings for that attach. This keeps local muscle memory even when the remote server has different config. The local keybindings are a snapshot from attach time; detach and reattach after editing local keybindings. Use `--remote-keybindings server` when you want the remote server config instead. Local custom command keybindings are not sent, because those commands would run on the remote host.
+
+For repeat targets, use your SSH config:
+
+```text
+Host workbox
+ HostName server.example.com
+ User you
+ Port 2222
+```
+
+Then attach with:
+
+```bash
+herdr --remote workbox
+```
+
+Remote attach supports Linux and macOS hosts on x86_64 and aarch64. Herdr checks the remote platform, prefers a matching `herdr` already on the remote `PATH`, then checks `~/.local/bin/herdr`. If no matching binary exists, interactive runs prompt to install one to `~/.local/bin/herdr`; non-interactive runs fail instead of modifying the host. If `~/.local/bin` is not on the remote `PATH`, Herdr warns after install.
+
+Native Windows `herdr --remote` is not part of the Windows beta. From Windows, SSH into the server and run `herdr` there.
+
+By default, `herdr --remote` runs the bridge through a temporary SSH config that includes your SSH config first, then adds fallback keepalive settings. Existing user keepalive settings win. Set `[remote].manage_ssh_config = false` to use plain `ssh` without Herdr's generated bridge config.
+
+By default, remote attach uses the normal restart/stop flow if it needs to replace or restart a running remote server. To opt into experimental live handoff for a supported running remote server, pass `--handoff`:
+
+```bash
+herdr --remote workbox --handoff
+```
+
+If you SSH into the server first and run `herdr` there, Herdr runs entirely on the server. That mode is useful and simple, but it cannot access your local desktop clipboard beyond normal terminal text paste.
+
+When your local and remote platforms match, Herdr can copy the current local binary for direct installs. For Homebrew, mise, and Nix installs, or when the platforms differ, it downloads the matching release asset for the current client version from `https://herdr.dev/latest.json`.
+
+For local builds or custom binaries, set `HERDR_REMOTE_BINARY` to a local file path before running remote attach.
+
+```bash
+HERDR_REMOTE_BINARY=target/release/herdr herdr --remote workbox
+```
+
+## Remote named sessions
+
+Use `--session` with `--remote` to attach to a named session on the remote host:
+
+```bash
+herdr --remote workbox --session agents
+```
+
+## Direct terminal attach
+
+Full Herdr attach opens the whole workspace UI. Direct attach opens one server-owned terminal in your current terminal.
+
+Direct terminal attach is Unix-only in the Windows beta.
+
+Attach by agent target:
+
+```bash
+herdr agent attach reviewer
+```
+
+Attach by terminal ID:
+
+```bash
+herdr terminal attach term_abc123
+```
+
+Direct attach streams the current rendered terminal state, then live ANSI frames. Input goes straight to that terminal.
+
+Detach with `ctrl+b q`. Send a literal `ctrl+b` with `ctrl+b ctrl+b`.
+
+Only one writable direct attach client owns input and resize for a terminal. Use `--takeover` to replace an existing owner:
+
+```bash
+herdr terminal attach term_abc123 --takeover
+```
+
+## Single-process escape hatch
+
+Use `--no-session` to run Herdr without the background server/client split:
+
+```bash
+herdr --no-session
+```
+
+This is mainly an escape hatch for debugging or compatibility. The default persistent session mode is the normal path.
diff --git a/docs/versions/0.7.0/website/src/content/docs/plugins.mdx b/docs/versions/0.7.0/website/src/content/docs/plugins.mdx
new file mode 100644
index 00000000..09d89bc0
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/plugins.mdx
@@ -0,0 +1,294 @@
+---
+title: Plugins
+description: Author local Herdr plugins with manifest actions, event hooks, and panes.
+---
+
+Herdr plugins are shareable, executable workflow packages. A plugin can be a
+Bash script, JavaScript app, Lua script, Rust binary, or any other argv command
+your machine can run. Herdr owns the host surface: installation, manifest
+validation, keybindings, terminal panes, events, invocation context, and socket
+access. The plugin owns its implementation language, dependencies, files, and
+durable state.
+
+Plugins exist so Herdr can stay lean. The core stays focused on terminal
+workspaces, panes, agents, and a stable CLI/socket API. Plugins turn that
+existing extension surface into reusable workflows that people can build,
+install, and share without adding every workflow to Herdr itself.
+
+A plugin is not an SDK integration. It is a directory with a
+`herdr-plugin.toml` manifest and commands Herdr can launch. Herdr validates the
+manifest, injects runtime context, starts the declared commands, and records
+logs. The commands call back into Herdr through the CLI or socket when they need
+to do more work.
+
+There is no separate plugin SDK or restricted command set. The entire Herdr CLI
+is the plugin API: every command in the [CLI reference](/docs/cli-reference/) is
+available to a plugin, and anything you can run as `herdr ...` yourself a plugin
+can run too. Most plugins should call Herdr through `HERDR_BIN_PATH`, which
+points at the running Herdr binary. That keeps plugins portable across Unix
+sockets and Windows named pipes. Use the [socket API](/docs/socket-api/) when
+you want to send raw JSON requests yourself.
+
+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
+
+The manifest is the contract between Herdr and the plugin. It declares package
+metadata, supported platforms, optional build commands, and the entrypoints
+Herdr can run.
+
+```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"]
+
+[[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"
+```
+
+Top-level `id`, `name`, `version`, and `min_herdr_version` are required.
+Set `min_herdr_version` to the oldest Herdr version that supports the plugin
+APIs, event names, and manifest fields your plugin uses. Herdr refuses to link
+or install a plugin when its minimum version is newer than the current binary.
+`description` is optional. Plugin ids may use ASCII letters, digits, dot,
+colon, underscore, and hyphen.
+
+Action ids, pane ids, and link handler ids are local ids inside the plugin.
+They may use ASCII letters, digits, colon, underscore, and hyphen, but not
+dots. Each id type must be unique inside a plugin. Herdr qualifies action ids
+as `plugin.id.action` when it needs a globally unique name.
+
+Use `platforms = ["linux", "macos", "windows"]` to declare where the plugin
+can run. Build commands, actions, event hooks, panes, and link handlers can
+also declare their own `platforms`; item-level platforms override the top-level
+list. Local plugins without top-level `platforms` link with a warning.
+
+`command` values are argv arrays. Herdr does not run them through a shell, so
+there is no shell expansion unless your command starts a shell itself. Put
+language-specific behavior in your script or binary.
+
+## First plugin
+
+Start with a directory that contains `herdr-plugin.toml` and one executable
+script or program:
+
+```text
+my-plugin/
+ herdr-plugin.toml
+ index.js
+```
+
+```toml
+id = "example.workspace-tools"
+name = "Workspace Tools"
+version = "0.1.0"
+min_herdr_version = "0.7.0"
+description = "Small workspace helpers"
+platforms = ["linux", "macos", "windows"]
+
+[[actions]]
+id = "list-workspaces"
+title = "List workspaces"
+contexts = ["workspace"]
+command = ["node", "index.js"]
+```
+
+Inside the command, call back into Herdr with `HERDR_BIN_PATH`:
+
+```js
+const { spawnSync } = require("node:child_process");
+
+const herdr = process.env.HERDR_BIN_PATH ?? "herdr";
+const result = spawnSync(herdr, ["workspace", "list"], {
+ encoding: "utf8",
+ stdio: ["ignore", "pipe", "pipe"],
+});
+
+process.stdout.write(result.stdout);
+process.stderr.write(result.stderr);
+process.exit(result.status ?? 1);
+```
+
+This example uses Node, but nothing about plugins requires Node. The manifest
+could launch Bash, PowerShell, Python, Rust, Go, Lua, Bun, or any other command
+available on the user's machine.
+
+## Install and link
+
+Install an example plugin:
+
+```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
+```
+
+When you are authoring a local plugin, link the working directory instead:
+
+```bash
+herdr plugin link /path/to/plugin
+herdr plugin config-dir example.layout
+herdr plugin action list --plugin example.layout
+herdr plugin action invoke example.layout.apply
+herdr plugin pane open --plugin example.layout --entrypoint board
+herdr plugin log list --plugin example.layout
+```
+
+`plugin install` accepts GitHub shorthand only, such as
+`owner/repo/subdir`. It clones with `git`, shows a preview in interactive
+terminals, runs supported build commands, then stores the checkout under
+Herdr-managed plugin data and registers it. Use `--yes` for noninteractive
+installs. Reinstalling a GitHub-managed plugin replaces that managed checkout.
+Installing over a locally linked plugin is refused; unlink or uninstall the
+local plugin first. `plugin install` and `plugin link` create the plugin's
+config and state directories, and `plugin config-dir <id>` prints the config
+directory for setup docs and shell scripts.
+
+`plugin uninstall <id-or-source>` unregisters the plugin. For GitHub-managed
+installs it also removes the managed checkout, and it accepts either the plugin
+id or the same `owner/repo[/subdir...]` shorthand used by install.
+`plugin unlink <id>` only unregisters a plugin and leaves files alone, which is
+useful for local development. There is no separate `plugin update` in v1;
+reinstall from GitHub to refresh a managed plugin.
+
+The example cookbook repo is `ogulcancelik/herdr-plugin-examples`. It contains
+separate example plugins in subdirectories, including `agent-telegram-notify`,
+`github-link-preview`, and `dev-layout-bootstrap`. These are examples to copy,
+not maintained official plugins.
+
+## Build commands
+
+Build commands run during GitHub `plugin install` after confirmation and before
+Herdr registers the plugin. If a build command fails, install aborts and the
+plugin is not registered. `plugin link` does not run build commands; local
+authors build their working tree themselves. Build commands may generate files,
+but changing `herdr-plugin.toml` after the install preview aborts install. Build
+failures show the plugin id, build index, working directory, command, exit
+status or spawn error, and capped stdout/stderr without interpreting tool output.
+
+Build commands are plain argv commands too, but they do not receive runtime
+plugin context or Herdr socket env. Plugin authors should document required
+system tools such as `cargo`, `npm`, `bun`, or `lua`; Herdr reports build
+failures but does not install missing toolchains.
+
+## Commands and environment
+
+Runtime commands run with the plugin directory as their working directory. Herdr
+injects `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`, and any available
+`HERDR_WORKSPACE_ID`, `HERDR_TAB_ID`, and `HERDR_PANE_ID`. Action commands also
+receive `HERDR_PLUGIN_ACTION_ID`; event hooks receive `HERDR_PLUGIN_EVENT` and
+`HERDR_PLUGIN_EVENT_JSON`; pane commands receive `HERDR_PLUGIN_ENTRYPOINT_ID`.
+
+`HERDR_PLUGIN_ROOT` is the installed or linked plugin directory. Do not store
+user credentials or durable state there, because GitHub-installed plugin roots
+are managed source checkouts. Put user-editable config such as `.env` files
+under `HERDR_PLUGIN_CONFIG_DIR`, and put local runtime state under
+`HERDR_PLUGIN_STATE_DIR`. Herdr creates those directories and seeds
+`HERDR_PLUGIN_CONFIG_DIR` from the legacy plugin config locations when present,
+but it does not validate, sync, or delete their contents. The plugin owns the
+file format and lifecycle.
+
+`HERDR_PLUGIN_CONTEXT_JSON` can include workspace, tab, focused pane, worktree,
+agent, selected text, clicked URL, and link handler fields when they are
+available for that invocation. Shell plugins can read the individual env vars
+for common ids, or parse the context JSON for the full shape.
+
+Use `HERDR_BIN_PATH` when a plugin needs to call Herdr portably from Node,
+PowerShell, Bash, or another runtime. The raw socket transport behind
+`HERDR_SOCKET_PATH` is OS-specific: Unix clients connect to a Unix socket path,
+while Windows clients connect to a named pipe. CLI calls through
+`HERDR_BIN_PATH` avoid that transport difference. See the
+[CLI reference](/docs/cli-reference/) for available commands and
+[socket API](/docs/socket-api/) for raw request shapes.
+
+## Panes
+
+Manifest pane `placement` defaults to `overlay`, which opens a temporary zoomed
+overlay over the active pane and restores the previous focus and zoom when it
+closes. A `plugin.pane.open` request can override the manifest placement with
+`overlay`, `split`, `tab`, or `zoomed`.
+
+Plugin panes are normal Herdr panes after they open. Plugins can call standard
+pane APIs such as `pane.move`, `pane.swap`, `pane.resize`, and `pane.zoom`
+through the socket or CLI; Herdr keeps plugin pane ownership attached to the
+underlying pane when it moves across tabs or workspaces.
+
+On Windows, build commands, action commands, and event commands resolve common
+`PATHEXT` shims such as `npm.cmd`, `bun.cmd`, and `pnpm.cmd` when the bare
+command is on `PATH`. Pane commands use Herdr's normal Windows pane launcher and
+must still be valid Windows argv commands.
+
+## Keybindings
+
+Bind a key to an installed plugin action:
+
+```toml
+[[keys.command]]
+key = "prefix+l"
+type = "plugin_action"
+command = "example.layout.apply"
+description = "apply layout"
+```
+
+## Link handlers
+
+Use `[[link_handlers]]` to route modified clicks on matching terminal URLs to a
+plugin action instead of opening the URL in the browser. The modified-click
+modifier is Control on every platform, including macOS, because captured
+terminal mouse reports do not expose Command/Super separately from a plain
+click. `pattern` is a Rust regular expression matched against the clicked URL,
+and `action` must
+name an action declared by the same plugin. Link handler actions receive
+`invocation_source = "link_click"`, `clicked_url`, and `link_handler_id` in
+`HERDR_PLUGIN_CONTEXT_JSON`; shell plugins can also read
+`HERDR_PLUGIN_CLICKED_URL` and `HERDR_PLUGIN_LINK_HANDLER_ID`. Handlers are
+checked in manifest order inside each plugin.
+
+## Storage
+
+There is no Herdr-managed plugin storage API in v1. Plugins that need durable
+state should own their files or database.
+
+## Marketplace
+
+A plugin marketplace is coming. Plugins are already shareable today: publish a
+GitHub repository with `herdr-plugin.toml`, then share
+`herdr plugin install owner/repo[/subdir]`.
+
+If you want the plugin to appear in the website marketplace when discovery
+launches, add the GitHub topic `herdr-plugin` to the repository now. See
+[Marketplace](/docs/marketplace/) for how publishing and discovery will work.
diff --git a/docs/versions/0.7.0/website/src/content/docs/quick-start.mdx b/docs/versions/0.7.0/website/src/content/docs/quick-start.mdx
new file mode 100644
index 00000000..a8f95e7c
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/quick-start.mdx
@@ -0,0 +1,69 @@
+---
+title: Quick start
+description: Create your first Herdr workspace and run agents in persistent terminal panes.
+---
+
+If Herdr is not installed yet, see [Install](/docs/install/). Then start Herdr from any project directory:
+
+```bash
+herdr
+```
+
+Herdr launches or attaches to your default background session. You do not manage sockets. If you detach, agents keep running.
+
+## Create a workspace
+
+When a session has no workspaces, Herdr opens one automatically. A workspace is a project-level container for tabs, panes, and agents. Give each active project its own workspace; this keeps agent state readable in the sidebar.
+
+## Use the mouse
+
+Herdr is mouse-native, so start by clicking. Click panes, tabs, workspaces, and agents to focus them. Drag split borders to resize. Right-click for context menus, including splitting panes and creating tabs. Drag-select text to copy it to your clipboard; double-click a token to copy it directly. Copying does not require Ctrl+C.
+
+Ctrl-click opens pane links when your terminal sends the modified click to Herdr. This works for OSC 8 hyperlinks and visible `http://` or `https://` URLs. On macOS, use Ctrl-click for Herdr-handled pane links while mouse capture is enabled; Cmd-click is only available through the terminal-native bypass path, such as Shift-Cmd-click or `ui.mouse_capture = false`.
+
+If you configure `ui.right_click_passthrough_modifier`, that modifier plus right-click sends right-click, hold, and drag gestures to mouse-reporting pane apps.
+
+## Run an agent
+
+Start your coding agent in a pane:
+
+```bash
+claude
+```
+
+Or `codex`, `pi`, `opencode`, or any other [supported agent](/docs/agents/). Herdr detects it automatically. The sidebar shows whether each agent is `working`, `blocked`, `done`, or `idle` — across every workspace, so you always know which project needs you.
+
+## Keyboard control
+
+Keyboard control is optional; the mouse covers everything. Press `ctrl+b` to enter prefix mode, then press an action key.
+
+Common actions:
+
+| 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` |
+
+New to the prefix idea? [Keyboard](/docs/keyboard/) explains what it is, why multiplexers use one, and how to go prefix-free. Press `prefix+?` inside Herdr to see every active binding, and `prefix+[` to copy from the keyboard in copy mode.
+
+## Detach and come back
+
+Press `prefix+q` or simply close your terminal window. The Herdr server and every agent keep running. Run `herdr` again to reattach to the same session.
+
+To actually end the session and stop its panes:
+
+```bash
+herdr server stop
+```
+
+## Where next
+
+- [Concepts](/docs/concepts/) — the workspace, tab, pane, and agent model in two minutes.
+- [How to work with Herdr](/docs/how-to-work/) — local, SSH, phone, and `herdr --remote` workflows.
+- [Agents](/docs/agents/) — supported agents, detection, and integrations that improve state accuracy.
+- [Configuration](/docs/configuration/) — keybindings, themes, notifications, and everything else.
diff --git a/docs/versions/0.7.0/website/src/content/docs/session-state.mdx b/docs/versions/0.7.0/website/src/content/docs/session-state.mdx
new file mode 100644
index 00000000..6ff70270
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/session-state.mdx
@@ -0,0 +1,105 @@
+---
+title: Session state and restore
+description: Understand what Herdr keeps live, restores after restart, replays from history, resumes through agent integrations, and hands off during updates.
+---
+
+Herdr has several state paths. They solve different problems.
+
+## What survives
+
+| Case | Processes keep running | Layout returns | Recent screen returns | Agent conversation resumes |
+| --- | --- | --- | --- | --- |
+| Detach and reattach | Yes | Yes | Yes, from the live terminal | Yes, because the process never stopped |
+| Server restart | No | Yes | Only with pane screen history | Only with native agent session restore |
+| Update without `--handoff` | Compatible servers keep running; restart-required servers may need stop/restart | Yes after restart | Only with pane screen history | Only with native agent session restore |
+| Update with `--handoff` | Best effort for supported running servers | Yes | Yes, from the live terminal if handoff succeeds | Yes, because the process keeps running if handoff succeeds |
+
+The sections below explain each path.
+
+## Live persistence
+
+Normal detach keeps the Herdr server running. Panes, shells, agents, servers, tests, and command processes keep running inside that server.
+
+Detach the client with `ctrl+b q`. Reattach later:
+
+```bash
+herdr
+```
+
+This is the strongest persistence path because the original processes never stop.
+
+## Snapshot restore
+
+If the Herdr server stops and starts again, the original pane processes are gone. Herdr restores the saved session shape: workspaces, tabs, panes, cwd, layout, and focus.
+
+Snapshot restore does not preserve running shells, servers, tests, or arbitrary processes. Panes that cannot use a stronger restore path come back as new shells in their saved directories.
+
+## Pane screen history replay
+
+Pane screen history restores recent terminal contents after a full server restart. It restores what Herdr can show, not the old process.
+
+This is off by default because pane output can include secrets, tokens, prompts, and command output. Enable it from Settings > Experiments > pane screen history or with:
+
+```toml
+[experimental]
+pane_history = true
+```
+
+When enabled, Herdr stores saved pane history in `session-history.json` next to `session.json`. Treat the Herdr config/session directory like terminal history.
+
+## Native agent session restore
+
+Some agents can resume their own conversation sessions. Herdr can use official integration-reported session references to restart supported agent panes after a Herdr server restart.
+
+This is enabled by default. Disable it with:
+
+```toml
+[session]
+resume_agents_on_restore = false
+```
+
+Herdr only resumes panes that reported a native session reference through a current official Herdr integration.
+
+After a client attaches and provides terminal size and theme context, Herdr resumes eligible restored agent panes across workspaces and tabs without waiting for each pane to be focused.
+
+Native session restore requires these Herdr integration versions or newer:
+
+| Agent | Minimum Herdr integration version | Resume command |
+| --- | --- | --- |
+| Pi | `2` | `pi --session <path-or-id>` |
+| Claude Code | `6` | `claude --resume <id>` |
+| Codex | `5` | `codex resume <id>` |
+| Cursor Agent CLI | `1` | `cursor-agent --resume <id>` |
+| GitHub Copilot CLI | `2` | `copilot --resume=<id>` |
+| Devin CLI | `1` | `devin --resume <id>` |
+| Droid | `2` | `droid --resume <id>` |
+| Kimi Code CLI | `3` | `kimi --session <id>` |
+| Qoder CLI | `2` | `qodercli --resume <id>` |
+| OpenCode | `5` | `opencode --session <id>` |
+| Kilo Code CLI | `1` | `kilo --session <id>` |
+| Hermes Agent | `2` | `hermes --resume <id>` |
+
+OMP integration version `2` reports agent state, but does not report native session references for restore.
+
+Run `herdr integration status` to check installed integration versions. Reinstall outdated integrations with `herdr integration install <agent>`.
+
+Unsupported, missing, invalid, duplicated, or stale session references restore as normal shells in the saved pane directory.
+
+If native agent session restore applies to a pane, Herdr resumes the agent session instead of replaying saved pane history for that pane.
+
+## Live handoff
+
+Live handoff is for update and remote attach flows that need to replace a running Herdr server. It asks the old server to transfer live panes to the new server, so pane processes can keep running across the server replacement.
+
+This is different from snapshot restore, pane history replay, and native agent session restore. Handoff tries to keep the current processes alive. The others reconstruct state after the old server has already stopped.
+
+Live handoff is experimental and opt-in:
+
+```bash
+herdr update --handoff
+herdr --remote workbox --handoff
+```
+
+Plain `herdr update` and plain `herdr --remote workbox` use the normal restart/stop flow by default.
+
+`herdr update --handoff` only applies to installs managed by Herdr's own updater. Homebrew, mise, and Nix installs are updated through their package managers, so `herdr update` is disabled there and cannot perform live handoff.
diff --git a/docs/versions/0.7.0/website/src/content/docs/socket-api.mdx b/docs/versions/0.7.0/website/src/content/docs/socket-api.mdx
new file mode 100644
index 00000000..74697fd8
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/socket-api.mdx
@@ -0,0 +1,702 @@
+---
+title: Socket API
+description: Control a running Herdr server from scripts, tools, and coding agents.
+---
+
+Herdr exposes a local socket API for scripts and agents that need to inspect or control a running session.
+
+Most automation should start with the CLI wrappers. Use the raw socket API only when you need direct request/response control or long-lived event subscriptions.
+
+## Choose an integration layer
+
+| Layer | Use it for |
+| --- | --- |
+| Agent skill | Teaching a coding agent how to use Herdr from inside a pane. |
+| CLI wrappers | Shell scripts, simple orchestration, and human debugging. |
+| Raw socket API | Custom tools, protocol clients, and event subscribers. |
+
+The layers share the same control surface.
+
+## What you can control
+
+The socket API can:
+
+- create, list, focus, rename, and close workspaces
+- create, list, focus, rename, and close tabs
+- list, inspect, split, swap, focus, resize, rename, read, close, and send input to panes
+- list, inspect, read, send to, rename, focus, start, and attach agents through CLI helpers
+- report custom agent state from hooks and plugins
+- subscribe to events and wait for output or state changes
+- install and uninstall built-in integrations
+- stop the server and reload config
+
+## CLI examples
+
+Create a workspace:
+
+```bash
+herdr workspace create --cwd ~/project --label api
+```
+
+Create a tab:
+
+```bash
+herdr tab create --label logs
+```
+
+Split a pane and run a command:
+
+```bash
+herdr pane split w1:p1 --direction right
+herdr pane run w1:p2 "npm test"
+```
+
+Inspect and rearrange panes:
+
+```bash
+herdr pane layout --current
+herdr pane neighbor --direction right --current
+herdr pane resize --direction right --amount 0.1 --current
+herdr pane swap --direction right --current
+herdr pane zoom --on --current
+herdr pane split w1:p1 --direction right --ratio 0.333
+```
+
+Wait for an agent:
+
+```bash
+herdr wait agent-status w1:p1 --status done
+```
+
+Read pane output:
+
+```bash
+herdr pane read w1:p2 --source recent --lines 50
+```
+
+## Raw methods
+
+Raw socket method names use dot notation:
+
+| Area | Methods |
+| --- | --- |
+| Server | `ping`, `server.stop`, `server.reload_config`, `server.agent_manifests`, `server.reload_agent_manifests` |
+| Notification | `notification.show` |
+| Client | `client.window_title.set`, `client.window_title.clear` |
+| Workspace | `workspace.create`, `workspace.list`, `workspace.get`, `workspace.focus`, `workspace.rename`, `workspace.close` |
+| Worktree | `worktree.list`, `worktree.create`, `worktree.open`, `worktree.remove` |
+| Tab | `tab.create`, `tab.list`, `tab.get`, `tab.focus`, `tab.rename`, `tab.close` |
+| Pane | `pane.split`, `pane.swap`, `pane.move`, `pane.zoom`, `pane.layout`, `pane.process_info`, `pane.neighbor`, `pane.edges`, `pane.focus_direction`, `pane.resize`, `pane.list`, `pane.current`, `pane.get`, `pane.rename`, `pane.send_text`, `pane.send_keys`, `pane.send_input`, `pane.read`, `pane.report_agent`, `pane.report_agent_session`, `pane.report_metadata`, `pane.clear_agent_authority`, `pane.release_agent`, `pane.close`, `pane.wait_for_output` |
+| Layout | `layout.export`, `layout.apply` |
+| Agent | `agent.list`, `agent.get`, `agent.read`, `agent.explain`, `agent.send`, `agent.rename`, `agent.focus`, `agent.start` |
+| Events | `events.subscribe`, `events.wait` |
+| Integrations | `integration.install`, `integration.uninstall` |
+| Plugins | `plugin.link`, `plugin.list`, `plugin.unlink`, `plugin.enable`, `plugin.disable`, `plugin.action.list`, `plugin.action.invoke`, `plugin.log.list`, `plugin.pane.open`, `plugin.pane.focus`, `plugin.pane.close` |
+
+Some CLI commands are conveniences around these methods. For example, `herdr agent wait` resolves an agent target and then subscribes to pane agent state events.
+
+Pane control methods use public pane ids such as `w1:p1`. Methods whose
+schema makes `pane_id` optional use the server's active focused pane when it is
+omitted. `pane.move` always requires the source `pane_id`.
+
+`pane.send_keys` and `pane.send_input.keys` accept Herdr key-combo strings:
+plain printable keys, special keys like `enter` and `esc`, modifier chords
+like `ctrl+h`, `control+j`, `alt+x`, and `shift+tab`, function keys like
+`f1`, and named punctuation like `minus` and `plus`. They do not accept
+`prefix+` binding strings.
+
+```json
+{"id":"req_current","method":"pane.current","params":{"caller_pane_id":"w1:p1"}}
+{"id":"req_layout","method":"pane.layout","params":{"pane_id":"w1:p1"}}
+{"id":"req_neighbor","method":"pane.neighbor","params":{"pane_id":"w1:p1","direction":"right"}}
+{"id":"req_edges","method":"pane.edges","params":{"pane_id":"w1:p1"}}
+{"id":"req_focus","method":"pane.focus_direction","params":{"direction":"right"}}
+{"id":"req_resize","method":"pane.resize","params":{"pane_id":"w1:p1","direction":"right","amount":0.1}}
+{"id":"req_zoom","method":"pane.zoom","params":{"pane_id":"w1:p1","mode":"toggle"}}
+{"id":"req_split","method":"pane.split","params":{"direction":"right","ratio":0.333,"env":{"HERDR_ROLE":"tests"}}}
+{"id":"req_process","method":"pane.process_info","params":{"pane_id":"w1:p1"}}
+```
+
+`pane.current` returns a single `PaneInfo`. When `caller_pane_id` is present,
+Herdr returns that pane. When it is omitted, Herdr returns the active focused
+pane.
+
+`pane.layout` returns the tab layout snapshot with `workspace_id`, `tab_id`,
+`zoomed`, outer `area`, `focused_pane_id`, pane rects, and split rects/ratios.
+`pane.neighbor` and `pane.edges` include that same layout snapshot so clients
+can make the next decision without private layout state.
+
+`pane.process_info` returns the pane's shell pid, foreground process group id
+when available, and foreground processes with pid, name, argv/cmdline, and cwd
+when the platform exposes them.
+
+`layout.export` returns a portable tab layout tree. Omit `tab_id` and `pane_id`
+to export the active tab, pass `tab_id` to export that tab, or pass `pane_id` to
+export the tab containing that pane.
+
+```json
+{"id":"req_export","method":"layout.export","params":{"tab_id":"w1:t1"}}
+```
+
+The response includes `workspace_id`, `tab_id`, `zoomed`, `focused_pane_id`, and
+`root`. `root` is a BSP tree of `pane` and `split` nodes. Pane nodes can include
+`pane_id`, `label`, `cwd`, and argv `command`. Split nodes use
+`direction` (`right` or `down`), `ratio`, `first`, and `second`.
+
+`layout.apply` creates a fresh tab from a declarative tree. If `tab_id` is
+provided, Herdr creates the replacement tab first and then closes the old tab.
+This restores structure, labels, cwd, env, and optional argv commands; it does
+not preserve live PTYs, scrollback, or running processes.
+
+```json
+{
+ "id": "req_apply",
+ "method": "layout.apply",
+ "params": {
+ "workspace_id": "wabc",
+ "tab_label": "dev",
+ "focus": true,
+ "root": {
+ "type": "split",
+ "direction": "right",
+ "ratio": 0.65,
+ "first": {
+ "type": "pane",
+ "label": "editor",
+ "cwd": "/repo"
+ },
+ "second": {
+ "type": "pane",
+ "label": "tests",
+ "cwd": "/repo",
+ "command": ["sh", "-c", "just test"],
+ "env": { "HERDR_ROLE": "tests" }
+ }
+ }
+ }
+}
+```
+
+Process-launching methods accept an `env` object. Herdr applies those key/value
+pairs to the newly launched process only. Herdr also injects `HERDR_SOCKET_PATH`,
+`HERDR_ENV=1`, `HERDR_WORKSPACE_ID`, `HERDR_TAB_ID`, and `HERDR_PANE_ID` into
+managed pane processes. Herdr-managed variables are authoritative when they
+conflict with caller-provided env.
+
+`pane.swap` supports directional and explicit forms:
+
+```json
+{"id":"req_swap_dir","method":"pane.swap","params":{"pane_id":"w1:p1","direction":"right"}}
+{"id":"req_swap_explicit","method":"pane.swap","params":{"source_pane_id":"w1:p1","target_pane_id":"w1:p2"}}
+```
+
+Swap is same-tab only. It preserves split shape, split ratios, pane ids, and
+running processes. The response is `type: "pane_swap"` with `changed`, optional
+`reason`, `source_pane_id`, optional `target_pane_id`, `focused_pane_id`, and
+`layout`. Reason values are `no_neighbor`, `same_pane`, `not_found`, and
+`cross_tab`. When a tab is zoomed, swap keeps zoom active and mutates the hidden
+full-tab layout.
+
+`pane.move` moves a running pane to a different tab, a new tab, or a new
+workspace:
+
+```json
+{"id":"req_move_tab","method":"pane.move","params":{"pane_id":"w1:p2","destination":{"type":"tab","tab_id":"w1:t2","target_pane_id":"w1:p3","split":"right","ratio":0.5},"focus":true}}
+{"id":"req_move_new_tab","method":"pane.move","params":{"pane_id":"w1:p2","destination":{"type":"new_tab","workspace_id":"w1","label":"logs"},"focus":true}}
+{"id":"req_move_new_workspace","method":"pane.move","params":{"pane_id":"w1:p2","destination":{"type":"new_workspace","label":"logs","tab_label":"main"},"focus":true}}
+```
+
+Existing-tab moves require `split: "right" | "down"`. `target_pane_id` is
+optional and defaults to the target tab's focused pane. Same-tab layout changes
+remain `pane.swap`; moving to the source tab returns `changed: false` with
+`reason: "same_tab"`. Moves involving a zoomed source or target tab return
+`changed: false` with `reason: "zoomed_tab"`.
+
+The response is `type: "pane_move"` with `changed`, optional `reason`,
+`previous_pane_id`, `previous_workspace_id`, `previous_tab_id`, the moved
+`pane`, optional `source_layout`, `target_layout`, optional created workspace or
+tab records, optional closed workspace or tab ids, and `focused_pane_id`.
+Cross-workspace moves keep the internal pane and terminal alive but assign a new
+public pane id in the destination workspace. Subscribers can listen for
+`pane.moved`; Herdr does not emit fake pane close/create events for the moved
+terminal process.
+
+`pane.zoom` toggles, enables, or disables zoom for the target pane's tab:
+
+```json
+{"id":"req_zoom_toggle","method":"pane.zoom","params":{"pane_id":"w1:p1"}}
+{"id":"req_zoom_on","method":"pane.zoom","params":{"pane_id":"w1:p1","mode":"on"}}
+{"id":"req_zoom_off","method":"pane.zoom","params":{"pane_id":"w1:p1","mode":"off"}}
+```
+
+Omitting `pane_id` targets the server's active focused pane. The response is
+`type: "pane_zoom"` with `changed`, `zoom_changed`, `focus_changed`, optional
+`reason`, `pane_id`, `focused_pane_id`, `zoomed`, and `layout`. `changed` is
+true when either zoom state or focus changed. Reason values are `single_pane`,
+`already_zoomed`, and `already_unzoomed`.
+
+The CLI wrapper for `notification.show` is:
+
+```bash
+herdr notification show "build failed" --body "api workspace" --position top-left --sound request
+```
+
+Show a user notification through the configured toast delivery:
+
+```json
+{"id":"req_notify","method":"notification.show","params":{"title":"build failed","body":"api workspace","position":"top-left","sound":"request"}}
+```
+
+`title` is required and must contain visible text after control characters and repeated whitespace are removed. `body` is optional. Herdr collapses newlines, tabs, carriage returns, and repeated whitespace into spaces, then trims notification text to 80 characters for `title` and 240 characters for `body`. An empty sanitized `title` returns `invalid_params`. `position` is optional and applies only when `ui.toast.delivery = "herdr"`; desktop positions are relative to the full Herdr frame, and omitted positions use `ui.toast.herdr.position`. Terminal, system, and off delivery ignore `position`. `sound` is optional and can be `none`, `done`, or `request`; it defaults to `none` and plays only when the notification is shown.
+
+The response reports whether anything was shown:
+
+```json
+{"id":"req_notify","result":{"type":"notification_show","shown":true,"reason":"shown"}}
+```
+
+Possible reasons are `shown`, `disabled`, `rate_limited`, `no_foreground_client`, and `busy`. `disabled` means `ui.toast.delivery = "off"`. `busy` means an existing in-app toast was not replaced. Terminal and system delivery are best-effort through the current foreground attached Herdr client.
+
+Set or clear the foreground client's outer terminal window title:
+
+```json
+{"id":"req_title","method":"client.window_title.set","params":{"title":"herdr api"}}
+{"id":"req_title_clear","method":"client.window_title.clear","params":{}}
+```
+
+`client.window_title.clear` restores Herdr's default title. The response is
+`type: "client_window_title"` with `changed` and reason `set`, `cleared`, or
+`no_foreground_client`.
+
+Worktree methods manage Git checkouts as Herdr workspaces. `worktree.create` creates a checkout and returns the new `workspace`, `tab`, `root_pane`, and `worktree` records. `worktree.open` opens an existing checkout or returns the already-open workspace. `worktree.remove` runs `git worktree remove` against a linked child workspace and never deletes the branch.
+
+Create a worktree from a source workspace:
+
+```json
+{"id":"req_1","method":"worktree.create","params":{"workspace_id":"w1","branch":"worktree/api","focus":false}}
+```
+
+Open an existing checkout:
+
+```json
+{"id":"req_2","method":"worktree.open","params":{"workspace_id":"w1","branch":"worktree/api","focus":true}}
+```
+
+Remove a linked checkout:
+
+```json
+{"id":"req_3","method":"worktree.remove","params":{"workspace_id":"2","force":false}}
+```
+
+Use at most one of `workspace_id` or `cwd` for `worktree.list`, `worktree.create`, and `worktree.open`; omit both to use the active workspace. Use exactly one of `path` or `branch` for `worktree.open`. Raw socket `cwd` and `path` values must be absolute; the CLI expands relative `--cwd` and `--path` values before sending requests. Workspace responses include optional `worktree` provenance when a workspace belongs to a Herdr worktree group. Worktree commands can emit `workspace.updated` when an existing workspace gains or changes worktree provenance.
+
+Worktree commands also emit lifecycle events. `worktree.create` emits `workspace.created`, `tab.created`, `pane.created`, and `worktree.created`. `worktree.open` emits `worktree.opened`, and it also emits workspace/tab/pane creation events when it opens a new Herdr workspace. `worktree.remove` emits `worktree.removed`; if the linked workspace is still open, it also emits `workspace.closed`.
+
+## Plugin APIs
+
+The plugin API is an early host surface for executable workflow tools. A plugin
+is a package with a `herdr-plugin.toml` manifest. The manifest declares
+shareable actions, event hooks, terminal pane entrypoints, and link handlers.
+Actions and panes are manifest-only; runtime action registration and runtime
+argv pane creation are not part of v1.
+
+Installed and linked plugins persist across restarts. Herdr writes a
+`plugins.json` registry file alongside `session.json` on `plugin.link`,
+`plugin.unlink`, `plugin.enable`, and `plugin.disable`. The
+`herdr plugin install` CLI also writes the same registry when Herdr is not
+running, then startup loads it automatically. On startup, Herdr re-reads each
+manifest from its original path; if the file is missing or unparseable the entry
+is kept with a `warnings` field so `plugin.list` surfaces it.
+
+Event hook `on` values are validated against the known Herdr event names at link time. An unrecognised name is not an error — the link still succeeds — but the returned plugin info includes a warning (e.g. `"unknown event 'worktree.craeted'"`). Check the `warnings` field in the `plugin.link` and `plugin.list` responses.
+
+Link a local plugin manifest:
+
+```json
+{"id":"req_plugin_link","method":"plugin.link","params":{"path":"/path/to/plugin","enabled":true}}
+```
+
+`plugin.link` also accepts optional `source` metadata. The CLI uses this when it installs from GitHub so `plugin.list` can show origin, requested ref, resolved commit, and managed checkout path:
+
+```json
+{"id":"req_plugin_link","method":"plugin.link","params":{"path":"/managed/plugin/herdr-plugin.toml","enabled":true,"source":{"kind":"github","owner":"ogulcancelik","repo":"herdr-plugin-examples","subdir":"worktree-bootstrap","requested_ref":"main","resolved_commit":"abc123","managed_path":"/data/plugins/github/<managed-checkout>","installed_unix_ms":1780000000000}}}
+```
+
+The path can be a plugin directory containing `herdr-plugin.toml` or a direct
+manifest path. The manifest shape is:
+
+```toml
+id = "example.worktree-bootstrap"
+name = "Worktree Bootstrap"
+version = "0.1.0"
+min_herdr_version = "0.7.0"
+description = "Prepare new worktrees"
+platforms = ["linux", "macos", "windows"]
+
+[[build]]
+command = ["bun", "install"]
+
+[[actions]]
+id = "bootstrap"
+title = "Bootstrap worktree"
+contexts = ["workspace"]
+command = ["bun", "run", "bootstrap.ts"]
+
+[[events]]
+on = "worktree.created"
+command = ["bun", "run", "bootstrap.ts"]
+
+[[panes]]
+id = "board"
+title = "Worktree board"
+placement = "overlay"
+command = ["bun", "run", "board.ts"]
+
+[[link_handlers]]
+id = "github-issue"
+title = "Open GitHub issue"
+pattern = "^https://github\\.com/[^/]+/[^/]+/(issues|pull)/[0-9]+$"
+action = "bootstrap"
+```
+
+`min_herdr_version` is required. The server refuses to link a plugin when the
+field is missing, invalid, or newer than the running Herdr binary.
+
+Declare `platforms` at the top level with the OS identifiers (`linux`, `macos`,
+`windows`) your plugin supports. Omitting `platforms` is allowed for local
+development — `plugin.link` succeeds but the response includes a warning.
+Individual build commands, actions, event hooks, panes, and link handlers can
+declare their own `platforms` to override the plugin-level list; if omitted they
+inherit from the plugin. Invoking an action or opening a pane whose effective
+platforms do not include the current OS returns a `platform_unsupported` error.
+
+List, enable, disable, or unlink linked plugins:
+
+```json
+{"id":"req_plugin_list","method":"plugin.list","params":{}}
+{"id":"req_plugin_disable","method":"plugin.disable","params":{"plugin_id":"example.worktree-bootstrap"}}
+{"id":"req_plugin_enable","method":"plugin.enable","params":{"plugin_id":"example.worktree-bootstrap"}}
+{"id":"req_plugin_unlink","method":"plugin.unlink","params":{"plugin_id":"example.worktree-bootstrap"}}
+```
+
+Actions are resolved from the linked manifest. `plugin.action.list` returns all actions across installed plugins; pass `plugin_id` to filter.
+
+```json
+{"id":"req_plugin_actions","method":"plugin.action.list","params":{}}
+{"id":"req_plugin_actions_filtered","method":"plugin.action.list","params":{"plugin_id":"example.worktree-bootstrap"}}
+```
+
+`plugin.action.list` returns each action's effective `platforms` after applying
+plugin-level inheritance.
+
+Invoke an action by its qualified id or bare action id:
+
+```json
+{"id":"req_plugin_invoke","method":"plugin.action.invoke","params":{"action_id":"example.worktree-bootstrap.bootstrap","context":{"invocation_source":"keybinding"}}}
+```
+
+`plugin.action.invoke` resolves the manifest action, starts the manifest
+command, and returns the Herdr-built invocation context plus the started command
+log record. Missing context fields are filled from the active workspace, tab,
+focused pane, worktree provenance, and request id. Invoking an action from a
+disabled plugin returns a `plugin_disabled` error.
+
+Herdr injects `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`, and available
+`HERDR_WORKSPACE_ID`, `HERDR_TAB_ID`, and `HERDR_PANE_ID` values. Action
+commands also receive `HERDR_PLUGIN_ACTION_ID`; event hooks receive
+`HERDR_PLUGIN_EVENT` and `HERDR_PLUGIN_EVENT_JSON`; pane commands receive
+`HERDR_PLUGIN_ENTRYPOINT_ID`.
+
+List recent action and event command logs:
+
+```json
+{"id":"req_plugin_logs","method":"plugin.log.list","params":{"plugin_id":"example.worktree-bootstrap","limit":20}}
+```
+
+Event hooks run for enabled installed plugins when Herdr emits a matching event
+name such as `worktree.created`.
+
+There is no Herdr-managed plugin storage API in v1. `HERDR_PLUGIN_CONFIG_DIR`
+and `HERDR_PLUGIN_STATE_DIR` are path discovery only; plugins own their files,
+schemas, migrations, and cleanup.
+
+Open a managed terminal UI:
+
+```json
+{"id":"req_plugin_pane","method":"plugin.pane.open","params":{"plugin_id":"example.board","entrypoint":"board","placement":"zoomed","target_pane_id":"w1:p1","env":{"HERDR_ROLE":"board"},"focus":true}}
+```
+
+`plugin.pane.open` requires an installed, enabled, platform-compatible plugin,
+then launches the requested manifest `[[panes]]` entrypoint as an argv-backed
+terminal pane. Manifest pane `placement` defaults to `overlay`; request
+`placement` overrides the manifest with `overlay`, `split`, `tab`, or `zoomed`.
+Overlay panes target the active pane. Split and zoomed panes target an existing
+pane; tab panes can target a workspace. The pane
+behaves like a normal Herdr pane, but `plugin.pane.focus` and
+`plugin.pane.close` only operate on panes opened through the plugin API. Focus
+returns `plugin_pane_focused`; close returns `plugin_pane_closed`.
+
+## Socket transport
+
+Herdr uses newline-delimited JSON over a local socket. On Unix, that socket is a
+Unix domain socket. On Windows, it is a named pipe.
+
+Send one request per line:
+
+```json
+{"id":"req_1","method":"ping","params":{}}
+```
+
+A successful response includes the same `id`:
+
+```json
+{"id":"req_1","result":{"type":"pong"}}
+```
+
+Event subscriptions keep the connection open after the initial response.
+
+## Socket paths
+
+The default socket lives under your Herdr config directory.
+
+Named sessions have separate sockets:
+
+```text
+~/.config/herdr/herdr.sock
+~/.config/herdr/sessions/<name>/herdr.sock
+```
+
+Resolution order:
+
+1. explicit CLI `--session <name>`
+2. `HERDR_SOCKET_PATH`
+3. `HERDR_SESSION=<name>`
+4. default session socket
+
+Use `HERDR_SOCKET_PATH` only for low-level overrides.
+
+For plugins, prefer invoking `HERDR_BIN_PATH` and the CLI wrappers when you need
+portable Windows behavior. Raw socket clients are responsible for using the
+platform-native local socket form.
+
+## Agent state reporting
+
+Integrations report agent state with `pane.report_agent`.
+
+```json
+{
+ "id": "req_1",
+ "method": "pane.report_agent",
+ "params": {
+ "pane_id": "w1:p1",
+ "source": "custom:docs",
+ "agent": "docs-bot",
+ "state": "working",
+ "message": "building docs",
+ "custom_status": "indexing"
+ }
+}
+```
+
+`state` is semantic. It affects waits, notifications, and rollups.
+
+`custom_status` is visual. It can show a short activity label like `indexing` without changing semantic behavior.
+
+Session-only official integrations report native session references with `pane.report_agent_session`. State-reporting integrations can still include native session references in `pane.report_agent`. State-independent session reports do not affect waits, notifications, or rollups.
+
+```json
+{
+ "id": "req_2",
+ "method": "pane.report_agent_session",
+ "params": {
+ "pane_id": "w1:p1",
+ "source": "herdr:codex",
+ "agent": "codex",
+ "agent_session_id": "..."
+ }
+}
+```
+
+`pane.get`, `pane.list`, `agent.get`, and `agent.list` expose a read-only `agent_session` object when Herdr has a stored native session reference:
+
+```json
+{
+ "agent_session": {
+ "source": "herdr:codex",
+ "agent": "codex",
+ "kind": "id",
+ "value": "..."
+ }
+}
+```
+
+If no native session reference is stored, the field is omitted.
+
+`pane.get`, `pane.list`, `agent.get`, and `agent.list` also expose `foreground_cwd` when Herdr can resolve the cwd of the process currently controlling the pane PTY. The existing `cwd` field remains the pane/workspace cwd used for labels, follow-cwd behavior, and restored session state.
+
+Use `pane.report_metadata` when a user hook wants to customize presentation without taking over lifecycle state from a Herdr integration.
+
+```json
+{
+ "id": "req_2",
+ "method": "pane.report_metadata",
+ "params": {
+ "pane_id": "w1:p1",
+ "source": "user:claude-title",
+ "agent": "claude",
+ "title": "Refactor auth middleware",
+ "display_agent": "Claude: auth",
+ "custom_status": "refactor auth",
+ "state_labels": {
+ "working": "refactoring auth",
+ "idle": "ready",
+ "done": "review ready"
+ },
+ "ttl_ms": 3600000
+ }
+}
+```
+
+Metadata reports are display-only. Valid metadata can override the pane title, displayed agent name, compact activity label, and visible state labels. `working`, `blocked`, `idle`, waits, notifications, and rollups still come from semantic state. Native session restore comes from stored official session references. `agent` is an optional guard for the authoritative agent label; `applies_to_source` is an optional guard for the active lifecycle authority source. Use `display_agent` to change the visible name. `state_labels` keys must be `idle`, `working`, `blocked`, `done`, or `unknown`. Use clear fields such as `clear_custom_status: true` with the same `source` to remove one presentation override.
+
+Presentation text is normalized before storage. Herdr trims surrounding whitespace, removes control characters, caps `custom_status` at 32 characters, and caps `title`, `display_agent`, and each state label at 80 characters. Empty normalized values are ignored.
+
+`source` and `applies_to_source` are source identifiers. They must be 80 characters or fewer and may contain only ASCII letters, digits, colon, dot, underscore, and hyphen.
+
+Use `ttl_ms` for short-lived metadata. It must be between `1` and `86400000` milliseconds. Omit `ttl_ms` for metadata that should stay until replaced, cleared, or the pane closes. When the TTL expires, Herdr removes that source's metadata and emits a presentation change if the visible pane presentation changed.
+
+Use `seq` when a hook may send updates out of order. For the same `source`, reports with a sequence number less than or equal to the last accepted sequence are accepted by the API but ignored by the pane state.
+
+## Event subscriptions
+
+Subscribe to events when you need a long-lived stream:
+
+```json
+{
+ "id": "sub_1",
+ "method": "events.subscribe",
+ "params": {
+ "subscriptions": [
+ { "type": "pane.agent_status_changed", "pane_id": "w1:p1", "agent_status": "blocked" }
+ ]
+ }
+}
+```
+
+The first response acknowledges the subscription. Later lines are pushed events.
+
+Workspace event subscriptions include `workspace.created`, `workspace.updated`, `workspace.renamed`, `workspace.closed`, and `workspace.focused`. Workspace events describe Herdr UI/runtime lifecycle. `workspace.created` includes optional `workspace.worktree` provenance when the workspace belongs to a worktree group. `workspace.closed` includes a final `workspace` snapshot when Herdr can still identify it before removal.
+Pane event subscriptions include `pane.created`, `pane.closed`, `pane.focused`,
+`pane.moved`, `pane.exited`, `pane.agent_detected`,
+`pane.output_matched`, and `pane.agent_status_changed`.
+
+Worktree event subscriptions include `worktree.created`, `worktree.opened`, and `worktree.removed`. Worktree events describe Git checkout lifecycle. `worktree.created` includes the opened `workspace` and created `worktree`. `worktree.opened` includes the target `workspace`, opened `worktree`, and `already_open`. `worktree.removed` includes the `workspace_id`, removed `worktree`, and `forced`.
+
+Use `events.subscribe` for lifecycle events. Dedicated wait helpers are documented separately when a one-shot wait is supported.
+
+## Reading panes
+
+Use `pane.read` through the CLI unless you are writing a protocol client.
+
+```bash
+herdr pane read w1:p1 --source visible --lines 80
+herdr pane read w1:p1 --source recent --lines 120
+herdr pane read w1:p1 --source recent-unwrapped --lines 120
+herdr pane read w1:p1 --source detection
+```
+
+`recent-unwrapped` is useful for logs because it ignores soft wrapping.
+`detection` returns the bottom-buffer snapshot used by agent screen detection.
+
+## Waiting for state
+
+Use waits to coordinate agents and scripts.
+
+```bash
+herdr wait agent-status w1:p1 --status done
+herdr wait agent-status w1:p1 --status blocked
+```
+
+Agent waits observe semantic state, not arbitrary command completion.
+
+## Response shapes
+
+Successful responses look like this:
+
+```json
+{
+ "id": "req_1",
+ "result": {
+ "type": "pane_info",
+ "pane": {
+ "pane_id": "w1:p1",
+ "terminal_id": "term_abc123",
+ "workspace_id": "w1",
+ "tab_id": "w1:t1",
+ "focused": true,
+ "agent_status": "working",
+ "revision": 42
+ }
+ }
+}
+```
+
+`server.agent_manifests` returns the active agent detection manifest sources and remote update diagnostics without reloading rules:
+
+```json
+{
+ "id": "req_1",
+ "result": {
+ "type": "agent_manifest_status",
+ "last_check_unix": 1781043522,
+ "last_result": "checked",
+ "manifests": [
+ {
+ "agent": "cursor",
+ "source": "/home/me/.config/herdr/agent-detection/cursor.toml",
+ "source_kind": "local override",
+ "active_version": "2026.06.10.1",
+ "cached_remote_version": "2026.06.10.1",
+ "local_override_shadowing_remote": true,
+ "remote_update_result": "current"
+ }
+ ]
+ }
+}
+```
+
+Fields such as `last_check_unix`, `last_result`, `active_version`, `cached_remote_version`, `remote_update_result`, `remote_update_error`, `remote_last_checked_unix`, and `warning` are omitted when not available. `server.reload_agent_manifests` returns `agent_manifest_reload` with the same `manifests` item shape after reloading the in-memory rule cache.
+
+`agent.explain` evaluates the target pane's detection snapshot in the running server using the server's active manifest cache:
+
+```json
+{
+ "id": "req_2",
+ "method": "agent.explain",
+ "params": { "target": "w1:p1" }
+}
+```
+
+The response contains the same explain object printed by `herdr agent explain --json`, including the final state, manifest source and version, matched rule, evaluated rule evidence, skip-state reason, idle fallback reason, and `screen_detection_skip_reason` when a full lifecycle hook authority makes screen rules non-authoritative.
+
+Clients need a running server that supports `agent.explain`; after upgrading Herdr, restart or live-handoff the server before relying on this method.
+
+Errors look like this:
+
+```json
+{
+ "id": "req_1",
+ "error": {
+ "code": "not_found",
+ "message": "pane not found"
+ }
+}
+```
+
+## Protocol stability
+
+Herdr has a protocol version for client/server compatibility. Protocol changes are reviewed with release compatibility in mind.
+
+Check the server protocol with `ping` or `herdr status` before depending on new behavior. Handle unknown fields gracefully.
diff --git a/docs/versions/0.7.0/website/src/content/docs/windows-beta.mdx b/docs/versions/0.7.0/website/src/content/docs/windows-beta.mdx
new file mode 100644
index 00000000..d64353c3
--- /dev/null
+++ b/docs/versions/0.7.0/website/src/content/docs/windows-beta.mdx
@@ -0,0 +1,100 @@
+---
+title: Windows beta
+description: Native Windows support status, supported workflows, and known limitations.
+---
+
+Native Windows support is experimental beta.
+
+Herdr on Windows uses ConPTY and Windows process/runtime behavior instead of the Unix PTY model Herdr was originally built around. Some Herdr features map cleanly to Windows, and some do not. This preview is not a commitment that every Linux/macOS feature will become fully supported on Windows.
+
+The goal of the beta is to learn from real use: install success, pane reliability, agent workflows, bug volume, missing features, and whether Windows users are getting enough value from Herdr. Based on that feedback, Windows support may graduate to stable, stay preview-only while it matures, or be reduced if the maintenance cost is not justified.
+
+Install native Windows beta builds with PowerShell:
+
+```powershell
+powershell -ExecutionPolicy Bypass -c "irm https://herdr.dev/install.ps1 | iex"
+```
+
+Windows beta builds ship only through the preview channel. The Windows installer defaults to preview, writes `channel = "preview"` to Herdr's config, stores releases under `%USERPROFILE%\.herdr\packages\standalone\releases`, points `%LOCALAPPDATA%\Programs\Herdr\bin` at the current release, and keeps a small number of older releases so running processes do not block updates.
+
+For internal beta testing, `HERDR_MANIFEST_URL` can point the installer at a custom manifest instead of Herdr's stable or preview manifest.
+
+## Supported in beta
+
+| Capability | Status |
+| --- | --- |
+| Local persistent sessions | beta |
+| Native panes through ConPTY | beta |
+| Windows Terminal / PowerShell app attach | beta |
+| `cmd.exe` panes | beta |
+| Startup cwd and workspace labels | beta |
+| Pane launch cwd | beta |
+| Agent command discovery | beta |
+| Agent self-report integrations | beta |
+| Agent process-tree detection | beta |
+| Git/worktree detection from known cwd | beta |
+| Plugins | preview |
+| Pane screen history | beta |
+| Nested launch override | beta |
+
+Windows agent process detection scans descendants of the pane shell and recognizes direct agents plus common command wrappers. It is useful for Codex, Claude, and similar agents, but it is not the same as Unix foreground process-group detection.
+
+Plugins support `windows` as a manifest platform in preview. GitHub install, local link, build commands, actions, events, and plugin panes are best effort on Windows. Commands are argv commands and must be Windows-compatible; Node package shims such as `npm`, `bun`, and `node` are expected to work when they are on `PATH`, while Unix-only examples using `sh` or Bash need Windows-specific alternatives. Platform filters skip unsupported build commands and return `platform_unsupported` for unsupported actions or panes.
+
+## Partial support
+
+| Capability | Status |
+| --- | --- |
+| Live cwd after shell `cd` | partial |
+| Live cwd via shell integration/OSC7 | beta |
+| Clipboard image paste to agents | unverified |
+| CJK hidden-cursor reveal | beta |
+| Kitty graphics rendering | unverified |
+
+Herdr can launch panes in the right directory and can create the initial workspace from the directory where you started Herdr. PowerShell directory changes after startup are different: the process field Herdr can inspect does not reliably track later logical `cd` changes. Use Herdr integrations or prompt shell integration for live cwd reporting.
+
+Windows Terminal may support image paste paths for specific agents, but Herdr's own clipboard-image reader is not wired on Windows yet. Treat `alt+v` image paste as unverified until the Windows clipboard bridge is implemented and tested. Remote clipboard image bridging is separate and remains tied to Unix/macOS `herdr --remote`.
+
+Kitty graphics remains experimental and is not claimed as Windows-supported yet. Leave `experimental.kitty_graphics = false` unless you are specifically testing image rendering in Windows Terminal.
+
+## Copy and paste
+
+Herdr's pane text copy works on Windows beta. Drag-select text inside a pane to copy through Herdr.
+
+For paste, use `ctrl+shift+v` in Windows Terminal, or hold `shift` and right-click to use the outer terminal paste action instead of sending the click through Herdr.
+
+## Not supported on Windows beta
+
+| Capability | Status |
+| --- | --- |
+| Direct terminal attach | unsupported |
+| `herdr --remote` from the Windows binary | unsupported |
+| Live server handoff | unsupported |
+| Unix file-descriptor handoff | unsupported |
+| Unix foreground process groups | unsupported |
+| Remote clipboard image bridge | unsupported |
+| Prefix input-source switching | unsupported |
+| Signed binary / SmartScreen avoidance | unsupported |
+
+For remote work from Windows, SSH into the server and run `herdr` there:
+
+```powershell
+ssh you@server
+herdr
+```
+
+That mode runs Herdr on the remote host. Native Windows `herdr --remote` is not part of the beta.
+
+Windows updates run through the Windows installer and update the versioned install junction. Restart running Herdr sessions after updating. Live handoff is Unix-only.
+
+## Reporting Windows beta issues
+
+Include:
+
+- Herdr version.
+- Windows version.
+- Terminal app.
+- Shell, such as PowerShell or cmd.
+- Whether you used a named `HERDR_SESSION`.
+- Relevant Herdr logs.
+- Exact steps to reproduce.