From 0230f14222e341746f638cf1fb85199a1fd50d12 Mon Sep 17 00:00:00 2001 From: Guillaume Jay Date: Sat, 26 Sep 2026 07:51:34 +0200 Subject: [PATCH 1/2] docs: working install URLs, and the book catches up with the code The one-line installers pointed at /releases/latest/, which GitHub resolves to nothing while every release is a pre-release, and at termherd-installer.{sh,ps1}, while dist names them after the package (termherd-app-installer.*). Both halves 404'd. The commands now name the tag and the real file. The attestation example had the same wrong tarball name, and the SHA256SUMS it promised only exists from the next release onward. A sweep of the rest of the book against the source fixed: - README: prompt_in_session missing from the live-bridge table, and still listed as a pending follow-up although it shipped (#196). - The mcp.allow_claude_nesting setting was in none of the settings pages, the template, the README list, or the file-only enumerations. - mcp/keyboard.md: the press step field is `result`, not `outcome`, and the close prompt reports as `tab-close-confirm`. - termherd://keys/schema lists neither activate-tab-N nor a default for copy/paste; three pages claimed the whole catalogue. - snapshot's focused_terminal argument was undocumented. - quick-start claimed splits resize by keyboard; nothing resizes them. - tabs-and-splits gave Shift+Right for a Cmd/Ctrl+Shift+Right chord. - AGENTS.md counted sixteen live-bridge tools; there are seventeen. Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 12 ++++----- README.md | 36 +++++++++++++++++---------- docs/settings.example.jsonc | 8 ++++++ docs/src/guide/installation.md | 17 +++++++++---- docs/src/guide/quick-start.md | 5 ++-- docs/src/mcp/keyboard.md | 9 ++++--- docs/src/mcp/live-bridge.md | 5 ++-- docs/src/mcp/stdio.md | 6 +++-- docs/src/reference/keyboard.md | 11 +++++--- docs/src/reference/settings.md | 18 +++++++++++--- docs/src/workspace/tabs-and-splits.md | 4 +-- 11 files changed, 88 insertions(+), 43 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 997e738..12d5d3e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -149,17 +149,17 @@ into its `mcpServers` at spawn (loopback, per-session token) — so it can read and drive the workspace it runs in. This is the richer sibling of the capture dump above: same `WorkspaceSnapshot` model, live instead of a file. -**Settled.** Sixteen tools: `list_sessions` + `snapshot` +**Settled.** Seventeen tools: `list_sessions` + `snapshot` (perception), `open_session` / `split_pane` / `focus_pane` / `rename_tab` / `close_pane` / `run_in_session` / `mouse_in_session` (action), `wait_for_status` + `read_terminal` (synchronisation), `screenshot` (pixels), `press_keys` + `run_action` (the app's own keyboard), `add_repo` + `forget_repo` (membership — what the sidebar *contains*, as against what the -window draws). The loop they exist to -serve is **act → wait → observe**: `run_in_session` returns immediately, so -synchronise with `wait_for_status` and then `read_terminal`. Do **not** poll -`snapshot` in a loop — it races the transition you are watching for, which is -why the wait rung exists. +window draws), and `prompt_in_session` (the loop below, composed). The loop +they exist to serve is **act → wait → observe**: `run_in_session` returns +immediately, so synchronise with `wait_for_status` and then `read_terminal`. +Do **not** poll `snapshot` in a loop — it races the transition you are +watching for, which is why the wait rung exists. **That loop did not run until #236, and now does.** Every session used to sit on `starting`, so `wait_for_status` only ever settled by timing out. Two diff --git a/README.md b/README.md index 281bb2f..d8f1522 100644 --- a/README.md +++ b/README.md @@ -69,17 +69,22 @@ one for your platform: `.AppImage`, `chmod +x` it, and run it directly. Prefer a bare command-line binary? The same releases carry one-line installers -that drop `termherd` into your Cargo bin directory: +that drop `termherd` into your Cargo bin directory. Every release so far is a +**pre-release**, which GitHub's `/releases/latest/` shortcut skips, so name the +tag — the newest one is at the top of the +[Releases](https://github.com/Termherd/termherd/releases) page: ```bash # macOS / Linux +TAG=v0.1.0-prerelease.4 curl --proto '=https' --tlsv1.2 -LsSf \ - https://github.com/Termherd/termherd/releases/latest/download/termherd-installer.sh | sh + "https://github.com/Termherd/termherd/releases/download/$TAG/termherd-app-installer.sh" | sh ``` ```powershell # Windows -powershell -c "irm https://github.com/Termherd/termherd/releases/latest/download/termherd-installer.ps1 | iex" +$Tag = "v0.1.0-prerelease.4" +irm "https://github.com/Termherd/termherd/releases/download/$Tag/termherd-app-installer.ps1" | iex ``` ### Verify a Linux download @@ -89,12 +94,15 @@ Linux release binaries carry a sigstore *keyless* build-provenance attestation in the public Rekor transparency log). Verify a download with the `gh` CLI: ```bash -gh attestation verify termherd-x86_64-unknown-linux-gnu.tar.xz \ +gh attestation verify termherd-app-x86_64-unknown-linux-gnu.tar.xz \ --repo Termherd/termherd ``` A successful check proves both integrity and that the artifact was built by -this repository's CI. A `SHA256SUMS` file is also attached to each release. +this repository's CI. The attestation and its `SHA256SUMS` file come from a +signing step added after `v0.1.0-prerelease.4`, so that pre-release has +neither — only per-file `.sha256` checksums and a combined `sha256.sum`, which +every release carries. ## Run from source @@ -133,6 +141,9 @@ you want and strip the comments (the real file is strict JSON). In short: - `open` — the editor command a Ctrl/Cmd-clicked file path opens in, with `{path}` / `{line}` / `{col}` templates (default: the OS default handler, which cannot honour a line number). +- `mcp` — `allow_claude_nesting`: whether `prompt_in_session` may prompt + another *Claude* session over the live bridge (default `false`; a shell is + never gated). - `keys` — keyboard overrides, one chord or a list per action; the full action vocabulary and its default chords are listed in the template. @@ -234,6 +245,7 @@ nothing to configure. It exposes the running workspace: | `press_keys` · `run_action` | drive termherd's own interface — chords through the live keymap, or actions by name | | `mouse_in_session` | a mouse event at a cell of a terminal — forwarded to a program reading the mouse, else the terminal's own selection | | `add_repo` · `forget_repo` | put a repository in the sidebar before it has any session, and drop that addition | +| `prompt_in_session` | type, wait and read in one round trip — prompting another Claude session is opt-in | The loop that makes it useful is **act → wait → observe**: `run_in_session`, then `wait_for_status`, then `read_terminal`. Sessions are addressed by a @@ -252,13 +264,12 @@ app on one it cannot answer; a sidebar rename used to be the exception rename — those go through a widget callback no synthesised event reaches ([#246]). -Five follow-ups remain: a composed prompt→wait→read in one round trip -([#196]), `enter` on the renames ([#246]), a doc editor that discards unsaved -edits when it closes ([#248]), reaching the bridge from outside a session -termherd spawned — the launcher cannot drive it today ([#267]) — and the -pointer at TermHerd's own interface ([#301]): it reaches a session's terminal, -and through it a program reading the mouse, but not yet the sidebar, tabs or -gutters. +Four follow-ups remain: `enter` on the renames ([#246]), a doc editor that +discards unsaved edits when it closes ([#248]), reaching the bridge from +outside a session termherd spawned — the launcher cannot drive it today +([#267]) — and the pointer at TermHerd's own interface ([#301]): it reaches a +session's terminal, and through it a program reading the mouse, but not yet +the sidebar, tabs or gutters. ### The stdio server (manual) @@ -284,7 +295,6 @@ It speaks JSON-RPC over stdio. Register it with Claude Code by adding it to your Build the binary with `cargo build -p termherd-mcp` (it lands in `target/`). [#90]: https://github.com/Termherd/termherd/issues/90 -[#196]: https://github.com/Termherd/termherd/issues/196 [#237]: https://github.com/Termherd/termherd/issues/237 [#246]: https://github.com/Termherd/termherd/issues/246 [#248]: https://github.com/Termherd/termherd/issues/248 diff --git a/docs/settings.example.jsonc b/docs/settings.example.jsonc index cceb757..cf65b73 100644 --- a/docs/settings.example.jsonc +++ b/docs/settings.example.jsonc @@ -156,6 +156,14 @@ "scale": 0.5 }, + // ── MCP live bridge ────────────────────────────────────────────────────── + // Whether `prompt_in_session` may prompt another *Claude* session (an agent + // driving an agent). Shell sessions are never gated. A single call can also + // opt in with its own `allow_claude_nesting: true`. Default: false. + "mcp": { + "allow_claude_nesting": false + }, + // ── Keyboard overrides ─────────────────────────────────────────────────── // Each entry binds an action to one chord or a list of chords and REPLACES // that action's default; unlisted actions keep their per-platform default. diff --git a/docs/src/guide/installation.md b/docs/src/guide/installation.md index 869b8e6..2bf33b8 100644 --- a/docs/src/guide/installation.md +++ b/docs/src/guide/installation.md @@ -40,17 +40,21 @@ On Windows, SmartScreen may warn — choose **More info → Run anyway**. ## Bare command-line binary The same releases carry one-line installers that drop `termherd` into your -Cargo bin directory: +Cargo bin directory. Every release so far is a **pre-release**, which GitHub's +`/releases/latest/` shortcut skips, so name the tag — the newest one is at the +top of the [Releases](https://github.com/Termherd/termherd/releases) page: ```bash # macOS / Linux +TAG=v0.1.0-prerelease.4 curl --proto '=https' --tlsv1.2 -LsSf \ - https://github.com/Termherd/termherd/releases/latest/download/termherd-installer.sh | sh + "https://github.com/Termherd/termherd/releases/download/$TAG/termherd-app-installer.sh" | sh ``` ```powershell # Windows -powershell -c "irm https://github.com/Termherd/termherd/releases/latest/download/termherd-installer.ps1 | iex" +$Tag = "v0.1.0-prerelease.4" +irm "https://github.com/Termherd/termherd/releases/download/$Tag/termherd-app-installer.ps1" | iex ``` ## Verifying a Linux download @@ -60,12 +64,15 @@ attestation — no signing key; the signer is the release workflow itself, via GitHub OIDC, logged in the public Rekor transparency log. ```bash -gh attestation verify termherd-x86_64-unknown-linux-gnu.tar.xz \ +gh attestation verify termherd-app-x86_64-unknown-linux-gnu.tar.xz \ --repo Termherd/termherd ``` A passing check proves both integrity and that the artifact was built by this -repository's CI. A `SHA256SUMS` file is attached to each release as well. +repository's CI. The attestation and its `SHA256SUMS` file come from a signing +step added after `v0.1.0-prerelease.4`, so that pre-release has neither — only +per-file `.sha256` checksums and a combined `sha256.sum`, which every release +carries. ## From source diff --git a/docs/src/guide/quick-start.md b/docs/src/guide/quick-start.md index e5f17ae..d3a09a4 100644 --- a/docs/src/guide/quick-start.md +++ b/docs/src/guide/quick-start.md @@ -67,8 +67,9 @@ shows the matched line under the row so you can tell *why* it matched. See | Close the focused pane (a lone pane closes its tab) | Cmd+W | Ctrl+W | | Reopen the tab you just closed | Cmd+Shift+T | Ctrl+Shift+T | -Tabs also reorder by drag-and-drop. Splits resize by keyboard focus only for -now — drag-resize is the remaining piece of `F-terminal-split`. +Tabs also reorder by drag-and-drop. Split panes always share their space +evenly — resizing them, by keyboard or by drag, is the remaining piece of +`F-terminal-split`. ## 4. Watch what needs you diff --git a/docs/src/mcp/keyboard.md b/docs/src/mcp/keyboard.md index e747d77..df452eb 100644 --- a/docs/src/mcp/keyboard.md +++ b/docs/src/mcp/keyboard.md @@ -89,18 +89,19 @@ anything applies. The error names the offender and the syntax. This is deliberate: a half-applied sequence is worse than none, because the caller cannot tell how far it got. -The action catalogue is published by the [stdio server](./stdio.md) at +The action catalogue — less the `activate-tab-N` family, which `run_action` +accepts all the same — is published by the [stdio server](./stdio.md) at `termherd://keys/schema`; the live bridge serves tools only, so its `run_action` error message carries the syntax instead. ## Example: verify a keyboard gesture end to end ```text -run_action(["split-vertical"]) → { steps: [{ outcome: "ran", +run_action(["split-vertical"]) → { steps: [{ result: "ran", action: "split-vertical" }], focused_handle: "4" } screenshot({ max_width: 900 }) → the pixels, to check the divider -press_keys(["cmd+w"]) → { steps: [{ outcome: "overlay", - overlay: "close-confirm" }] } +press_keys(["cmd+w"]) → { steps: [{ result: "overlay", + overlay: "tab-close-confirm" }] } press_keys(["escape"]) → cancelled ``` diff --git a/docs/src/mcp/live-bridge.md b/docs/src/mcp/live-bridge.md index c52398f..36bb579 100644 --- a/docs/src/mcp/live-bridge.md +++ b/docs/src/mcp/live-bridge.md @@ -16,7 +16,7 @@ session is torn down. | Tool | Args | Returns | | --- | --- | --- | | `list_sessions` | — | `{ sessions: [...] }` — each row a live session: stable `handle`, tab title, cwd, kind (`shell` / `claude`), resumed Claude id, status | -| `snapshot` | `sections`, `terminals`, `text_lines` | the whole state: config, sidebar, tabs and panes | +| `snapshot` | `sections`, `terminals`, `focused_terminal`, `text_lines` | the whole state: config, sidebar, tabs and panes | | `read_terminal` | `session`, `lines` | `{ text, rendered }` | | `screenshot` | `max_width` | the window as a PNG | @@ -25,7 +25,8 @@ schema check, which is why `list_sessions` puts its rows in a `sessions` field rather than answering the array itself. **`snapshot` is light by default**: structure only, no terminal text. Scope -text to named handles with `terminals`, or pass `sections` (any of `"config"`, +text to named handles with `terminals` (or set `focused_terminal: true` for the +focused pane, when you do not know its handle yet), or pass `sections` (any of `"config"`, `"sidebar"`, `"tabs"`) to narrow it further. `text_lines` defaults to 40. Read the structure first, then ask for a handle — that ordering is why the filter exists. diff --git a/docs/src/mcp/stdio.md b/docs/src/mcp/stdio.md index 40b34c3..06fc06a 100644 --- a/docs/src/mcp/stdio.md +++ b/docs/src/mcp/stdio.md @@ -55,7 +55,7 @@ outside `dark`/`light`) answers a JSON-RPC error and writes nothing. `null` is always accepted on a writable id — it unsets the option. That is the whole write surface today. The `close`, `sidebar`, `record`, -`open`, `keys`, `terminal.font_size`, `terminal.copy_on_select` and +`open`, `mcp`, `keys`, `terminal.font_size`, `terminal.copy_on_select` and `terminal.paste_on_right_click` blocks of [`settings.json`](../reference/settings.md) are file-only — `keys` is readable as a resource, below. @@ -71,7 +71,9 @@ readable as a resource, below. keymap itself uses, so it cannot drift from the binary you are running. It is the machine-readable form of [Keyboard shortcuts](../reference/keyboard.md), and the catalogue the live -bridge's `run_action` speaks. +bridge's `run_action` speaks — less the `activate-tab-N` family, which +`run_action` accepts but the resource does not list. `copy` and `paste` appear +with no default: theirs differ per platform and are set outside that table. ## What it is not diff --git a/docs/src/reference/keyboard.md b/docs/src/reference/keyboard.md index 77a7805..9fed4b1 100644 --- a/docs/src/reference/keyboard.md +++ b/docs/src/reference/keyboard.md @@ -107,7 +107,10 @@ chords are logged and skipped — they do not invalidate the rest of the file. ## Reading the live keymap -The [stdio MCP server](../mcp/stdio.md) publishes the whole catalogue — -every action with its default *and* current chords — as a resource at -`termherd://keys/schema`. It is generated from the same in-code table this page -describes, so it cannot drift from the binary you are running. +The [stdio MCP server](../mcp/stdio.md) publishes the action catalogue — each +action with its default chords and the override `settings.json` sets for it, +if any — as a resource at `termherd://keys/schema`. It is generated from the +same in-code table this page describes, so it cannot drift from the binary you +are running. Two gaps: the `activate-tab-N` family is not listed, and `copy` / +`paste` show no default, because theirs differ per platform and are set +outside that table — this page has them. diff --git a/docs/src/reference/settings.md b/docs/src/reference/settings.md index 001806b..34ad4b3 100644 --- a/docs/src/reference/settings.md +++ b/docs/src/reference/settings.md @@ -110,6 +110,17 @@ Values clamp: fps 1–60, `max_seconds` 1–600, `scale` 0.1–1.0. "record": { "fps": 8, "max_seconds": 30, "scale": 0.5 } ``` +### `mcp` + +Whether the live bridge's `prompt_in_session` may prompt another **Claude** +session — one agent driving another. Off by default; a shell session is never +gated. A single call can opt in on its own with `allow_claude_nesting: true` +(see [The live bridge](../mcp/live-bridge.md)). + +```json +"mcp": { "allow_claude_nesting": false } +``` + ### `open` The command a Cmd/Ctrl-clicked file path opens in. Omit @@ -166,9 +177,9 @@ The eight ids it covers today: `theme`, `shell.program`, `shell.args`, `terminal.colors.palette`. Two of them — `shell.program` and `shell.args` — are **read-only** over MCP: they name what TermHerd executes at the next launch, so an agent may read them but never set them. The `close`, `sidebar`, -`record`, `open`, `keys`, `terminal.font_size`, `terminal.copy_on_select` and -`terminal.paste_on_right_click` blocks are file-only for now; `keys` is -published as a read-only resource. +`record`, `open`, `mcp`, `keys`, `terminal.font_size`, +`terminal.copy_on_select` and `terminal.paste_on_right_click` blocks are +file-only for now; `keys` is published as a read-only resource. A `set_option` write lands in `settings.json` and **applies on restart**, like any other edit to the file. @@ -189,6 +200,7 @@ any other edit to the file. "sidebar": { "session_limit": 0 }, "record": { "fps": 10, "max_seconds": 20, "scale": 0.5 }, "open": { "command": "code -g {path}:{line}:{col}" }, + "mcp": { "allow_claude_nesting": false }, "keys": { "toggle-sidebar": "ctrl+alt+b", "focus-next": "ctrl+alt+right" diff --git a/docs/src/workspace/tabs-and-splits.md b/docs/src/workspace/tabs-and-splits.md index f01b88b..cb9dc28 100644 --- a/docs/src/workspace/tabs-and-splits.md +++ b/docs/src/workspace/tabs-and-splits.md @@ -53,8 +53,8 @@ there is no second, rival tab tree to drift out of sync. | Focus a neighbour | Cmd+Shift+←↑↓→ | Ctrl+Shift+←↑↓→ | A split opens a **fresh shell** beside the focused pane. Directional focus -walks the pane tree geometrically — Shift+→ goes to the -pane on the right, whatever the nesting. +walks the pane tree geometrically — Cmd/Ctrl+Shift+→ +goes to the pane on the right, whatever the nesting. Closing the **last** pane in a tab closes the tab. From b8f9625965df759a926b08228466281e9746b762 Mon Sep 17 00:00:00 2001 From: Guillaume Jay Date: Sat, 26 Sep 2026 07:56:16 +0200 Subject: [PATCH 2/2] fix(sidebar): the hide button speaks English, and the book's loose ends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sidebar's collapse button was the one user-facing label left outside strings.rs, hard-coded in French ("◀ Masquer le panneau") while the book shows "◀ Hide". It now reads strings::SIDEBAR_HIDE. Doc wording the audit flagged as doubtful, now settled against the code: - mcp/keyboard.md: the second rename that ignores `enter` is tab-rename; there is no rename in the doc pane. - contributing.md / book.toml: create-missing = false checks SUMMARY.md entries only, not links inside a page. - reference/keyboard.md: list the modifier aliases and the `plus` key. - README / terminal.md: the copy chord asks the terminal for its selection, including one scrolled out of view, rather than reading the screen. .serena/ (local state of the Serena MCP tool) is now ignored. Co-Authored-By: Claude Opus 5.5 --- .gitignore | 3 +++ README.md | 19 +++++++++---------- crates/app/src/shell/view/sidebar.rs | 2 +- crates/app/src/strings.rs | 1 + docs/book.toml | 5 +++-- docs/src/mcp/keyboard.md | 9 +++++---- docs/src/project/contributing.md | 8 +++++--- docs/src/reference/keyboard.md | 4 +++- docs/src/workspace/terminal.md | 10 +++++----- 9 files changed, 35 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index f1bd836..ea63c1f 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,6 @@ dev.termherd.lock # Per-directory tool caches the impeccable skill drops beside the sources it # reads; they reappear on every run, so ignore rather than clean repeatedly. .impeccable/ + +# Serena MCP tool state (local) +.serena/ diff --git a/README.md b/README.md index d8f1522..2235d7c 100644 --- a/README.md +++ b/README.md @@ -191,17 +191,16 @@ where those keys produce `&`, `é`, … without Shift. Dragging with the mouse selects, and the wheel scrolls back through history. The two classic terminal clipboard gestures are off until you ask for them: `terminal.copy_on_select` makes a drag release (or a double-click) copy -outright, and `terminal.paste_on_right_click` makes a right-click paste into -the pane under the pointer. Left off, the copy chord reads whatever is -highlighted on screen. A full-screen program that reads the mouse — Claude -Code's `/diff` and `/resume`, vim, lazygit, less — owns it while it runs: -clicks, drags and the wheel go to the program, nothing is selected or pasted -locally, and Shift+drag takes the mouse back for a selection. The -copy chord does nothing in such a pane unless a Shift selection +outright, and `terminal.paste_on_right_click` makes a right-click paste into the +pane under the pointer. Left off, the copy chord copies the terminal's current +selection, even one scrolled out of view. A full-screen program that reads the +mouse — Claude Code's `/diff` and `/resume`, vim, lazygit, less — owns it while +it runs: clicks, drags and the wheel go to the program, nothing is selected or +pasted locally, and Shift+drag takes the mouse back for a selection. +The copy chord does nothing in such a pane unless a Shift selection exists, so a program's own clipboard write (Claude Code copies a drag on -release) is never overwritten. In -the sidebar, click a project or session to open it; a tab's `×` also closes -it. Hovering a tab shows the session's fuller +release) is never overwritten. In the sidebar, click a project or session to +open it; a tab's `×` also closes it. Hovering a tab shows the session's fuller description (the same card the sidebar shows). **+ Add a repo** puts a repository in the sidebar before it has any session — or drop its folder on the window, which does the same thing (a dropped *file* is ignored). diff --git a/crates/app/src/shell/view/sidebar.rs b/crates/app/src/shell/view/sidebar.rs index 0ad5c91..05c78d8 100644 --- a/crates/app/src/shell/view/sidebar.rs +++ b/crates/app/src/shell/view/sidebar.rs @@ -116,7 +116,7 @@ impl Shell { } // A handle to collapse the sidebar, mirroring the one that // restores it from the main pane. - let hide = button(text("◀ Masquer le panneau").size(11)) + let hide = button(text(strings::SIDEBAR_HIDE).size(11)) .on_press(Message::ToggleSidebar) .style(button::text) .padding(0); diff --git a/crates/app/src/strings.rs b/crates/app/src/strings.rs index 7167bd8..557eb06 100644 --- a/crates/app/src/strings.rs +++ b/crates/app/src/strings.rs @@ -17,6 +17,7 @@ pub const RENAME_PLACEHOLDER: &str = "title…"; pub const SIDEBAR_LAUNCH_SHELL: &str = "Open a shell here"; pub const SIDEBAR_LAUNCH_CLAUDE: &str = "Start a fresh Claude session"; pub const SIDEBAR_SHOW_LESS: &str = "show less"; +pub const SIDEBAR_HIDE: &str = "◀ Hide"; pub const SIDEBAR_ADD_REPO: &str = "+ Add a repo"; pub const SIDEBAR_ADD_REPO_HINT: &str = "Pick a folder, or drop one on the window"; pub const SIDEBAR_FORGET_REPO: &str = "Remove this repo from the sidebar"; diff --git a/docs/book.toml b/docs/book.toml index 5ed7b60..1efa68e 100644 --- a/docs/book.toml +++ b/docs/book.toml @@ -7,8 +7,9 @@ src = "src" [build] build-dir = "book" -# A link to a page that does not exist must fail the build, not silently mint an -# empty page. The chapter map in SUMMARY.md is a promise; this keeps it honest. +# A SUMMARY.md entry for a page that does not exist must fail the build, not +# silently mint an empty page (in-page links are not checked). The chapter map +# in SUMMARY.md is a promise; this keeps it honest. create-missing = false [output.html] diff --git a/docs/src/mcp/keyboard.md b/docs/src/mcp/keyboard.md index df452eb..48800e4 100644 --- a/docs/src/mcp/keyboard.md +++ b/docs/src/mcp/keyboard.md @@ -72,10 +72,11 @@ selection, and `copy` runs on it. - On **`quit-confirm`**, `enter` quits the app — killing every session and the connection you are speaking over. -- **`session-rename`** (the sidebar's inline ✎ field) answers to neither - `enter` nor the rename in the doc pane: both commit through the widget's own - submit, which a synthesised key event never reaches. `escape` abandons it — - so you can always back out and start over — but committing a rename over MCP +- **`session-rename`** (the sidebar's inline ✎ field) does not commit on + `enter`, and neither does **`tab-rename`**: both commit through the widget's + own submit, which a synthesised key event never reaches. `escape` abandons + either — so you can always back out and start over — but committing a rename + over MCP is a missing capability, tracked as [#246](https://github.com/Termherd/termherd/issues/246). - Every other overlay is exitable from the keyboard, and a test sweep derived diff --git a/docs/src/project/contributing.md b/docs/src/project/contributing.md index e491914..0dee4c4 100644 --- a/docs/src/project/contributing.md +++ b/docs/src/project/contributing.md @@ -36,9 +36,11 @@ just docs # build → docs/book/index.html just docs-serve # live reload on http://localhost:3000 ``` -`create-missing = false` in `book.toml` means a link to a page that does not -exist **fails the build** rather than silently minting an empty page. The -chapter map in `SUMMARY.md` is a promise; that setting keeps it honest. +`create-missing = false` in `book.toml` means a `SUMMARY.md` entry for a page +that does not exist **fails the build** rather than silently minting an empty +page. The chapter map is a promise; that setting keeps it honest. It covers +`SUMMARY.md` only — a broken link *inside* a page still builds, so check those +by hand. ## Three rules that surprise newcomers diff --git a/docs/src/reference/keyboard.md b/docs/src/reference/keyboard.md index 9fed4b1..e8d2864 100644 --- a/docs/src/reference/keyboard.md +++ b/docs/src/reference/keyboard.md @@ -92,7 +92,9 @@ way an [MCP caller](../mcp/keyboard.md) can answer a prompt it armed. ## Chord syntax Case- and order-insensitive. Modifiers `ctrl`, `shift`, `alt`, `cmd`, joined to -a key with `+`: +a key with `+`. Aliases: `control` for `ctrl`, `option` for `alt`, and +`super`, `logo`, `win` or `meta` for `cmd`. The `+` key itself is spelled +`plus`, since a literal `+` is the separator: ```json "keys": { diff --git a/docs/src/workspace/terminal.md b/docs/src/workspace/terminal.md index 7521919..bbac232 100644 --- a/docs/src/workspace/terminal.md +++ b/docs/src/workspace/terminal.md @@ -30,11 +30,11 @@ so nothing reaches the clipboard unless you asked for it: - **`copy_on_select`** — releasing a drag, or double-clicking a word, copies the selection outright. With it off the selection still highlights and waits - for the copy chord, which reads the highlight currently on screen — so the - text you copy is the text you just selected, never what you copied last. - With nothing selected the chord does nothing — in particular in a pane - whose program owns the mouse (below), where the program's own copy of a drag - stays on the clipboard untouched. + for the copy chord, which asks the terminal for its current selection — even + one scrolled out of view — so the text you copy is the text you just + selected, never what you copied last. With nothing selected the chord does + nothing — in particular in a pane whose program owns the mouse (below), where + the program's own copy of a drag stays on the clipboard untouched. - **`paste_on_right_click`** — a right-click pastes into **the pane under the pointer**, which need not be the focused one, and is bracketed when that pane asked for bracketed paste. The click also focuses that pane, so the keys you