Picks up #7108, which restores main's clippy and rustfmt gate (CW-7525).
Signed-off-by: CodeWhale Bot <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **MCP catalogs stay fresh:** a server's tools, resources, prompts and skills are rediscovered on their own connection when an advertised `ttlMs` expires or the server sends a list-changed notice. A tool resolved against the old catalog is refused with "retry the call", a removed tool cannot run, and a failed refresh reconnects instead of serving stale entries. Catalogs are never shared across servers, credentials or reconnects. (CW-7547)
- **MCP Skills extension:** servers that advertise the published Skills extension have their skills listed in `list_mcp_resources`. Listing never activates a skill, and reading a skill file is refused unless its size and sha256 digest match the listing. MCP skills do not yet join `/skills`. (CW-7545)
- **Computer Use is installed, not bundled:** the Computer Use plugin is no longer vendored into the binary. Install it from the `codewhale` marketplace, which points at its independent release; its consent tools load on first use, and decisions still require a human approval card. (CW-6732)
- **First-party marketplace receipt:** the shipped catalog is pinned to marketplace revision `a5f1d210372ff48c9a278a0a39737956ac0f2d93`.
- **Tool image validation:** an image returned by a tool must decode before it is sent, so truncated or corrupt files are omitted with a receipt even when they are already within the delivery budget.
- **Image-heavy session recovery:** ordinary image reads use a 256 KiB delivery budget. Requests measure serialized bytes, omit older images from an outbound copy with receipts, and retry an initial HTTP 413 once only with a smaller body. Saved images and executed tool actions remain intact. (CW-7550)
@@ -209,6 +210,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
is now interrupted instead of running on with nothing able to stop it
(#6558).
- Multiline mode now has a send key on every terminal: with
`composer_multiline_mode = true`, `Enter` inserts a newline and `Alt-Enter`
sends. `Shift-Enter` also sends where the terminal reports it distinctly; on
Linux terminals that report it as plain `Enter`, multiline mode previously
had no way to send. `Ctrl-J` always inserts a newline. Thanks
[@luestr](https://github.com/luestr) for the report. (#7093)
- Session saves no longer fail with "Fleet artifact path must stay within the
workspace" when the Codewhale state root is a symlink or Windows junction to
another volume: the state root is resolved before session-side state is
- **[@Lstarsky0](https://github.com/Lstarsky0)** — kept the `/diff` pager's place across a resize ([#7087](https://github.com/codewhale-hq/Codewhale/pull/7087)), said "Goal cleared." only when there was a goal ([#7089](https://github.com/codewhale-hq/Codewhale/pull/7089)), and stopped printing an unpriced session cost as `$0.0000` in `/status` ([#7090](https://github.com/codewhale-hq/Codewhale/pull/7090)).
- **[@gaord](https://github.com/gaord)** — a running turn's cost and context in the Runtime ([#7074](https://github.com/codewhale-hq/Codewhale/pull/7074)).
- **[Sh1Zuku / @SparkofSpike](https://github.com/SparkofSpike)** — resolved a relocated state root before session-side state opens ([#7097](https://github.com/codewhale-hq/Codewhale/pull/7097)).
- **[@M-Maciej](https://github.com/M-Maciej)** — reported answerless output-limit stops in long Fleet proofs ([#6990](https://github.com/codewhale-hq/Codewhale/issues/6990)).
- **[@asto18089](https://github.com/asto18089)** — diagnosed the NoNewPrivs child-matrix failure on hardened containers ([#7021](https://github.com/codewhale-hq/Codewhale/issues/7021)).
- **[@luestr](https://github.com/luestr)** — reported the Linux multiline send key ([#7093](https://github.com/codewhale-hq/Codewhale/issues/7093)) and session export guidance ([#6996](https://github.com/codewhale-hq/Codewhale/issues/6996)).
## [0.10.2] - 2026-10-22
Codewhale v0.10.2 adds an animated pet view (`/pet on`), a live Terminal work
@@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **MCP catalogs stay fresh:** a server's tools, resources, prompts and skills are rediscovered on their own connection when an advertised `ttlMs` expires or the server sends a list-changed notice. A tool resolved against the old catalog is refused with "retry the call", a removed tool cannot run, and a failed refresh reconnects instead of serving stale entries. Catalogs are never shared across servers, credentials or reconnects. (CW-7547)
- **MCP Skills extension:** servers that advertise the published Skills extension have their skills listed in `list_mcp_resources`. Listing never activates a skill, and reading a skill file is refused unless its size and sha256 digest match the listing. MCP skills do not yet join `/skills`. (CW-7545)
- **Computer Use is installed, not bundled:** the Computer Use plugin is no longer vendored into the binary. Install it from the `codewhale` marketplace, which points at its independent release; its consent tools load on first use, and decisions still require a human approval card. (CW-6732)
- **First-party marketplace receipt:** the shipped catalog is pinned to marketplace revision `a5f1d210372ff48c9a278a0a39737956ac0f2d93`.
- **Tool image validation:** an image returned by a tool must decode before it is sent, so truncated or corrupt files are omitted with a receipt even when they are already within the delivery budget.
- **Image-heavy session recovery:** ordinary image reads use a 256 KiB delivery budget. Requests measure serialized bytes, omit older images from an outbound copy with receipts, and retry an initial HTTP 413 once only with a smaller body. Saved images and executed tool actions remain intact. (CW-7550)
@@ -209,6 +210,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
is now interrupted instead of running on with nothing able to stop it
(#6558).
- Multiline mode now has a send key on every terminal: with
`composer_multiline_mode = true`, `Enter` inserts a newline and `Alt-Enter`
sends. `Shift-Enter` also sends where the terminal reports it distinctly; on
Linux terminals that report it as plain `Enter`, multiline mode previously
had no way to send. `Ctrl-J` always inserts a newline. Thanks
[@luestr](https://github.com/luestr) for the report. (#7093)
- Session saves no longer fail with "Fleet artifact path must stay within the
workspace" when the Codewhale state root is a symlink or Windows junction to
another volume: the state root is resolved before session-side state is
- **[@Lstarsky0](https://github.com/Lstarsky0)** — kept the `/diff` pager's place across a resize ([#7087](https://github.com/codewhale-hq/Codewhale/pull/7087)), said "Goal cleared." only when there was a goal ([#7089](https://github.com/codewhale-hq/Codewhale/pull/7089)), and stopped printing an unpriced session cost as `$0.0000` in `/status` ([#7090](https://github.com/codewhale-hq/Codewhale/pull/7090)).
- **[@gaord](https://github.com/gaord)** — a running turn's cost and context in the Runtime ([#7074](https://github.com/codewhale-hq/Codewhale/pull/7074)).
- **[Sh1Zuku / @SparkofSpike](https://github.com/SparkofSpike)** — resolved a relocated state root before session-side state opens ([#7097](https://github.com/codewhale-hq/Codewhale/pull/7097)).
- **[@M-Maciej](https://github.com/M-Maciej)** — reported answerless output-limit stops in long Fleet proofs ([#6990](https://github.com/codewhale-hq/Codewhale/issues/6990)).
- **[@asto18089](https://github.com/asto18089)** — diagnosed the NoNewPrivs child-matrix failure on hardened containers ([#7021](https://github.com/codewhale-hq/Codewhale/issues/7021)).
- **[@luestr](https://github.com/luestr)** — reported the Linux multiline send key ([#7093](https://github.com/codewhale-hq/Codewhale/issues/7093)) and session export guidance ([#6996](https://github.com/codewhale-hq/Codewhale/issues/6996)).
## [0.10.2] - 2026-10-22
Codewhale v0.10.2 adds an animated pet view (`/pet on`), a live Terminal work
- **[gaord](https://github.com/gaord)** — a running turn's cost and context ([#7074](https://github.com/codewhale-hq/Codewhale/pull/7074)).
- **[Sh1Zuku / SparkofSpike](https://github.com/SparkofSpike)** — relocated state root before session-side state ([#7097](https://github.com/codewhale-hq/Codewhale/pull/7097)).
</details>
<details>
<summary><strong>v0.10.2 — terminal, recovery and reliability</strong></summary>
@@ -17,8 +17,8 @@ Global key chords are not yet user-configurable — tracked for a future release
| `Ctrl-C` | Cancel current turn / dismiss modal / clear a non-empty draft (recoverable — see `Ctrl-Z`) / arm-then-confirm quit |
| `Ctrl-B` | Release the current shell wait so the turn can continue; foreground commands move into `/jobs`, and background tasks keep running. Use `/jobs` or `Bash` with `action: "wait"` to inspect output |
| `Ctrl-D` | Quit (only when the composer is empty) |
| `Tab` | When the composer is empty, cycle TUI mode: Plan → Work → Operate → Plan |
| `Shift+Tab` | Cycle permission posture: Ask → Auto-Review → Full Access. Live regardless of composer contents or whether a turn is running (suppressed only while a modal other than Config is open) |
| `Tab` | When the composer is empty, cycle TUI mode: Plan → Work → Operate → Plan. Works while a turn is running: the change applies at the agent's next step in the same turn, and the status line says so until it does |
| `Shift+Tab` | Cycle permission posture: Ask → Auto-Review → Full Access. Live regardless of composer contents or whether a turn is running (suppressed only while a modal other than Config is open). During a turn the change applies at the agent's next step; a call you already approved runs only if the new posture is equal or broader. Model, thinking level and provider stay locked until the turn ends |
| `Ctrl-T` | Cycle reasoning effort for the active model. Walks the same ladder as `/model` and `/effort` (catalog or documented route dialect). Always-thinking models omit `off`; Grok 4.6 includes `xhigh`. |
| `Ctrl-Shift-T` | Toggle live transcript overlay (sticky-tail auto-scroll) |
| `Ctrl-R` | Open the resume-session picker |
@@ -46,7 +46,7 @@ Editing the message you're about to send.
| `Enter` | Send when idle; queue while busy; with an empty composer, send the next queued follow-up now |
| `Shift-Enter` / `Alt-Enter` / `Ctrl-J` | Insert a newline without sending (idle or busy) |
| `Ctrl-Enter` / `Cmd-Enter` | Send into the current turn; send normally when idle (when the terminal reports it distinctly) |
| `Ctrl-Enter` / `Cmd-Enter` | Steer: send into the current turn, closing the in-flight model request at once (reasoning, text or tool call) and continuing the same turn with your message; send normally when idle (when the terminal reports it distinctly). Text already shown is kept; unfinished reasoning and partial tool calls are discarded, never run. A second `Enter` within 500 ms of queueing a message while busy steers too |
| `Ctrl-U` | Clear the whole draft (recoverable — see `Ctrl-Z`) |
| `Ctrl-Z` | Restore the cleared draft (only while the composer is empty) |
| `Ctrl-C` | Clear the whole draft when no turn is running (recoverable — see `Ctrl-Z`) |
"content":"# Installing Codewhale\n\n> 阅读简体中文版:[zh_hans/INSTALL.md](zh_hans/INSTALL.md)\n\nCodewhale is an open-source coding agent that runs in your terminal. You give\nit a task (\"fix the failing test\", \"add a CLI flag\"). It reads your repository,\nedits files and runs commands. In the default **Ask** posture it applies file\nedits inside the workspace immediately (and shows you the diff), but asks before\nrunning shell commands, so commit or stash anything you care about first. It\nworks with many model providers. **DeepSeek** is the default.\n\nThe command is `codewhale`. `codew` is a shorter alias for the same program.\n\nThe installation paths were first checked with **v0.10.0** (released 2026-09-22) on a\nfresh **Ubuntu 24.04 x86_64** machine. The dated\n[install receipts](https://github.com/codewhale-hq/Codewhale/blob/37ecdfcc49bc68a9b0d058b97c3946e62c34bd31/docs/install-report/v0.10.0-2026-09-23/RECEIPTS.md) record the commands and output checked at that time. Steps that\ncould not be run on that machine are marked **(untested on this VM: reason)**.\nmacOS, Windows and Android are out of scope, apart from a few notes. A second\npass re-ran the installer, manual-download, archive and npm paths, the no-key\nchecks and zsh completion on **macOS 26.1 (Apple silicon)**; see\n[macOS notes](#macos-notes). Steps that need a model call were not re-run\nthere.\n\nInstall commands that use `latest` resolve to the latest **published** GitHub\nRelease or package. Between releases, `main` may already describe the next\nversion (for example a v0.10.2 source candidate before its tag). A\nprebuilt candidate is available through the official installer only after its\ntag, checksums and release assets exist. Contributors can build `main` now.\n\n## No account needed\n\nCodewhale needs no account. Keys you save with `/provider` or\n`codewhale auth set` stay on your machine; see\n[API keys and providers](#8-api-keys-and-providers). New Codewhale accounts\nare not open, so this guide does not cover account key storage.\n\n## Test and contribute to current source\n\n`latest` selects the latest published release. To test unreleased repairs,\nbuild canonical GitHub `main`, or CNB `main` after verifying its commit matches.\nThe source version number alone does not establish a published package.\n\n```bash\ngit clone --branch main https://github.com/codewhale-hq/CodeWhale.git\ncd CodeWhale\ncargo build --release --locked -p codewhale-cli\ntarget/release/codewhale --version\n```\n\nSee the Cargo section for build prerequisites; use the repository's stable Rust\nselection (declared minimum 1.89). Windows uses `target/release/codewhale.exe`\nand needs MSVC. A development build is separate from a signed release package.\nFor mainland-China downloads and source validation, see [CNB mirror](CNB_MIRROR.md).\nThe [Tencent Lighthouse bootstrap](../scripts/tencent-lighthouse/README.md) is\nbilingual. An npm registry mirror serves the wrapper; native binary downloads\nstill need an available release asset source.\n\n---\n\n## 60-second quickstart (Linux or macOS)\n\n```bash\n# 1. Install. Downloads two checksum-verified binaries into ~/.local/bin (no sudo).\ncurl -fsSL https://codewhale.net/install.sh | sh\n\n# 2. Make sure ~/.local/bin is on your PATH, now and in future terminals.\necho 'export PATH=\"$HOME/.local/bin:$PATH\"' >> ~/.bashrc # zsh: use ~/.zshrc\nexport PATH=\"$HOME/.local/bin:$PATH\"\ncodewhale --version # -> codewhale 0.10.0 (1be1a703b975)\n\n# 3. Give it a DeepSeek API key (from https://platform.deepseek.com/api_keys).\ncodewhale auth set --provider deepseek # prompts for the key; nothing is echoed\ncodewhale auth status --provider deepseek # \"active source: secret store\"\n\n#4.Runyourfirsttaskinsideagitrepository.\ncd~/your-project\ncodewhale\n```\n\nIntheTUI,typesomethingconcrete:\n\n```text\ncreateaPythonfileprimes.pythatprintsthefirst10primes,runit,andshowmetheoutput\n```\n\nCodewhalewritesthefile,showsyouadiff,thenasks**APPROVAL:bash\npython3primes.py–Doyouwanttoproceed?**Press`y`toallowitonce.It\nrunsthecommandandreportstheoutput.Press`Ctrl-D`(withanemptyinput\nbox)toquit.Itprintsthecommandtoresumethesessionlater.\n\n>**Ifnothinghappensafteryousendyourfirstmessage,**youhavenokey\n>configured.v0.10.0doesn'twarnyouinthatcase.Press**F3**.IfDeepSeek\n>shows`missingkey`,pressEnter,pastethekey,thenpickamodeland\n>confirm.\n\n---\n\n##Contents\n\n1.[Beforeyoustart](#1-before-you-start)\n2.[Install:recommendedinstaller](#2-recommended-installer-curl--sh)\n3.[Install:manualdownloadfromGitHubReleases](#3-manual-download-from-github-releases)\n4.[Install:npm](#4-npm)\n5.[Install:Cargo/buildfromsource](#5-cargo-and-building-from-source)\n6.[Install:Homebrew(Linux)andNix](#6-homebrew-on-linux-and-nix)\n7.[Updatingandrollingback](#Line truncated
"content":"# Installing Codewhale\n\n> 阅读简体中文版:[zh_hans/INSTALL.md](zh_hans/INSTALL.md)\n\nCodewhale is an open-source coding agent that runs in your terminal. You give\nit a task (\"fix the failing test\", \"add a CLI flag\"). It reads your repository,\nedits files and runs commands. In the default **Ask** posture it applies file\nedits inside the workspace immediately (and shows you the diff), but asks before\nrunning shell commands, so commit or stash anything you care about first. It\nworks with many model providers. **DeepSeek** is the default.\n\nThe command is `codewhale`. `codew` is a shorter alias for the same program.\n\nThe installation paths were first checked with **v0.10.0** (released 2026-09-22) on a\nfresh **Ubuntu 24.04 x86_64** machine. The dated\n[install receipts](https://github.com/codewhale-hq/Codewhale/blob/37ecdfcc49bc68a9b0d058b97c3946e62c34bd31/docs/install-report/v0.10.0-2026-09-23/RECEIPTS.md) record the commands and output checked at that time. Steps that\ncould not be run on that machine are marked **(untested on this VM: reason)**.\nmacOS, Windows and Android are out of scope, apart from a few notes. A second\npass re-ran the installer, manual-download, archive and npm paths, the no-key\nchecks and zsh completion on **macOS 26.1 (Apple silicon)**; see\n[macOS notes](#macos-notes). Steps that need a model call were not re-run\nthere.\n\nInstall commands that use `latest` resolve to the latest **published** GitHub\nRelease or package. Between releases, `main` may already describe the next\nversion (for example a v0.10.2 source candidate before its tag). A\nprebuilt candidate is available through the official installer only after its\ntag, checksums and release assets exist. Contributors can build `main` now.\n\n## No account needed\n\nCodewhale needs no account. Keys you save with `/provider` or\n`codewhale auth set` stay on your machine; see\n[API keys and providers](#8-api-keys-and-providers). New Codewhale accounts\nare not open, so this guide does not cover account key storage.\n\n## Test and contribute to current source\n\n`latest` selects the latest published release. To test unreleased repairs,\nbuild canonical GitHub `main`, or CNB `main` after verifying its commit matches.\nThe source version number alone does not establish a published package.\n\n```bash\ngit clone --branch main https://github.com/codewhale-hq/CodeWhale.git\ncd CodeWhale\ncargo build --release --locked -p codewhale-cli\ntarget/release/codewhale --version\n```\n\nSee the Cargo section for build prerequisites; use the repository's stable Rust\nselection (declared minimum 1.89). Windows uses `target/release/codewhale.exe`\nand needs MSVC. A development build is separate from a signed release package.\nFor mainland-China downloads and source validation, see [CNB mirror](CNB_MIRROR.md).\nThe [Tencent Lighthouse bootstrap](../scripts/tencent-lighthouse/README.md) is\nbilingual. An npm registry mirror serves the wrapper; native binary downloads\nstill need an available release asset source.\n\n---\n\n## 60-second quickstart (Linux or macOS)\n\n```bash\n# 1. Install. Downloads two checksum-verified binaries into ~/.local/bin (no sudo).\ncurl -fsSL https://codewhale.net/install.sh | sh\n\n# 2. Make sure ~/.local/bin is on your PATH, now and in future terminals.\necho 'export PATH=\"$HOME/.local/bin:$PATH\"' >> ~/.bashrc # zsh: use ~/.zshrc\nexport PATH=\"$HOME/.local/bin:$PATH\"\ncodewhale --version # -> codewhale 0.10.0 (1be1a703b975)\n\n# 3. Give it a DeepSeek API key (from https://platform.deepseek.com/api_keys).\ncodewhale auth set --provider deepseek # prompts for the key; nothing is echoed\ncodewhale auth status --provider deepseek # \"active source: secret store\"\n\n#4.Runyourfirsttaskinsideagitrepository.\ncd~/your-project\ncodewhale\n```\n\nIntheTUI,typesomethingconcrete:\n\n```text\ncreateaPythonfileprimes.pythatprintsthefirst10primes,runit,andshowmetheoutput\n```\n\nCodewhalewritesthefile,showsyouadiff,thenasks**APPROVAL:bash\npython3primes.py–Doyouwanttoproceed?**Press`y`toallowitonce.It\nrunsthecommandandreportstheoutput.Press`Ctrl-D`(withanemptyinput\nbox)toquit.Itprintsthecommandtoresumethesessionlater.\n\n>**Ifnothinghappensafteryousendyourfirstmessage,**youhavenokey\n>configured.v0.10.0doesn'twarnyouinthatcase.Press**F3**.IfDeepSeek\n>shows`missingkey`,pressEnter,pastethekey,thenpickamodeland\n>confirm.\n\n---\n\n##Contents\n\n1.[Beforeyoustart](#1-before-you-start)\n2.[Install:recommendedinstaller](#2-recommended-installer-curl--sh)\n3.[Install:manualdownloadfromGitHubReleases](#3-manual-download-from-github-releases)\n4.[Install:npm](#4-npm)\n5.[Install:Cargo/buildfromsource](#5-cargo-and-building-from-source)\n6.[Install:Homebrew(Linux)andNix](#6-homebrew-on-linux-and-nix)\n7.[Updatingandrollingback](#Line truncated
"content":"# Keybindings\n\n> 阅读简体中文版:[zh_hans/KEYBINDINGS.md](zh_hans/KEYBINDINGS.md)\n\nThis is the source-of-truth catalog of every keyboard shortcut the TUI recognizes. Bindings are grouped by **context** — the focus or modal state they fire in. A binding listed under \"Composer\" only takes effect when the composer is focused; one under \"Transcript\" only when the transcript has focus; and so on.\n\nGlobal key chords are not yet user-configurable — tracked for a future release (#436, #437). Hotbar slot actions are configurable with `[[hotbar]]` and `/hotbar`; the Hotbar activation chord remains `Alt-1` through `Alt-8`.\n\n## Global (any context)\n\n| Chord | Action |\n|----------------------|---------------------------------------------------------------|\n| `/help`, `F1` or `Ctrl-/` | Toggle the help overlay. `/help` is what the chrome advertises: it is the one route every terminal delivers, where `F1` is eaten by tmux and some emulators and `Ctrl-/` encoding varies |\n| `F2` | Toggle the typed Settings editor |\n| `F3` | Open the provider/model picker (same as `/provider`) |\n| `Ctrl-K` | Open the command palette (slash-command finder) |\n| `Ctrl-C` | Cancel current turn / dismiss modal / clear a non-empty draft (recoverable — see `Ctrl-Z`) / arm-then-confirm quit |\n| `Ctrl-B` | Release the current shell wait so the turn can continue; foreground commands move into `/jobs`, and background tasks keep running. Use `/jobs` or `Bash` with `action: \"wait\"`toinspectoutput|\n|`Ctrl-D`|Quit(onlywhenthecomposerisempty)|\n|`Tab`|Whenthecomposerisempty,cycleTUImode:Plan→Work→Operate→Plan|\n|`Shift+Tab`|Cyclepermissionposture:Ask→Auto-Review→FullAccess.Liveregardlessofcomposercontentsorwhetheraturnisrunning(suppressedonlywhileamodalotherthanConfigisopen)|\n|`Ctrl-T`|Cyclereasoningeffortfortheactivemodel.Walksthesameladderas`/model`and`/effort`(catalogordocumentedroutedialect).Always-thinkingmodelsomit`off`;Grok4.6includes`xhigh`.|\n|`Ctrl-Shift-T`|Togglelivetranscriptoverlay(sticky-tailauto-scroll)|\n|`Ctrl-R`|Opentheresume-sessionpicker|\n|`Ctrl-L`|Compacttheconversationcontext(statuslineshowsprogress;no-opwhileacompactionisalreadyrunning)|\n|`Ctrl-O`|Openthereasoningdetailfortheselectedorcurrentturn,regardlessofcomposercontents|\n|`Ctrl-Alt-O`|Openthewhole-turnTurnInspector,regardlessofcomposercontents|\n|`Alt-V`/`Option-V`(macOS)|Openthedetailspagerfortheselectedtool/sub-agentcard;withnothingselected,thenewestvisibleerror,elsethefirstvisiblecardwithdetails,elsethemostrecentone.ClickacardfirsttokeepAlt-Vonitwhilenewercardsarrive.TerminalsthatemitthelegacyOption-Vglypharealsohandled|\n|`Ctrl-Shift-E`/`Cmd-Shift-E`|Togglethefiletreeintheworkbar|\n|`Ctrl-]`or`Ctrl-Tab`|Cyclethepetviewwhilethepetmainviewisshowing;otherwisecycletheworkdock:TODO→Agents→Jobs→Background.`Ctrl-]`isportable;`Ctrl-Tab`requiresthekittykeyboardprotocol.Terminal.appusesittoswitchterminaltabs|\n|`Ctrl-Shift-Tab`|Cyclethepetvieworworkdockbackwardswheretheterminalsendsthekittykeyboardchord.Terminal.appusesittoswitchterminaltabs|\n|`Alt-G`/`Alt-Shift-G`|Scrolltranscripttotop/bottomwhenthecomposerisempty|\n|`Alt-1`-`Alt-8`|DispatchHotbarslots1-8whennomodalorinlinepickerisopen|\n|`Alt-!`/`Alt-@`/`Alt-#`/`Alt-$`|Selecttheworkbarpanel:Tasks/Agents/Context/Files|\n|`Ctrl-Alt-0`|Toggletheworkbaroff/backtothebottomplacement|\n|`Alt-L`|Openthepagerforthelastmessage(composerempty)|\n|`Alt-P`/`Alt-A`/`Alt-Y`|JumptoPlan/Work,orrequestFullAccess(`Alt-Y`isthelegacypermissionchannel—Work+FullAccess—notaseparatemode;ithonorsalockedapprovalpolicy)|\n|`Ctrl-X`(Activityworkbar)|Cancelallrunningbackgroundshelljobs|\n|`Esc`|Closetopmostmodal·cancelslashmenu·dismisstoast.Duringacompactthatisservinganin-flightturn,Escstopstheturn(thecompactiscollateral).|\n\n##Composer\n\nEditingthemessageyou'reabouttosend.\n\n|Chord|Action|\n|-----------------------------|---------------------------------------------------------|\n|`Enter`Line truncated
"content":"# Keybindings\n\n> 阅读简体中文版:[zh_hans/KEYBINDINGS.md](zh_hans/KEYBINDINGS.md)\n\nThis is the source-of-truth catalog of every keyboard shortcut the TUI recognizes. Bindings are grouped by **context** — the focus or modal state they fire in. A binding listed under \"Composer\" only takes effect when the composer is focused; one under \"Transcript\" only when the transcript has focus; and so on.\n\nGlobal key chords are not yet user-configurable — tracked for a future release (#436, #437). Hotbar slot actions are configurable with `[[hotbar]]` and `/hotbar`; the Hotbar activation chord remains `Alt-1` through `Alt-8`.\n\n## Global (any context)\n\n| Chord | Action |\n|----------------------|---------------------------------------------------------------|\n| `/help`, `F1` or `Ctrl-/` | Toggle the help overlay. `/help` is what the chrome advertises: it is the one route every terminal delivers, where `F1` is eaten by tmux and some emulators and `Ctrl-/` encoding varies |\n| `F2` | Toggle the typed Settings editor |\n| `F3` | Open the provider/model picker (same as `/provider`) |\n| `Ctrl-K` | Open the command palette (slash-command finder) |\n| `Ctrl-C` | Cancel current turn / dismiss modal / clear a non-empty draft (recoverable — see `Ctrl-Z`) / arm-then-confirm quit |\n| `Ctrl-B` | Release the current shell wait so the turn can continue; foreground commands move into `/jobs`, and background tasks keep running. Use `/jobs` or `Bash` with `action: \"wait\"`toinspectoutput|\n|`Ctrl-D`|Quit(onlywhenthecomposerisempty)|\n|`Tab`|Whenthecomposerisempty,cycleTUImode:Plan→Work→Operate→Plan.Workswhileaturnisrunning:thechangeappliesattheagent'snextstepinthesameturn,andthestatuslinesayssountilitdoes|\n|`Shift+Tab`|Cyclepermissionposture:Ask→Auto-Review→FullAccess.Liveregardlessofcomposercontentsorwhetheraturnisrunning(suppressedonlywhileamodalotherthanConfigisopen).Duringaturnthechangeappliesattheagent'snextstep;acallyoualreadyapprovedrunsonlyifthenewpostureisequalorbroader.Model,thinkinglevelandproviderstaylockeduntiltheturnends|\n|`Ctrl-T`|Cyclereasoningeffortfortheactivemodel.Walksthesameladderas`/model`and`/effort`(catalogordocumentedroutedialect).Always-thinkingmodelsomit`off`;Grok4.6includes`xhigh`.|\n|`Ctrl-Shift-T`|Togglelivetranscriptoverlay(sticky-tailauto-scroll)|\n|`Ctrl-R`|Opentheresume-sessionpicker|\n|`Ctrl-L`|Compacttheconversationcontext(statuslineshowsprogress;no-opwhileacompactionisalreadyrunning)|\n|`Ctrl-O`|Openthereasoningdetailfortheselectedorcurrentturn,regardlessofcomposercontents|\n|`Ctrl-Alt-O`|Openthewhole-turnTurnInspector,regardlessofcomposercontents|\n|`Alt-V`/`Option-V`(macOS)|Openthedetailspagerfortheselectedtool/sub-agentcard;withnothingselected,thenewestvisibleerror,elsethefirstvisiblecardwithdetails,elsethemostrecentone.ClickacardfirsttokeepAlt-Vonitwhilenewercardsarrive.TerminalsthatemitthelegacyOption-Vglypharealsohandled|\n|`Ctrl-Shift-E`/`Cmd-Shift-E`|Togglethefiletreeintheworkbar|\n|`Ctrl-]`or`Ctrl-Tab`|Cyclethepetviewwhilethepetmainviewisshowing;otherwisecycletheworkdock:TODO→Agents→Jobs→Background.`Ctrl-]`isportable;`Ctrl-Tab`requiresthekittykeyboardprotocol.Terminal.appusesittoswitchterminaltabs|\n|`Ctrl-Shift-Tab`|Cyclethepetvieworworkdockbackwardswheretheterminalsendsthekittykeyboardchord.Terminal.appusesittoswitchterminaltabs|\n|`Alt-G`/`Alt-Shift-G`|Scrolltranscripttotop/bottomwhenthecomposerisempty|\n|`Alt-1`-`Alt-8`|DispatchHotbarslots1-8whennomodalorinlinepickerisopen|\n|`Alt-!`/`Alt-@`/`Alt-#`/`Alt-$`|Selecttheworkbarpanel:Tasks/Agents/Context/Files|\n|`Ctrl-Alt-0`|Toggletheworkbaroff/backtothebottomplacement|\n|`Alt-L`|Openthepagerforthelastmessage(composerempty)|\n|`Alt-P`/`Alt-A`/`Alt-Y`|JumptoPlan/Work,orrequestFullAccess(`Alt-Y`isthelegacypermissionchannel—Work+FullAccess—notaseparatemode;ithonorsalockedapprovalpolicy)|\n|`Ctrl-X`(Activityworkbar)|Cancelallrunningbackgroundshelljobs|\n|`Esc`|Closetopmostmodal·cancelslashmenu·dismisstoast.DuringacompactLine truncated
"content":"# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. Instruction files written for other tools (`CLAUDE.md`,\n `.claude/instructions.md`, `.cursorrules`, `.github/copilot-instructions.md`\n and similar) are read only when you opt in with the top-level\n `project_instruction_imports` key, for example `[\"claude\"]`, `[\"cursor\"]` or\n `[\"all\"]`(see`config.example.toml`);Codewhalewarnswhenitfindsoneit\ndidnotload.\n\nCodewhalereadsoneinstructionfileperdirectory,fromtherepository\nrootdowntotheworkspace,andputsyourglobalinstructionfile(suchas\n`~/.codewhale/AGENTS.md`)infrontofthem.Thenearestscopereadslast\nandwins:theworkspacefileoverridesitsparents,andprojectfiles\noverridetheglobalfile.Globalandprojectinstructionsarebudgeted\nseparatelyinestimatedtokens(see[Instructionbudget](#instruction-budget-instruction_budget-6526)\nbelow):ascopeoveritsbudgetdropswholefilesfromthebroadestend\nfirst,andasinglefilelargerthantheremainingbudgetkeepsitshead\nwithamarkerthatnamesthebytesandtokensdropped.Afilekeepsatmost\nitsfirst100KiB,andafilelargerthan`file_max_bytesLine truncated
"content":"# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. Instruction files written for other tools (`CLAUDE.md`,\n `.claude/instructions.md`, `.cursorrules`, `.github/copilot-instructions.md`\n and similar) are read only when you opt in with the top-level\n `project_instruction_imports` key, for example `[\"claude\"]`, `[\"cursor\"]` or\n `[\"all\"]`(see`config.example.toml`);Codewhalewarnswhenitfindsoneit\ndidnotload.\n\nCodewhalereadsoneinstructionfileperdirectory,fromtherepository\nrootdowntotheworkspace,andputsyourglobalinstructionfile(suchas\n`~/.codewhale/AGENTS.md`)infrontofthem.Thenearestscopereadslast\nandwins:theworkspacefileoverridesitsparents,andprojectfiles\noverridetheglobalfile.Globalandprojectinstructionsarebudgeted\nseparatelyinestimatedtokens(see[Instructionbudget](#instruction-budget-instruction_budget-6526)\nbelow):ascopeoveritsbudgetdropswholefilesfromthebroadestend\nfirst,andasinglefilelargerthantheremainingbudgetkeepsitshead\nwithamarkerthatnamesthebytesandtokensdropped.Afilekeepsatmost\nitsfirst100KiB,andafilelargerthan`file_max_bytesLine truncated
"content":"# Provider Registry\n\n> 阅读简体中文版:[zh_hans/PROVIDERS.md](zh_hans/PROVIDERS.md)\n\nSpeech recognition, synthesis, translation and video have separate execution\npaths. See [media models](MEDIA_MODELS.md) for current support and reviewed\nupstream candidates; a chat catalogue row alone does not add a media backend.\n\nThis registry describes provider behavior that is wired into the current\nCodewhale codebase. It is intentionally conservative: shipped entries are\nlimited to provider IDs, config keys, auth paths, base URLs, model resolution,\nand capability metadata that the code already knows about.\n\nThe `/provider` and `/model` pickers recommend OrcaRouter as a partner option.\nClick the recommendation or press F7 to view the Codewhale × OrcaRouter offer:\na **30% top-up match for DeepSeek V4.1 Flash**. The pager includes the\n[redemption link](https://www.orcarouter.ai/redeem/1a6250545fdc4e0aaccb0a4470159e67)\nand can copy its text. Codewhale earns a referral fee from OrcaRouter.\nCurrent eligibility and terms are owned by the linked offer page. Viewing it\npreserves the current provider, model and credentials; redemption happens on\nOrcaRouter's site.\n\nDeepSeek remains the default provider, but every entry in `ProviderKind::ALL`\nis a first-class selectable provider route. `ALL` is the catalog/picker\nsurface — one identity per vendor. Dual-wire dialect kinds (`*Anthropic`, e.g.\n`deepseek-anthropic`) and the Model Studio plan variants stay on the enum for\nserde and `provider_for_kind` but are deliberately **not** catalog rows:\na plan is `mode`/`base_url` and a dialect is `wire = openai|anthropic` on the\nprimary provider config (`crates/config/src/provider_kind.rs:221-226`). Hosted\nroutes, generic OpenAI-compatible endpoints, the OpenAI Codex/ChatGPT route,\nnative Anthropic, and local runtimes all run the same terminal harness against\nthe selected provider/model/base URL.\n\nA host reached over plain Chat Completions is an ordinary named provider,\nnot a `ProviderKind`: enum variants are reserved for distinct *wires*\n(Anthropic Messages, Codex Responses, Google thought signatures). Any such\nhost is a `[providers.<name>]` table with a base URL, a model, and a key env\n(`docs/CONFIGURATION.md`); `/provider` and `/setup` keep a \"paste a Base URL\nand a key\"pathforexactlythis.Offeringscomefromlive`GET/v1/models`\nplustheCodewhalecatalogratherthanacompiledroster(#5350,#6289).\n\nKnown-goodhosts.Theseshipasbundleddescriptorrowsin\n`crates/config/assets/provider_descriptors.json`(compiledinby\n`crates/config/src/descriptors.rs`):eachrowsayshowtoreachthehost—wire,\nbaseURL,keyenv,aliases—whilemodelidsstaylivefrom`GET/v1/models`\nandtheCodewhalecatalog;theexamplemodelisonlyabootstraphint.Verify\nagainstthevendor'sowndocsbeforetrustinganyvaluehere:\n\n|Host|BaseURL|Examplemodels|APIkeyenv|\n|---|---|---|---|\n|SenseNova|`https://token.sensenova.cn/v1`|`deepseek-v4-flash`|`SENSENOVA_API_KEY`|\n|Baseten|`https://inference.baseten.co/v1`|`deepseek-ai/DeepSeek-V4-Pro`|`BASETEN_API_KEY`|\n|Groq|`https://api.groq.com/openai/v1`|`llama-3.3-70b-versatile`|`GROQ_API_KEY`|\n|Cerebras|`https://api.cerebras.ai/v1`|`llama-3.3-70b`|`CEREBRAS_API_KEY`|\n|CommandCode|`https://api.commandcode.ai/provider/v1`|`deepseek/deepseek-v4-flash`|`COMMAND_CODE_API_KEY`|\n|AlibabaModelStudio(DashScope)|`https://dashscope-intl.aliyuncs.com/compatible-mode/v1`|`qwen3.8-flash`|`DASHSCOPE_API_KEY`|\n|AICraft|`https://aicraftapi.com/v1`|`claude-4.6-sonnet`;DeepSeek/Claude/Gemini/Qwen/GLM/MiniMax/Doubaofamilies|`AICRAFT_API_KEY`|\n|Tsubasa|`https://api.tsubasa.sh/v1`|`tsubasa-pro`,`tsubasa-fast`(32,768-tokencontext)|`TSUBASA_API_KEY`|\n|CheaperInference|`https://api.cheaperinference.com/v1`|`gpt-5.4-mini`,`claude-sonnet-5`,`gemini-3.1-pro`|`CHEAPER_INFERENCE_API_KEY`|\n|Yolo-Auto|`https://yolo-auto.com/v1`|`qwen3.8-flash`;`yolo`/`yolo-small`|`YOLO_AUTO_API_KEY`|\n|StandardCompute|`https://api.stdcmpt.com/v1`|`standardcompute`(router);`deepseek/deepseek-v4-pro`,`anthropic/claude-sonnet-5.5`|`STANDARDCOMPUTE_API_KEY`|\n\nAICraft'srosterspansDeepSeek,AnthropicClaude,GoogleGemini,Qwen,GLM,\nMiniMaxandDoubaoidsonitsOpenAI-compatibleendpoint.Theauthorityis\n`GEThttps://aicraftapi.com/v1/models`withyourkey—pickamodelfromthat\nlist,notfromthistable.\nTsubasaimplementsonly`GET/v1/models`andChatCompletions.Itstwopublic\nmodelidssharea32,768-tokencontext,smallerthanthe128,000tokensCodewhaleassumes\nforanunknownmodel,sosetitontherouteaftersaving:\n`codewhaleconfigsetproviders.tsubasa.context_window32768`.\n\nCheaperInferenceisanOpenAI-compatiblegatewaywithonekeyformodelsfrom\nseverallabs.Modelidsarebare,sucLine truncated
"content":"# Provider Registry\n\n> 阅读简体中文版:[zh_hans/PROVIDERS.md](zh_hans/PROVIDERS.md)\n\nSpeech recognition, synthesis, translation and video have separate execution\npaths. See [media models](MEDIA_MODELS.md) for current support and reviewed\nupstream candidates; a chat catalogue row alone does not add a media backend.\n\nThis registry describes provider behavior that is wired into the current\nCodewhale codebase. It is intentionally conservative: shipped entries are\nlimited to provider IDs, config keys, auth paths, base URLs, model resolution,\nand capability metadata that the code already knows about.\n\nThe `/provider` and `/model` pickers recommend OrcaRouter as a partner option.\nClick the recommendation or press F7 to view the Codewhale × OrcaRouter offer:\na **30% top-up match for DeepSeek V4.1 Flash**. The pager includes the\n[redemption link](https://www.orcarouter.ai/redeem/1a6250545fdc4e0aaccb0a4470159e67)\nand can copy its text. Codewhale earns a referral fee from OrcaRouter.\nCurrent eligibility and terms are owned by the linked offer page. Viewing it\npreserves the current provider, model and credentials; redemption happens on\nOrcaRouter's site.\n\nDeepSeek remains the default provider, but every entry in `ProviderKind::ALL`\nis a first-class selectable provider route. `ALL` is the catalog/picker\nsurface — one identity per vendor. Dual-wire dialect kinds (`*Anthropic`, e.g.\n`deepseek-anthropic`) and the Model Studio plan variants stay on the enum for\nserde and `provider_for_kind` but are deliberately **not** catalog rows:\na plan is `mode`/`base_url` and a dialect is `wire = openai|anthropic` on the\nprimary provider config (`crates/config/src/provider_kind.rs:221-226`). Hosted\nroutes, generic OpenAI-compatible endpoints, the OpenAI Codex/ChatGPT route,\nnative Anthropic, and local runtimes all run the same terminal harness against\nthe selected provider/model/base URL.\n\nA host reached over plain Chat Completions is an ordinary named provider,\nnot a `ProviderKind`: enum variants are reserved for distinct *wires*\n(Anthropic Messages, Codex Responses, Google thought signatures). Any such\nhost is a `[providers.<name>]` table with a base URL, a model, and a key env\n(`docs/CONFIGURATION.md`); `/provider` and `/setup` keep a \"paste a Base URL\nand a key\"pathforexactlythis.Offeringscomefromlive`GET/v1/models`\nplustheCodewhalecatalogratherthanacompiledroster(#5350,#6289).\n\nKnown-goodhosts.Theseshipasbundleddescriptorrowsin\n`crates/config/assets/provider_descriptors.json`(compiledinby\n`crates/config/src/descriptors.rs`):eachrowsayshowtoreachthehost—wire,\nbaseURL,keyenv,aliases—whilemodelidsstaylivefrom`GET/v1/models`\nandtheCodewhalecatalog;theexamplemodelisonlyabootstraphint.Verify\nagainstthevendor'sowndocsbeforetrustinganyvaluehere:\n\n|Host|BaseURL|Examplemodels|APIkeyenv|\n|---|---|---|---|\n|SenseNova|`https://token.sensenova.cn/v1`|`deepseek-v4-flash`|`SENSENOVA_API_KEY`|\n|Baseten|`https://inference.baseten.co/v1`|`deepseek-ai/DeepSeek-V4-Pro`|`BASETEN_API_KEY`|\n|Groq|`https://api.groq.com/openai/v1`|`llama-3.3-70b-versatile`|`GROQ_API_KEY`|\n|Cerebras|`https://api.cerebras.ai/v1`|`llama-3.3-70b`|`CEREBRAS_API_KEY`|\n|CommandCode|`https://api.commandcode.ai/provider/v1`|`deepseek/deepseek-v4-flash`|`COMMAND_CODE_API_KEY`|\n|AlibabaModelStudio(DashScope)|`https://dashscope-intl.aliyuncs.com/compatible-mode/v1`|`qwen3.8-flash`|`DASHSCOPE_API_KEY`|\n|AICraft|`https://aicraftapi.com/v1`|`claude-4.6-sonnet`;DeepSeek/Claude/Gemini/Qwen/GLM/MiniMax/Doubaofamilies|`AICRAFT_API_KEY`|\n|Tsubasa|`https://api.tsubasa.sh/v1`|`tsubasa-pro`,`tsubasa-fast`(32,768-tokencontext)|`TSUBASA_API_KEY`|\n|CheaperInference|`https://api.cheaperinference.com/v1`|`gpt-5.4-mini`,`claude-sonnet-5`,`gemini-3.1-pro`|`CHEAPER_INFERENCE_API_KEY`|\n|Yolo-Auto|`https://yolo-auto.com/v1`|`qwen3.8-flash`;`yolo`/`yolo-small`|`YOLO_AUTO_API_KEY`|\n|StandardCompute|`https://api.stdcmpt.com/v1`|`standardcompute`(router);`deepseek/deepseek-v4-pro`,`anthropic/claude-sonnet-5.5`|`STANDARDCOMPUTE_API_KEY`|\n\nAICraft'srosterspansDeepSeek,AnthropicClaude,GoogleGemini,Qwen,GLM,\nMiniMaxandDoubaoidsonitsOpenAI-compatibleendpoint.Theauthorityis\n`GEThttps://aicraftapi.com/v1/models`withyourkey—pickamodelfromthat\nlist,notfromthistable.\nTsubasaimplementsonly`GET/v1/models`andChatCompletions.Itstwopublic\nmodelidssharea32,768-tokencontext,smallerthanthe128,000tokensCodewhaleassumes\nforanunknownmodel,sosetitontherouteaftersaving:\n`codewhaleconfigsetproviders.tsubasa.context_window32768`.\n\nCheaperInferenceisanOpenAI-compatiblegatewaywithonekeyformodelsfrom\nseverallabs.Modelidsarebare,sucLine truncated
"content":"# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. Instruction files written for other tools (`CLAUDE.md`,\n `.claude/instructions.md`, `.cursorrules`, `.github/copilot-instructions.md`\n and similar) are read only when you opt in with the top-level\n `project_instruction_imports` key, for example `[\"claude\"]`, `[\"cursor\"]` or\n `[\"all\"]`(see`config.example.toml`);Codewhalewarnswhenitfindsoneit\ndidnotload.\n\nCodewhalereadsoneinstructionfileperdirectory,fromtherepository\nrootdowntotheworkspace,andputsyourglobalinstructionfile(suchas\n`~/.codewhale/AGENTS.md`)infrontofthem.Thenearestscopereadslast\nandwins:theworkspacefileoverridesitsparents,andprojectfiles\noverridetheglobalfile.Globalandprojectinstructionsarebudgeted\nseparatelyinestimatedtokens(see[Instructionbudget](#instruction-budget-instruction_budget-6526)\nbelow):ascopeoveritsbudgetdropswholefilesfromthebroadestend\nfirst,andasinglefilelargerthantheremainingbudgetkeepsitshead\nwithamarkerthatnamesthebytesandtokensdropped.Afilekeepsatmost\nitsfirst100KiB,andafilelargerthan`file_max_bytesLine truncated
"content":"# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. Instruction files written for other tools (`CLAUDE.md`,\n `.claude/instructions.md`, `.cursorrules`, `.github/copilot-instructions.md`\n and similar) are read only when you opt in with the top-level\n `project_instruction_imports` key, for example `[\"claude\"]`, `[\"cursor\"]` or\n `[\"all\"]`(see`config.example.toml`);Codewhalewarnswhenitfindsoneit\ndidnotload.\n\nCodewhalereadsoneinstructionfileperdirectory,fromtherepository\nrootdowntotheworkspace,andputsyourglobalinstructionfile(suchas\n`~/.codewhale/AGENTS.md`)infrontofthem.Thenearestscopereadslast\nandwins:theworkspacefileoverridesitsparents,andprojectfiles\noverridetheglobalfile.Globalandprojectinstructionsarebudgeted\nseparatelyinestimatedtokens(see[Instructionbudget](#instruction-budget-instruction_budget-6526)\nbelow):ascopeoveritsbudgetdropswholefilesfromthebroadestend\nfirst,andasinglefilelargerthantheremainingbudgetkeepsitshead\nwithamarkerthatnamesthebytesandtokensdropped.Afilekeepsatmost\nitsfirst100KiB,andafilelargerthan`file_max_bytesLine truncated
"content":"# Legacy `.deepseek/` compatibility paths — audit & migration status (#3068)\n\n> 阅读简体中文版:[zh_hans/LEGACY_PATHS.md](zh_hans/LEGACY_PATHS.md)。\n\n## v0.9.10 cleanse ledger\n\nThis is the release-window decision record for residue that can otherwise look\ninterchangeable in a text search. A compatibility entry must name the contract\nthat still requires it; new production code must use a current path.\n\n| Class | Surface | Decision / contract |\n|---|---|---|\n| DELETE | Retired underwater build-version test override | Removed in `1cc4d1d1b`; the owner test was already deleted and the production-only build version remains authoritative. |\n| MIGRATE | Cross-task Agent Mail | `bd998495a` and managed-app `4ff7bc50d` replace guessed event aliases and same-session mailbox conflation with one durable typed runtime protocol. |\n| MIGRATE | TUI `status_message` writes | Active residue; touched flows must move to the typed toast/current-state owner. No new writes are allowed. |\n| COMPATIBILITY | `.deepseek/` state and stored provider aliases | Read fallback for upgraded installations and stored provider identity; writes remain Codewhale-only. Details are below. |\n| COMPATIBILITY | `agent_message` transcript/protocol decoding | Persisted transcripts and tool wire values require decoding; it is not the cross-task Agent Mail transport. |\n| COMPATIBILITY | Managed runtime envelope schema 1 | Previously persisted/enrolled runner replay; current local Codewhale Agent Mail producer is schema 2 and both normalize to the managed envelope. |\n| CURRENT | DeepSeek provider support | A real selectable provider, not product branding; provider-scoped names and configuration remain. |\n| CURRENT | Same-session subagent mailbox | Start/status/peek/message/followup/interrupt/wait/cancel stays scoped to a parent runtime session. |\n| CURRENT | Web locale dictionaries | The application and documentation routes have no page-local `isZh` branches; new copy continues through dictionaries. |\n| CURRENT | Safety, authorization, protocol, persistence, migration, and data-integrity tests | These protect external or durable contracts and are not copy/layout cleanup candidates. |\n\nSnapshot on 2026-08-19: `10,954` Rust `#[test]` attributes under\n`crates/tui`, `523` TUI `status_message` source lines, and zero page-local\n`isZh` files under `apps/web/app` in the paired managed-app candidate. Counts\nare inventory signals, not deletion targets.\n\nCodewhale was renamed from DeepSeek-TUI. To avoid breaking existing installs, the runtime reads\nstate from the new `~/.codewhale/` location but **falls back** to the legacy `~/.deepseek/` location,\nand always **writes** to `~/.codewhale/`. This doc audits each legacy reference and records a\nkeep / deprecate / remove decision so the migration is auditable.\n\n## The canonical resolver (use this for new code)\n\nState-dir resolution is consolidated in `crates/config/src/lib.rs`:\n\n| Symbol | Line | Purpose |\n|---|---|---|\n| `CODEWHALE_APP_DIR` / `LEGACY_APP_DIR` | 5369 | re-exported from `crates/paths` (defined at `crates/paths/src/lib.rs` 13 / 16) |\n| `codewhale_home()` | 5375 | `~/.codewhale` |\n| `legacy_deepseek_home()` | 5392 | `~/.deepseek` (legacy) |\n| `resolve_state_dir(subdir)` | 5434 | **read** path: `~/.codewhale/<subdir>`, falling back to `~/.deepseek/<subdir>` when only the legacy dir exists |\n| `ensure_state_dir(subdir)` | 5458 | **write** path: always creates under `~/.codewhale/<subdir>` |\n\nMigration contract: read-with-fallback, write-to-new. This preserves the v0.8.44 migration for\nusers who still have `~/.deepseek/` while steering all new writes to `~/.codewhale/`.\n\n## Per-path decisions\n\n**Decision for all legacy references below: keep-as-fallback.** Removing the `.deepseek` fallback\nwould strand users who upgraded in place and never re-ran onboarding. Revisit only after a release\nthat actively migrates `~/.deepseek/` → `~/.codewhale/` on first run and a deprecation window.\n\n| Reference | Routed through `resolve_state_dir`? | Decision |\n|---|---|---|\n| `config::resolve_state_dir` / `ensure_state_dir` | n/a (the resolver itself) | keep — canonical |\n| `crates/tui/src/skills/mod.rs` (`~/.deepseek/skills`) | no — hardcoded | keep-as-fallback; route through resolver in a follow-up refactor |\n| `crates/tui/src/prompts.rs` (`LEGACY_HANDOFF_RELATIVE_PATH = \".deepseek/handoff.md\"`)|no—explicitlegacyconst|keep—explicitlegacyhandofffallback|\n|`crates/tui/src/workspace_trust.rs`|no—hardcoded|keep-as-fallback;follow-up|\n|`crates/tui/src/session_manager.rs`|no—hardcoded|keep-as-fallback;follow-up|\n|`crates/runtime/src/skill_state.rs`|no—hardcoded|keep-as-fallback;follow-up|\n|`crates/tui/src/tools/skill.rs`|no—hardcoded|keep-as-fallback;follow-up|\n|`crates/tui/src/snapshot/mod.rs`|no—hardcoded|keep-as-fallback;follow-up|\n|`crates/runtime/src/woLine truncated
"content":"# Legacy `.deepseek/` compatibility paths — audit & migration status (#3068)\n\n> 阅读简体中文版:[zh_hans/LEGACY_PATHS.md](zh_hans/LEGACY_PATHS.md)。\n\n## v0.9.10 cleanse ledger\n\nThis is the release-window decision record for residue that can otherwise look\ninterchangeable in a text search. A compatibility entry must name the contract\nthat still requires it; new production code must use a current path.\n\n| Class | Surface | Decision / contract |\n|---|---|---|\n| DELETE | Retired underwater build-version test override | Removed in `1cc4d1d1b`; the owner test was already deleted and the production-only build version remains authoritative. |\n| MIGRATE | Cross-task Agent Mail | `bd998495a` and managed-app `4ff7bc50d` replace guessed event aliases and same-session mailbox conflation with one durable typed runtime protocol. |\n| MIGRATE | TUI `status_message` writes | Active residue; touched flows must move to the typed toast/current-state owner. No new writes are allowed. |\n| COMPATIBILITY | `.deepseek/` state and stored provider aliases | Read fallback for upgraded installations and stored provider identity; writes remain Codewhale-only. Details are below. |\n| COMPATIBILITY | `agent_message` transcript/protocol decoding | Persisted transcripts and tool wire values require decoding; it is not the cross-task Agent Mail transport. |\n| COMPATIBILITY | Managed runtime envelope schema 1 | Previously persisted/enrolled runner replay; current local Codewhale Agent Mail producer is schema 2 and both normalize to the managed envelope. |\n| CURRENT | DeepSeek provider support | A real selectable provider, not product branding; provider-scoped names and configuration remain. |\n| CURRENT | Same-session subagent mailbox | Start/status/peek/message/followup/interrupt/wait/cancel stays scoped to a parent runtime session. |\n| CURRENT | Web locale dictionaries | The application and documentation routes have no page-local `isZh` branches; new copy continues through dictionaries. |\n| CURRENT | Safety, authorization, protocol, persistence, migration, and data-integrity tests | These protect external or durable contracts and are not copy/layout cleanup candidates. |\n\nSnapshot on 2026-08-19: `10,954` Rust `#[test]` attributes under\n`crates/tui`, `523` TUI `status_message` source lines, and zero page-local\n`isZh` files under `apps/web/app` in the paired managed-app candidate. Counts\nare inventory signals, not deletion targets.\n\nCodewhale was renamed from DeepSeek-TUI. To avoid breaking existing installs, the runtime reads\nstate from the new `~/.codewhale/` location but **falls back** to the legacy `~/.deepseek/` location,\nand always **writes** to `~/.codewhale/`. This doc audits each legacy reference and records a\nkeep / deprecate / remove decision so the migration is auditable.\n\n## The canonical resolver (use this for new code)\n\nState-dir resolution is consolidated in `crates/config/src/lib.rs`:\n\n| Symbol | Line | Purpose |\n|---|---|---|\n| `CODEWHALE_APP_DIR` / `LEGACY_APP_DIR` | 5369 | re-exported from `crates/paths` (defined at `crates/paths/src/lib.rs` 13 / 16) |\n| `codewhale_home()` | 5375 | `~/.codewhale` |\n| `legacy_deepseek_home()` | 5392 | `~/.deepseek` (legacy) |\n| `resolve_state_dir(subdir)` | 5434 | **read** path: `~/.codewhale/<subdir>`, falling back to `~/.deepseek/<subdir>` when only the legacy dir exists |\n| `ensure_state_dir(subdir)` | 5458 | **write** path: always creates under `~/.codewhale/<subdir>` |\n\nMigration contract: read-with-fallback, write-to-new. This preserves the v0.8.44 migration for\nusers who still have `~/.deepseek/` while steering all new writes to `~/.codewhale/`.\n\n## Per-path decisions\n\n**Decision for all legacy references below: keep-as-fallback.** Removing the `.deepseek` fallback\nwould strand users who upgraded in place and never re-ran onboarding. Revisit only after a release\nthat actively migrates `~/.deepseek/` → `~/.codewhale/` on first run and a deprecation window.\n\n| Reference | Routed through `resolve_state_dir`? | Decision |\n|---|---|---|\n| `config::resolve_state_dir` / `ensure_state_dir` | n/a (the resolver itself) | keep — canonical |\n| `crates/tui/src/skills/mod.rs` (`~/.deepseek/skills`) | no — hardcoded | keep-as-fallback; route through resolver in a follow-up refactor |\n| `crates/tui/src/prompts.rs` (`LEGACY_HANDOFF_RELATIVE_PATH = \".deepseek/handoff.md\"`)|no—explicitlegacyconst|keep—explicitlegacyhandofffallback|\n|`crates/tui/src/workspace_trust.rs`|no—hardcoded|keep-as-fallback;follow-up|\n|`crates/tui/src/session_manager.rs`|no—hardcoded|keep-as-fallback;follow-up|\n|`crates/runtime/src/skill_state.rs`|no—hardcoded|keep-as-fallback;follow-up|\n|`crates/tui/src/tools/skill.rs`|no—hardcoded|keep-as-fallback;follow-up|\n|`crates/snapshot/src/lib.rs`|no—hardcoded|keep-as-fallback;follow-up|\n|`crates/runtime/src/workspLine truncated
"content":"# Modes and Permission Postures\n\n> 阅读简体中文版:[zh_hans/MODES.md](zh_hans/MODES.md)\n\nCodewhale has three related concepts:\n\n- **TUI mode**: what kind of visible interaction you're in (Plan/Work/Operate).\n- **Permission posture**: how aggressively the UI asks before executing tools.\n- **Workflow**: named steps that coordinate sub-agents, with dependencies and\n results, available in any TUI mode.\n\nModel selection is separate. `--model auto` and `/model auto` route each turn to\na concrete model and thinking level; they are not TUI modes and are not part of\nthe `Tab` cycle.\n\nWorkflow runs named steps through the same sub-agent runtime; Fleet manages\ntheir saved roles and model assignments. A workflow adds ordering, result\nhandoffs, gates and a progress view. The active mode and permission posture\nstill control what each step may execute.\n\nBefore assigning steps, query `agent(action=\"roster\")` for the saved Fleet\nmodels and roles. A plan child can select a listed model with `model`, or use\nthe saved `role`/`profile` assignment. An Exact Fleet fixes each member's route.\n\n## TUI Modes\n\nPress `Tab` to complete composer menus or cycle through the visible modes\nwhen the composer is empty: **Plan → Work → Operate → Plan**. `Tab` never sends\nor queues composer text; use `Enter` to send or queue it.\nPress `Shift+Tab` to cycle permission posture (Ask → Auto-Review → Full Access).\nEvery change of effective permission writes a `Permissions changed to …` line\nin the transcript.\nPress `Ctrl+T` to cycle reasoning effort.\nRun `/mode` to open the mode picker, or switch directly with `/mode work`,\n`/mode plan`, or `/mode operate`.\n\n- **Plan**: design-first prompting. The stable primitive names remain familiar, but the runtime centrally refuses file mutation and shell execution. Read-only inspection and policy-allowed research, including deferred Web search/fetch, remain available. When a Plan turn successfully finishes a nonempty response, including a prose-only plan, the TUI asks how to continue: Work (Ask), Work (Auto-Review), or keep planning. Work sends the exact approved response as a normal follow-up and preserves that turn's existing To-dos, or adds one pending plan item without replacing unrelated work.\n- **Work** (internally `agent`): ordinary multi-step execution. The first-turn toolbox includes `read`, `write`, `edit`, `file_search`, `bash`, `agent`, `workflow`, `todo_write`, and `load_skill`, plus `create_goal`, `get_goal`, `update_goal`, and `task_shell_wait` so goal and background-shell controls are available without discovery. The agent calls `create_goal` when a request is a durable objective; the host never infers a goal from wording, and the contract must not tell the model otherwise. Approval, sandbox, repository law, and managed policy decide what may execute.\n- **Operate**: Work at full strength, the \"ultra\"mode.SametoolsandauthorityasWork;thedifferenceishowtheyareused.Eachsubstantiverequestbecomesagoal(`create_goal`),theplanstaysvisible(`todo_write`),multi-partworkrunsthrough`workflow`andparallel`agent`workers,non-trivialchangesgetanindependentreviewerbeforetheyarecalleddone,longcommandskeeprunninginthebackground,andrecurringorwatch-typeworkisofferedasan`automation`(createdafterapproval).Itkeepsgoinguntilthegoalisverified,blockedonyou,orpaused.\n\n`Act`and`/modeact`remaincompatibilityaliasesforWork.Savedsettings\nstillnormalizetotheinternalvalue`agent`.\n\n###Toolavailabilitybymode\n\n|Toolfamily|Plan|Work|Operate|\n|:---|:---:|:---:|:---:|\n|`read`andpolicy-alloweddeferredresearchtools|yes|yes|yes|\n|`write`and`edit`|visiblenames;executiondenied|approval-andpolicy-gated|sameasWork|\n|`bash`|visiblename;executiondenied|approval-andpolicy-gated|sameasWork;delegationispreferredwhenparallelismorisolationhelps|\n|`agent`|yes,subjecttochild-depthauthority|yes,subjecttochild-depthauthority|yes,subjecttochild-depthauthority|\n|Deferrednative,MCP,andplugintools|discoverablethrough`tool_search`whenpolicypermits|same|same|\n|Paidorexternal-servicetools|followspermissionposture|followspermissionposture|followspermissionposture|\n|Accessoutsidetheworkspaceroot|explicittrustedpathsonly|onlythroughtrustedpathsortrustmode|sametrusted-path/trustpolicyasWork;fleetprofilesneverwidenit|\n\nOperatechangesschedulingemphasis,notauthority.Itneitheraddsa\nmode-specifictooldenialnorbypassestheactiveapproval,sandbox,shell,\nask-rule,repository-law,ormanaged-policyboundary.Planremainsthe\nmode-specificexecutionboundaryforshellandwrite-capabletools;that\nauthoritydifferencedoesnotrequireadifferentprimitivevocabulary.\n\n###Operateloop(onescreen)\n\n```text\nUserLine truncated
"content":"# Modes and Permission Postures\n\n> 阅读简体中文版:[zh_hans/MODES.md](zh_hans/MODES.md)\n\nCodewhale has three related concepts:\n\n- **TUI mode**: what kind of visible interaction you're in (Plan/Work/Operate).\n- **Permission posture**: how aggressively the UI asks before executing tools.\n- **Workflow**: named steps that coordinate sub-agents, with dependencies and\n results, available in any TUI mode.\n\nModel selection is separate. `--model auto` and `/model auto` route each turn to\na concrete model and thinking level; they are not TUI modes and are not part of\nthe `Tab` cycle.\n\nWorkflow runs named steps through the same sub-agent runtime; Fleet manages\ntheir saved roles and model assignments. A workflow adds ordering, result\nhandoffs, gates and a progress view. The active mode and permission posture\nstill control what each step may execute.\n\nBefore assigning steps, query `agent(action=\"roster\")` for the saved Fleet\nmodels and roles. A plan child can select a listed model with `model`, or use\nthe saved `role`/`profile` assignment. An Exact Fleet fixes each member's route.\n\n## TUI Modes\n\nPress `Tab` to complete composer menus or cycle through the visible modes\nwhen the composer is empty: **Plan → Work → Operate → Plan**. `Tab` never sends\nor queues composer text; use `Enter` to send or queue it.\nPress `Shift+Tab` to cycle permission posture (Ask → Auto-Review → Full Access).\nEvery change of effective permission writes a `Permissions changed to …` line\nin the transcript.\nPress `Ctrl+T` to cycle reasoning effort.\nRun `/mode` to open the mode picker, or switch directly with `/mode work`,\n`/mode plan`, or `/mode operate`.\n\n- **Plan**: design-first prompting. The stable primitive names remain familiar, but the runtime centrally refuses file mutation and shell execution. Read-only inspection and policy-allowed research, including deferred Web search/fetch, remain available. When a Plan turn successfully finishes a nonempty response, including a prose-only plan, the TUI asks how to continue: Work (Ask), Work (Auto-Review), or keep planning. Work sends the exact approved response as a normal follow-up and preserves that turn's existing To-dos, or adds one pending plan item without replacing unrelated work.\n- **Work** (internally `agent`): ordinary multi-step execution. The first-turn toolbox includes `read`, `write`, `edit`, `file_search`, `bash`, `agent`, `workflow`, `todo_write`, and `load_skill`, plus `create_goal`, `get_goal`, `update_goal`, and `task_shell_wait` so goal and background-shell controls are available without discovery. The agent calls `create_goal` when a request is a durable objective; the host never infers a goal from wording, and the contract must not tell the model otherwise. Approval, sandbox, repository law, and managed policy decide what may execute.\n- **Operate**: Work at full strength, the \"ultra\"mode.SametoolsandauthorityasWork;thedifferenceishowtheyareused.Eachsubstantiverequestbecomesagoal(`create_goal`),theplanstaysvisible(`todo_write`),multi-partworkrunsthrough`workflow`andparallel`agent`workers,non-trivialchangesgetanindependentreviewerbeforetheyarecalleddone,longcommandskeeprunninginthebackground,andrecurringorwatch-typeworkisofferedasan`automation`(createdafterapproval).Itkeepsgoinguntilthegoalisverified,blockedonyou,orpaused.\n\n`Act`and`/modeact`remaincompatibilityaliasesforWork.Savedsettings\nstillnormalizetotheinternalvalue`agent`.\n\n###Toolavailabilitybymode\n\n|Toolfamily|Plan|Work|Operate|\n|:---|:---:|:---:|:---:|\n|`read`andpolicy-alloweddeferredresearchtools|yes|yes|yes|\n|`write`and`edit`|visiblenames;executiondenied|approval-andpolicy-gated|sameasWork|\n|`bash`|visiblename;executiondenied|approval-andpolicy-gated|sameasWork;delegationispreferredwhenparallelismorisolationhelps|\n|`agent`|yes,subjecttochild-depthauthority|yes,subjecttochild-depthauthority|yes,subjecttochild-depthauthority|\n|Deferrednative,MCP,andplugintools|discoverablethrough`tool_search`whenpolicypermits|same|same|\n|Paidorexternal-servicetools|followspermissionposture|followspermissionposture|followspermissionposture|\n|Accessoutsidetheworkspaceroot|explicittrustedpathsonly|onlythroughtrustedpathsortrustmode|sametrusted-path/trustpolicyasWork;fleetprofilesneverwidenit|\n\nOperatechangesschedulingemphasis,notauthority.Itneitheraddsa\nmode-specifictooldenialnorbypassestheactiveapproval,sandbox,shell,\nask-rule,repository-law,ormanaged-policyboundary.Planremainsthe\nmode-specificexecutionboundaryforshellandwrite-capabletools;that\nauthoritydifferencedoesnotrequireadifferentprimitivevocabulary.\n\n###Operateloop(onescreen)\n\n```text\nUserLine truncated
"content":"# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. Instruction files written for other tools (`CLAUDE.md`,\n `.claude/instructions.md`, `.cursorrules`, `.github/copilot-instructions.md`\n and similar) are read only when you opt in with the top-level\n `project_instruction_imports` key, for example `[\"claude\"]`, `[\"cursor\"]` or\n `[\"all\"]`(see`config.example.toml`);Codewhalewarnswhenitfindsoneit\ndidnotload.\n\nCodewhalereadsoneinstructionfileperdirectory,fromtherepository\nrootdowntotheworkspace,andputsyourglobalinstructionfile(suchas\n`~/.codewhale/AGENTS.md`)infrontofthem.Thenearestscopereadslast\nandwins:theworkspacefileoverridesitsparents,andprojectfiles\noverridetheglobalfile.Globalandprojectinstructionsarebudgeted\nseparatelyinestimatedtokens(see[Instructionbudget](#instruction-budget-instruction_budget-6526)\nbelow):ascopeoveritsbudgetdropswholefilesfromthebroadestend\nfirst,andasinglefilelargerthantheremainingbudgetkeepsitshead\nwithamarkerthatnamesthebytesandtokensdropped.Afilekeepsatmost\nitsfirst100KiB,andafilelargerthan`file_max_bytesLine truncated
"content":"# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. Instruction files written for other tools (`CLAUDE.md`,\n `.claude/instructions.md`, `.cursorrules`, `.github/copilot-instructions.md`\n and similar) are read only when you opt in with the top-level\n `project_instruction_imports` key, for example `[\"claude\"]`, `[\"cursor\"]` or\n `[\"all\"]`(see`config.example.toml`);Codewhalewarnswhenitfindsoneit\ndidnotload.\n\nCodewhalereadsoneinstructionfileperdirectory,fromtherepository\nrootdowntotheworkspace,andputsyourglobalinstructionfile(suchas\n`~/.codewhale/AGENTS.md`)infrontofthem.Thenearestscopereadslast\nandwins:theworkspacefileoverridesitsparents,andprojectfiles\noverridetheglobalfile.Globalandprojectinstructionsarebudgeted\nseparatelyinestimatedtokens(see[Instructionbudget](#instruction-budget-instruction_budget-6526)\nbelow):ascopeoveritsbudgetdropswholefilesfromthebroadestend\nfirst,andasinglefilelargerthantheremainingbudgetkeepsitshead\nwithamarkerthatnamesthebytesandtokensdropped.Afilekeepsatmost\nitsfirst100KiB,andafilelargerthan`file_max_bytesLine truncated
"content":"# Codewhale product telemetry\n\n> 阅读简体中文版:[zh_hans/TELEMETRY.md](zh_hans/TELEMETRY.md)\n\n**Usage analytics are on by default in the current source.** The first\ninteractive launch gives a localized, nonblocking disclosure naming **Codewhale\nand PostHog**, with a direct route to turn counting off. Notice version `5`\ndescribes this policy; displaying it is not recorded as human acceptance.\nMissing an older acceptance record does not turn a fresh installation off.\nExisting explicit opt-outs remain off across upgrades, and unreadable privacy\nstate fails closed. Environment and CLI kill switches still take precedence.\n\nRead the disclosure with `codewhale config telemetry`. Turn usage off in\n`/settings` or run `codewhale config set telemetry false`. Turning it back on\nin Settings or with `codewhale config set telemetry true` updates the existing\ndurable preference and privacy records for new sessions. The compatibility\ncommand `codewhale config telemetry --accept-notice 5` remains available, but\nis not required for a fresh installation. Collection never includes work content or credentials.\n\nThe PostHog sink is optional and inert until the ingest operator explicitly\nconfigures a project token and approved regional host, and records staging\nproof that the actual egress path does not forward the original client IP.\nSource readiness does not establish a deployment, an activated processor,\nan egress receipt, or a retention setting.\n\nCodewhale does not collect conversations, code, prompts, files, file/repo/branch\nnames, model content, or credentials. It sends no per-turn or per-tool timeline.\nIt does send the closed, aggregate schema below: version and platform classes,\nsession duration/outcome, feature/error counters, and a random install id that\nrotates every 90 days.\n\n**There is now a real endpoint.** An enabled session sends its batches to the\nfirst-party ingest service at `https://telemetry.codewhale.net/v1/telemetry`,\nwhich is the shipped default for `telemetry_endpoint`. What that service is,\nwhat it stores, and what it structurally cannot store is spelled out in \"What\nthe endpoint does\" below.\n\n**To send nothing anywhere, turn telemetry off** (see \"Turning it off\"). To stay\nenabled but contact nobody, set `telemetry_endpoint = \"\"`:batchesarethen\nappendedto`$CODEWHALE_HOME/telemetry/dryrun.jsonl`onyourownmachine,byte\nforbytewhattheserverwouldhavereceived,andnoHTTPclientisever\nconstructed.Thatfileishowyouauditthisdocumentagainstreality.\n\nThisdocumentistheschema.Itisnotasummaryoftheschema:atestin\n`crates/telemetry`parsesthefieldnamesoutofthisfileandassertsset\nequalityagainstthestructstheserializeractuallyuses,soafieldthatis\nhereandnotinthecode—orinthecodeandnothere—failsthebuild.\n\nLocalsavedsessionsand`codewhalemetrics`remainavailablewithtelemetry\ndisabledandrequirenoaccountorhostedreportingservice.Disablingtelemetry\ndoesnotdisablelocalusagereceipts.\n\n##Turningitoff\n\nTherearetwooffswitchesandtheydodifferentthings.Bothstopcollection\ncompletely;onlyoneofthemerasesanything.\n\n```sh\ncodewhaleconfigsettelemetryfalse#optout:stopscollectionanderasesstate\nCODEWHALE_TELEMETRY=0codewhale#killswitch:stopscollection,erasesnothing\ncodewhale--telemetryfalse#thesamekillswitch,foronecommand\n```\n\n**`telemetry=false`intheconfigfileistheopt-out.**Itisafloor:\n`--telemetrytrue`and`CODEWHALE_TELEMETRY=1`bothlosetoit,becausea\nsettingyoucanundobyaccidentfromawrapperscriptisnotasetting.It\ndeletestherandominstallid,truncateseverybufferedeventandeverydry-run\nrecord,andwritesatombstone.Appends,identity/statewrites,anddeliveryall\nsharethewipe'sorderinglock,soonceopt-outreturnsnopre-opt-outwriteor\nPOSTremainsinflight.Ifanypartofthatwipefails,thetombstoneisstill\nthereandthebufferisundrainable—afailedwipefailsclosed.Everylater\nrunre-assertsthesametombstoneforaslongasthesettingstands,soit\nsurvives.Turningtelemetrybackonin`/settings`recordsthatexplicitpreference\ninbothexistingprivacyregisters;afreshlaunchcanthenclearthetombstone.Nothingbufferedbeforethatpointis\neversent.\n\n**Theenvironmentvariableandtheflagarekillswitches,notopt-outs.**\nTelemetryisofffortherun,nothingiswritten,nothingissent—and\nnothingondiskistouchedordeleted.Thatisdeliberate:aharnessoragent\nthatsets`CODEWHALE_TELEMETRY=0`foronecommandmustnotsilentlydiscardthe\ninstallidandthedry-runrecordsofthepersonwhoownsthemachine.Ifyou\nwanttheerasingkind,usetheconfigfile.\n\n`CODEWHALE_TELEMETRY`(andits`DEEPSEEK_TELEMETRY`alias)accepts\n`0`,`1`,`true`,`false`,`yes`,`no`,Line truncated
"content":"# Codewhale product telemetry\n\n> 阅读简体中文版:[zh_hans/TELEMETRY.md](zh_hans/TELEMETRY.md)\n\n**Usage analytics are on by default in the current source.** The first\ninteractive launch gives a localized, nonblocking disclosure naming **Codewhale\nand PostHog**, with a direct route to turn counting off. Notice version `5`\ndescribes this policy; displaying it is not recorded as human acceptance.\nMissing an older acceptance record does not turn a fresh installation off.\nExisting explicit opt-outs remain off across upgrades, and unreadable privacy\nstate fails closed. Environment and CLI kill switches still take precedence.\n\nRead the disclosure with `codewhale config telemetry`. Turn usage off in\n`/settings` or run `codewhale config set telemetry false`. Turning it back on\nin Settings or with `codewhale config set telemetry true` updates the existing\ndurable preference and privacy records for new sessions. The compatibility\ncommand `codewhale config telemetry --accept-notice 5` remains available, but\nis not required for a fresh installation. Collection never includes work content or credentials.\n\nThe PostHog sink is optional and inert until the ingest operator explicitly\nconfigures a project token and approved regional host, and records staging\nproof that the actual egress path does not forward the original client IP.\nSource readiness does not establish a deployment, an activated processor,\nan egress receipt, or a retention setting.\n\nCodewhale does not collect conversations, code, prompts, files, file/repo/branch\nnames, model content, or credentials. It sends no per-turn or per-tool timeline.\nIt does send the closed, aggregate schema below: version and platform classes,\nsession duration/outcome, feature/error counters, and a random install id that\nrotates every 90 days.\n\n**There is now a real endpoint.** An enabled session sends its batches to the\nfirst-party ingest service at `https://telemetry.codewhale.net/v1/telemetry`,\nwhich is the shipped default for `telemetry_endpoint`. What that service is,\nwhat it stores, and what it structurally cannot store is spelled out in \"What\nthe endpoint does\" below.\n\n**To send nothing anywhere, turn telemetry off** (see \"Turning it off\"). To stay\nenabled but contact nobody, set `telemetry_endpoint = \"\"`:batchesarethen\nappendedto`$CODEWHALE_HOME/telemetry/dryrun.jsonl`onyourownmachine,byte\nforbytewhattheserverwouldhavereceived,andnoHTTPclientisever\nconstructed.Thatfileishowyouauditthisdocumentagainstreality.\n\nThisdocumentistheschema.Itisnotasummaryoftheschema:atestin\n`crates/telemetry`parsesthefieldnamesoutofthisfileandassertsset\nequalityagainstthestructstheserializeractuallyuses,soafieldthatis\nhereandnotinthecode—orinthecodeandnothere—failsthebuild.\n\nLocalsavedsessionsand`codewhalemetrics`remainavailablewithtelemetry\ndisabledandrequirenoaccountorhostedreportingservice.Disablingtelemetry\ndoesnotdisablelocalusagereceipts.\n\n##Turningitoff\n\nTherearetwooffswitchesandtheydodifferentthings.Bothstopcollection\ncompletely;onlyoneofthemerasesanything.\n\n```sh\ncodewhaleconfigsettelemetryfalse#optout:stopscollectionanderasesstate\nCODEWHALE_TELEMETRY=0codewhale#killswitch:stopscollection,erasesnothing\ncodewhale--telemetryfalse#thesamekillswitch,foronecommand\n```\n\n**`telemetry=false`intheconfigfileistheopt-out.**Itisafloor:\n`--telemetrytrue`and`CODEWHALE_TELEMETRY=1`bothlosetoit,becausea\nsettingyoucanundobyaccidentfromawrapperscriptisnotasetting.It\ndeletestherandominstallid,truncateseverybufferedeventandeverydry-run\nrecord,andwritesatombstone.Appends,identity/statewrites,anddeliveryall\nsharethewipe'sorderinglock,soonceopt-outreturnsnopre-opt-outwriteor\nPOSTremainsinflight.Ifanypartofthatwipefails,thetombstoneisstill\nthereandthebufferisundrainable—afailedwipefailsclosed.Everylater\nrunre-assertsthesametombstoneforaslongasthesettingstands,soit\nsurvives.Turningtelemetrybackonin`/settings`recordsthatexplicitpreference\ninbothexistingprivacyregisters;afreshlaunchcanthenclearthetombstone.Nothingbufferedbeforethatpointis\neversent.\n\n**Theenvironmentvariableandtheflagarekillswitches,notopt-outs.**\nTelemetryisofffortherun,nothingiswritten,nothingissent—and\nnothingondiskistouchedordeleted.Thatisdeliberate:aharnessoragent\nthatsets`CODEWHALE_TELEMETRY=0`foronecommandmustnotsilentlydiscardthe\ninstallidandthedry-runrecordsofthepersonwhoownsthemachine.Ifyou\nwanttheerasingkind,usetheconfigfile.\n\n`CODEWHALE_TELEMETRY`(andits`DEEPSEEK_TELEMETRY`alias)accepts\n`0`,`1`,`true`,`false`,`yes`,`no`,Line truncated
"content":"# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. Instruction files written for other tools (`CLAUDE.md`,\n `.claude/instructions.md`, `.cursorrules`, `.github/copilot-instructions.md`\n and similar) are read only when you opt in with the top-level\n `project_instruction_imports` key, for example `[\"claude\"]`, `[\"cursor\"]` or\n `[\"all\"]`(see`config.example.toml`);Codewhalewarnswhenitfindsoneit\ndidnotload.\n\nCodewhalereadsoneinstructionfileperdirectory,fromtherepository\nrootdowntotheworkspace,andputsyourglobalinstructionfile(suchas\n`~/.codewhale/AGENTS.md`)infrontofthem.Thenearestscopereadslast\nandwins:theworkspacefileoverridesitsparents,andprojectfiles\noverridetheglobalfile.Globalandprojectinstructionsarebudgeted\nseparatelyinestimatedtokens(see[Instructionbudget](#instruction-budget-instruction_budget-6526)\nbelow):ascopeoveritsbudgetdropswholefilesfromthebroadestend\nfirst,andasinglefilelargerthantheremainingbudgetkeepsitshead\nwithamarkerthatnamesthebytesandtokensdropped.Afilekeepsatmost\nitsfirst100KiB,andafilelargerthan`file_max_bytesLine truncated
"content":"# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. Instruction files written for other tools (`CLAUDE.md`,\n `.claude/instructions.md`, `.cursorrules`, `.github/copilot-instructions.md`\n and similar) are read only when you opt in with the top-level\n `project_instruction_imports` key, for example `[\"claude\"]`, `[\"cursor\"]` or\n `[\"all\"]`(see`config.example.toml`);Codewhalewarnswhenitfindsoneit\ndidnotload.\n\nCodewhalereadsoneinstructionfileperdirectory,fromtherepository\nrootdowntotheworkspace,andputsyourglobalinstructionfile(suchas\n`~/.codewhale/AGENTS.md`)infrontofthem.Thenearestscopereadslast\nandwins:theworkspacefileoverridesitsparents,andprojectfiles\noverridetheglobalfile.Globalandprojectinstructionsarebudgeted\nseparatelyinestimatedtokens(see[Instructionbudget](#instruction-budget-instruction_budget-6526)\nbelow):ascopeoveritsbudgetdropswholefilesfromthebroadestend\nfirst,andasinglefilelargerthantheremainingbudgetkeepsitshead\nwithamarkerthatnamesthebytesandtokensdropped.Afilekeepsatmost\nitsfirst100KiB,andafilelargerthan`file_max_bytesLine truncated
"content":"# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. Instruction files written for other tools (`CLAUDE.md`,\n `.claude/instructions.md`, `.cursorrules`, `.github/copilot-instructions.md`\n and similar) are read only when you opt in with the top-level\n `project_instruction_imports` key, for example `[\"claude\"]`, `[\"cursor\"]` or\n `[\"all\"]`(see`config.example.toml`);Codewhalewarnswhenitfindsoneit\ndidnotload.\n\nCodewhalereadsoneinstructionfileperdirectory,fromtherepository\nrootdowntotheworkspace,andputsyourglobalinstructionfile(suchas\n`~/.codewhale/AGENTS.md`)infrontofthem.Thenearestscopereadslast\nandwins:theworkspacefileoverridesitsparents,andprojectfiles\noverridetheglobalfile.Globalandprojectinstructionsarebudgeted\nseparatelyinestimatedtokens(see[Instructionbudget](#instruction-budget-instruction_budget-6526)\nbelow):ascopeoveritsbudgetdropswholefilesfromthebroadestend\nfirst,andasinglefilelargerthantheremainingbudgetkeepsitshead\nwithamarkerthatnamesthebytesandtokensdropped.Afilekeepsatmost\nitsfirst100KiB,andafilelargerthan`file_max_bytesLine truncated
"content":"# Configuration\n\ncodewhale reads configuration from a TOML file plus environment variables.\nAt process startup it may also load literal built-in-provider credentials from\na workspace-local `.env` file. Use the tracked `.env.example` as the template;\ncopy it to `.env`, then add only credential values.\n\nA workspace is not configuration authority. Codewhale therefore ignores\nconfig/profile/home paths, provider/model/base-URL routing, MCP/plugin state,\napproval/sandbox/shell posture, executable paths, runtime settings, and every\nother non-credential `.env` entry. Variable expansion is rejected so a\nrepository cannot substitute an ambient secret into a credential value. Use\n`config.toml`, CLI flags, or values exported by the launching shell for those\nexplicit control-plane settings. `.env` is read from a stable regular-file\nhandle, is capped at 1 MiB, and symbolic links, reparse points, and multiply\nlinked files are rejected.\n\n## Reading and checking configuration from the CLI\n\n`codewhale config get <key>` reads scalar keys, whole tables such as `tools`,\nand nested paths such as `tools.user_input_timeout_seconds`. Displayed tables\nand nested values apply the same recursive credential redaction as `config dump`.\n\n`config set` supports its named scalar keys and the provider, route, and\nnotification commands. It refuses a key that nothing reads and suggests the\nnearest real key (`config set calm_mod on` names `calm_mode`). A settings.toml\nkey such as `calm_mode` or `tool_collapse` is validated and written to the\nuser-global settings.toml, not config.toml; `config get` reads it back from\nthere even when an old config.toml copy (which nothing reads) is still present,\nand names that copy so you can `config unset` it. Settings keys have no project\nscope, so `--project` refuses them. A config.toml key is checked against the\ntype its reader expects and stored as a TOML boolean or number where the\nreader needs one (`yolo = true`, `max_subagents = 4`); `reasoning_effort`\naccepts the same aliases as `/effort` (#6563). Other dotted writes fail before\nmodifying the file and name the TOML table to edit. For example, set a tools\ntimeout in the file as:\n\n```toml\n[tools]\nuser_input_timeout_seconds = 0\n```\n\n`codewhale config doctor` checks credential presence and endpoint shape, and\nwarns about each config.toml root key that nothing reads: a settings.toml key\nleft in config.toml is named as misplaced, and any other unread key gets a\ndid-you-mean. Keys read by any runtime reader are not reported. The warnings do\nnot fail the check, and a clean result does not validate every runtime setting's\nvalue (#6083, #6563).\n\n## Constitution, project instructions, and repo authority\n\nCodewhale has several instruction surfaces. They are deliberately separate so a\npersonal constitution, repo policy, project instructions, and runtime security\ncontrols do not blur together.\n\n- **Bundled global Constitution** — the compiled base law in the binary. It is\n the default floor for every session.\n- **User-global constitution** — the normal guided setup output. Manage it with\n `/constitution` or `/setup`; Codewhale stores structured data at\n `$CODEWHALE_HOME/constitution.json` (default `~/.codewhale/constitution.json`)\n and renders it into a separate `<codewhale_user_constitution>` prose block.\n This can express preferences and stop conditions, but it does not change\n runtime approval policy, sandbox, shell, network, trust, or MCP permissions.\n- **Repo-local constitution** — optional project policy in\n `.codewhale/constitution.json`, described below.\n- **`AGENTS.md`** — cross-agent **project instructions** (prose). This is the\n canonical file for \"how should an agent work in this repo.\" Run `/init` to\n scaffold one. Instruction files written for other tools (`CLAUDE.md`,\n `.claude/instructions.md`, `.cursorrules`, `.github/copilot-instructions.md`\n and similar) are read only when you opt in with the top-level\n `project_instruction_imports` key, for example `[\"claude\"]`, `[\"cursor\"]` or\n `[\"all\"]`(see`config.example.toml`);Codewhalewarnswhenitfindsoneit\ndidnotload.\n\nCodewhalereadsoneinstructionfileperdirectory,fromtherepository\nrootdowntotheworkspace,andputsyourglobalinstructionfile(suchas\n`~/.codewhale/AGENTS.md`)infrontofthem.Thenearestscopereadslast\nandwins:theworkspacefileoverridesitsparents,andprojectfiles\noverridetheglobalfile.Globalandprojectinstructionsarebudgeted\nseparatelyinestimatedtokens(see[Instructionbudget](#instruction-budget-instruction_budget-6526)\nbelow):ascopeoveritsbudgetdropswholefilesfromthebroadestend\nfirst,andasinglefilelargerthantheremainingbudgetkeepsitshead\nwithamarkerthatnamesthebytesandtokensdropped.Afilekeepsatmost\nitsfirst100KiB,andafilelargerthan`file_max_bytesLine truncated
"content":"# Writing an extension tool or command\n\nThe experimental TypeScript extension host runs reviewed plugin code in a\nshared Node process (or, as an opt-in, Bun). Rust still owns sessions, tool admission, approval and\nexecution. Extensions currently contribute tools and slash commands; they\ncannot provide an approval service, run a second agent loop or replace\nbuilt-in tools or commands.\n\n## Quick start\n\nStart with [hello-extension](examples/plugins/hello-extension/hello.mts) and its\n[plugin.json](examples/plugins/hello-extension/plugin.json). The example is\nexecuted unchanged by the host tests. It returns a greeting and does not read\nfiles or use the network.\n\n1. Explicitly enable `[features] extension_host = true` in your configuration,\n or start Codewhale with `codewhale --enable extension_host` (the flag goes\n before any subcommand).\n2. Install the example's directory using `/plugin install <local-directory>`.\n3. Run `/plugin validate hello-extension`, then `/plugin show hello-extension`.\n4. Run `/plugin enable hello-extension` to open its content/capability review.\n Read the review and personally run its exact `/plugin trust <token>` command,\n then enable the plugin. Trust alone does not execute the code.\n5. Ask Codewhale to use `hello_greet`. The tool follows the normal approval gate.\n6. Run `/hello-greet Codewhale`. The command runs when you type it, and shows\n its answer in the transcript with its origin, `extension:hello-extension`.\n\nAn authoring agent should stop after installation and validation and present\nthe review to the person. Do not trust or enable a bundle automatically.\n\n## Locations, installation and trust\n\nUser bundles live under `~/.codewhale/plugins/`; workspace bundles live under\n`<workspace>/.codewhale/plugins/`. New bundles use Agent Plugins v1.0.0\n`plugin.json`. Declare `extensions[\"net.codewhale\"].native.path` as one regular\n`.mjs`, `.js` or `.mts` file inside the bundle. Directories and other extensions\nfail validation when the host is enabled. With the flag off, native entries\nremain inventory-only.\n\nA plugin may split its code across several entries with `native.paths` (up to\n64, alone or beside `path`). They are activated in the order declared, as the\nfibers of one plugin: they share one owner, so one disable, review change or\ncrash tears all of them down together. Each entry is a separate module with its\nown `apply`, and tool and command names must be unique across them. If an entry\nfails to activate (throws, requires a service the host does not provide, or has\na registration refused), only that entry is withdrawn: entries that already\nactivated stay registered, later entries still activate, and the plugin fails\nonly when no entry activates. Listing the same file twice is one entry.\n\n## Runtime\n\n`[extension_host] runtime` selects what runs the host. Node is the default.\nBun is an opt-in: it is qualified on macOS only, and becomes the default only\nafter an explicit, recorded cutover.\n\n```toml\n[extension_host]\nruntime = \"node\" # default: Node only\n# runtime = \"bun\" # Bun only; fails rather than falling back to Node\n# runtime = \"auto\" # Bun >= 1.4.0 if one is found and starts, otherwise Node\n# bun = \"~/.bun/bin/bun\" # the only Bun tried when set\n# node = \"/opt/homebrew/bin/node\" # the only Node tried when set\n# mcp_backend = \"rust\" # temporary opt-out; default is \"host\"\n```\n\nThe default `mcp_backend = \"host\"` uses the pinned MCP SDK independently of\n`[features] extension_host`, which controls optional Native extensions. Existing\nstdio and HTTP servers use modern discovery when supported; explicitly configured\nlegacy SSE servers use their legacy handshake. Rust retains process and network\nauthority, credential resolution, catalog admission, tool approval and cancellation.\nThe SDK receives opaque session selectors and exact operation grants. Modern\nrequests carry Rust-approved protocol metadata and headers without a session id.\n\nA typed discovery refusal can admit a legacy handshake. Only an explicit HTTP\ntransport refusal during that handshake can admit legacy SSE with a fresh exact\nRust grant. Legacy HTTP retains its GET preflight and bounded OAuth refresh;\nmodern HTTP does not inherit those session or resend behaviors. Incomplete result\nflows are reported without automatically repeating the operation. Credentials,\nconfigured URLs, OAuth browser/login operations and Computer Use decision keys\nstay in Rust.\n\nBoth backends share recorded semantic MCP goldens and retain separate transport\ngoldens, including discovery, authentication and session evidence. The Host default\nrequires those fixtures and the actual broker acceptance checks, plus the platform\nisolation and measured gates in Ops CURRENT_DECISIONS §26. An explicit\n`mcp_backend = \"rust\"`remainsavailableforonereleaseafterthequalifieddefault\nflip,beforethenativeprotocoLine truncated
"content":"# Writing an extension tool or command\n\nThe experimental TypeScript extension host runs reviewed plugin code in a\nshared Node process (or, as an opt-in, Bun). Rust still owns sessions, tool admission, approval and\nexecution. Extensions currently contribute tools and slash commands; they\ncannot provide an approval service, run a second agent loop or replace\nbuilt-in tools or commands.\n\n## Quick start\n\nStart with [hello-extension](examples/plugins/hello-extension/hello.mts) and its\n[plugin.json](examples/plugins/hello-extension/plugin.json). The example is\nexecuted unchanged by the host tests. It returns a greeting and does not read\nfiles or use the network.\n\n1. Explicitly enable `[features] extension_host = true` in your configuration,\n or start Codewhale with `codewhale --enable extension_host` (the flag goes\n before any subcommand).\n2. Install the example's directory using `/plugin install <local-directory>`.\n3. Run `/plugin validate hello-extension`, then `/plugin show hello-extension`.\n4. Run `/plugin enable hello-extension` to open its content/capability review.\n Read the review and personally run its exact `/plugin trust <token>` command,\n then enable the plugin. Trust alone does not execute the code.\n5. Ask Codewhale to use `hello_greet`. The tool follows the normal approval gate.\n6. Run `/hello-greet Codewhale`. The command runs when you type it, and shows\n its answer in the transcript with its origin, `extension:hello-extension`.\n\nAn authoring agent should stop after installation and validation and present\nthe review to the person. Do not trust or enable a bundle automatically.\n\n## Locations, installation and trust\n\nUser bundles live under `~/.codewhale/plugins/`; workspace bundles live under\n`<workspace>/.codewhale/plugins/`. New bundles use Agent Plugins v1.0.0\n`plugin.json`. Declare `extensions[\"net.codewhale\"].native.path` as one regular\n`.mjs`, `.js` or `.mts` file inside the bundle. Directories and other extensions\nfail validation when the host is enabled. With the flag off, native entries\nremain inventory-only.\n\nA plugin may split its code across several entries with `native.paths` (up to\n64, alone or beside `path`). They are activated in the order declared, as the\nfibers of one plugin: they share one owner, so one disable, review change or\ncrash tears all of them down together. Each entry is a separate module with its\nown `apply`, and tool and command names must be unique across them. If an entry\nfails to activate (throws, requires a service the host does not provide, or has\na registration refused), only that entry is withdrawn: entries that already\nactivated stay registered, later entries still activate, and the plugin fails\nonly when no entry activates. Listing the same file twice is one entry.\n\n## Runtime\n\n`[extension_host] runtime` selects what runs the host. Node is the default.\nBun is an opt-in: it is qualified on macOS only, and becomes the default only\nafter an explicit, recorded cutover.\n\n```toml\n[extension_host]\nruntime = \"node\" # default: Node only\n# runtime = \"bun\" # Bun only; fails rather than falling back to Node\n# runtime = \"auto\" # Bun >= 1.4.0 if one is found and starts, otherwise Node\n# bun = \"~/.bun/bin/bun\" # the only Bun tried when set\n# node = \"/opt/homebrew/bin/node\" # the only Node tried when set\n# mcp_backend = \"rust\" # temporary opt-out; default is \"host\"\n```\n\nThe default `mcp_backend = \"host\"` uses the pinned MCP SDK independently of\n`[features] extension_host`, which controls optional Native extensions. Existing\nstdio and HTTP servers use modern discovery when supported; explicitly configured\nlegacy SSE servers use their legacy handshake. Rust retains process and network\nauthority, credential resolution, catalog admission, tool approval and cancellation.\nThe SDK receives opaque session selectors and exact operation grants. Modern\nrequests carry Rust-approved protocol metadata and headers without a session id.\n\nA typed discovery refusal can admit a legacy handshake. Only an explicit HTTP\ntransport refusal during that handshake can admit legacy SSE with a fresh exact\nRust grant. Legacy HTTP retains its GET preflight and bounded OAuth refresh;\nmodern HTTP does not inherit those session or resend behaviors. Incomplete result\nflows are reported without automatically repeating the operation. Credentials,\nconfigured URLs, OAuth browser/login operations and Computer Use decision keys\nstay in Rust.\n\nBoth backends share recorded semantic MCP goldens and retain separate transport\ngoldens, including discovery, authentication and session evidence. The Host default\nrequires those fixtures and the actual broker acceptance checks, plus the platform\nisolation and measured gates in Ops CURRENT_DECISIONS §26. An explicit\n`mcp_backend = \"rust\"`remainsavailableforonereleaseafterthequalifieddefault\nflip,beforethenativeprotocoLine truncated
"content":"# Contributing to codewhale\n\nThank you for your interest in contributing to codewhale! This document provides guidelines and instructions for contributing.\n\n## Getting Started\n\n### Prerequisites\n\n- Rust 1.89 or later (edition 2024)\n- Cargo package manager\n- Git\n\n### Setting Up Development Environment\n\n1. Fork and clone the repository:\n ```bash\n git clone https://github.com/YOUR_USERNAME/CodeWhale.git\n cd CodeWhale\n ```\n\n2. Build the current engine and terminal:\n ```bash\n CODEWHALE_BUILD_SHA=\"$(git rev-parse HEAD)\" cargo build --locked -p codewhale-cli\n ```\n\n3. Run the tests near your change (see [Fast local loop](#fast-local-loop)):\n ```bash\n scripts/dev-test.sh tui your_test_filter\n ```\n\n4. Run with development settings:\n ```bash\n ./target/debug/codewhale --version\n ./target/debug/codewhale\n ```\n\n### Testing the latest source\n\nThe canonical source is [`codewhale-hq/Codewhale`'s `main` branch](https://github.com/codewhale-hq/Codewhale/tree/main).\nRelease candidates land there after their CI gates pass, so contributors can\ntest and build on the same source. Tagged downloads remain the latest published\nrelease; their version can lag the development version on `main`.\n\nFor a fresh checkout of the current source:\n\n```bash\ngit clone --branch main https://github.com/codewhale-hq/Codewhale.git\ncd Codewhale\nCODEWHALE_BUILD_SHA=\"$(git rev-parse HEAD)\"cargobuild--release--locked-pcodewhale-cli\n./target/release/codewhale--version\n./target/release/codewhale\n```\n\nIncludethecommitshownby`--version`whenreportingaproblem.Ifyouwork\nfromafork,addthecanonicalrepositoryas`upstream`andfetch`upstream/main`\nbeforestartingachange;preserveanylocalworkwhenupdatingyourbranch.\n\n##DevelopmentWorkflow\n\n###CodeStyle\n\n-Run`cargofmt`beforecommittingtoensureconsistentformatting\n-Run`cargoclippy`andaddressallwarnings\n-FollowRustnamingconventions(snake_caseforfunctions/variables,CamelCasefortypes)\n-AdddocumentationcommentsforpublicAPIs\n\n###Testing\n\n-Writetestsfornewfunctionality\n-Runthetestsnearyourchange(see[Fastlocalloop](#fast-local-loop));\nyourpullrequestrunstheLinuxworkspacesuiteandaWindowsbuildfor\nyou(see[Whathappensafteryouopenapullrequest](#what-happens-after-you-open-a-pull-request))\n-Colocateunittestsbesidethecodetheycover(standardRust`#[cfg(test)]`\nmodules),andaddintegrationtestsundertheowningcrate's`tests/`\ndirectory(forexample`crates/tui/tests/`or`crates/state/tests/`).The\nrepositoryroot`tests/`directoryisnotused\n\n###Pre-pushverification\n\nThesearetheRustcommandsyourpullrequestrunsonLinux(the`Lint`and\n`Test(ubuntu-latest)`checks).Youdonotneedallofthembeforeevery\npush:run`cargofmt`,thencheckandtestthecratesyoutouched(see\n[Fastlocalloop](#fast-local-loop)).Runthefullsetlocallywhenachange\nspansmanycrates,orletthepullrequestrunitforyou:\n\n```bash\ncargofmt--all----check\ncargoclippy--workspace--all-targets--all-features--locked--\\\n-Dwarnings\\\n-Aclippy::uninlined_format_args\\\n-Aclippy::too_many_arguments\\\n-Aclippy::unnecessary_map_or\ncargotest--workspace--all-features--locked\n```\n\nClippylintstest,benchandexampletargetstoo(`--all-targets`),andthe\nthreeallowancesabovearetheonlyonesCIandthereleaselaneaccept.\n\n####Fastlocalloop\n\nThefullgateaboveiswhatCIenforces,butyoudonotneeditforevery\nedit.`crates/tui`isa~750k-linecrate,sotheloopthatstaysfastis\ntheonethatavoidsrebuildingitmorethannecessary(numbersandthe\nreasoningarein[`docs/BUILD_PERFORMANCE.md`](docs/BUILD_PERFORMANCE.md)):\n\n```bash\n#1.Type-checkfirst(secondsafterthefirstbuild;nocodegen,nolink).\nscripts/dev-cargo.shcheck-pcodewhale-tui\n\n#2.Runonlythetestsnearyourchange(onecrate,onefilter).\nscripts/dev-test.shtuifleet_setup\n#or:scripts/dev-test.shcrates/command-contract/src/elapsed.rs\n\n#3.Runawholecrate'sunitsuite.scripts/dev-test.shusesnextestwhen\n#itisinstalled(oneprocesspertest,allcoresbusy,slowtests\n#named;~100sherevs~270swithlibtest).\ncargoinstallcargo-nextest--locked#once\nscripts/dev-test.shtui\nscripts/dev-cargo.shnextestrun--workspace--all-features--locked\n\n#4.TheLinuxsuiteyourPRruns:\ncargotest--workspace--all-features--locked\n```\n\n`.config/nextest.toml`alreadyserializesthePTYsuiteandboundsthe\nintegrationteststhatspawntherealbinary,so`cargonextestrun`is\nsafetouseonthewholeworkspace(nextestdoesnotrundoctests;the\nauthoritative`cargotest`gatedoes).Testsmustnotdependonrunningin\nthesameprocessasanothertest(nextestgiveseverytestitsown\nprocess);ifatestLine truncated
"content":"# Contributing to codewhale\n\nThank you for your interest in contributing to codewhale! This document provides guidelines and instructions for contributing.\n\n## Getting Started\n\n### Prerequisites\n\n- Rust 1.89 or later (edition 2024)\n- Cargo package manager\n- Git\n\n### Setting Up Development Environment\n\n1. Fork and clone the repository:\n ```bash\n git clone https://github.com/YOUR_USERNAME/CodeWhale.git\n cd CodeWhale\n ```\n\n2. Build the current engine and terminal:\n ```bash\n CODEWHALE_BUILD_SHA=\"$(git rev-parse HEAD)\" cargo build --locked -p codewhale-cli\n ```\n\n3. Run the tests near your change (see [Fast local loop](#fast-local-loop)):\n ```bash\n scripts/dev-test.sh tui your_test_filter\n ```\n\n4. Run with development settings:\n ```bash\n ./target/debug/codewhale --version\n ./target/debug/codewhale\n ```\n\n### Testing the latest source\n\nThe canonical source is [`codewhale-hq/Codewhale`'s `main` branch](https://github.com/codewhale-hq/Codewhale/tree/main).\nRelease candidates land there after their CI gates pass, so contributors can\ntest and build on the same source. Tagged downloads remain the latest published\nrelease; their version can lag the development version on `main`.\n\nFor a fresh checkout of the current source:\n\n```bash\ngit clone --branch main https://github.com/codewhale-hq/Codewhale.git\ncd Codewhale\nCODEWHALE_BUILD_SHA=\"$(git rev-parse HEAD)\"cargobuild--release--locked-pcodewhale-cli\n./target/release/codewhale--version\n./target/release/codewhale\n```\n\nIncludethecommitshownby`--version`whenreportingaproblem.Ifyouwork\nfromafork,addthecanonicalrepositoryas`upstream`andfetch`upstream/main`\nbeforestartingachange;preserveanylocalworkwhenupdatingyourbranch.\n\n##DevelopmentWorkflow\n\n###CodeStyle\n\n-Run`cargofmt`beforecommittingtoensureconsistentformatting\n-Run`cargoclippy`andaddressallwarnings\n-FollowRustnamingconventions(snake_caseforfunctions/variables,CamelCasefortypes)\n-AdddocumentationcommentsforpublicAPIs\n\n###Testing\n\n-Writetestsfornewfunctionality\n-Runthetestsnearyourchange(see[Fastlocalloop](#fast-local-loop));\nyourpullrequestrunstheLinuxworkspacesuiteandaWindowsbuildfor\nyou(see[Whathappensafteryouopenapullrequest](#what-happens-after-you-open-a-pull-request))\n-Colocateunittestsbesidethecodetheycover(standardRust`#[cfg(test)]`\nmodules),andaddintegrationtestsundertheowningcrate's`tests/`\ndirectory(forexample`crates/tui/tests/`or`crates/state/tests/`).The\nrepositoryroot`tests/`directoryisnotused\n\n###Pre-pushverification\n\nThesearetheRustcommandsyourpullrequestrunsonLinux(the`Lint`and\n`Test(ubuntu-latest)`checks).Youdonotneedallofthembeforeevery\npush:run`cargofmt`,thencheckandtestthecratesyoutouched(see\n[Fastlocalloop](#fast-local-loop)).Runthefullsetlocallywhenachange\nspansmanycrates,orletthepullrequestrunitforyou:\n\n```bash\ncargofmt--all----check\ncargoclippy--workspace--all-targets--all-features--locked--\\\n-Dwarnings\\\n-Aclippy::uninlined_format_args\\\n-Aclippy::too_many_arguments\\\n-Aclippy::unnecessary_map_or\ncargotest--workspace--all-features--locked\n```\n\nClippylintstest,benchandexampletargetstoo(`--all-targets`),andthe\nthreeallowancesabovearetheonlyonesCIandthereleaselaneaccept.\n\n####Fastlocalloop\n\nThefullgateaboveiswhatCIenforces,butyoudonotneeditforevery\nedit.`crates/tui`isa~750k-linecrate,sotheloopthatstaysfastis\ntheonethatavoidsrebuildingitmorethannecessary(numbersandthe\nreasoningarein[`docs/BUILD_PERFORMANCE.md`](docs/BUILD_PERFORMANCE.md)):\n\n```bash\n#1.Type-checkfirst(secondsafterthefirstbuild;nocodegen,nolink).\nscripts/dev-cargo.shcheck-pcodewhale-tui\n\n#2.Runonlythetestsnearyourchange(onecrate,onefilter).\nscripts/dev-test.shtuifleet_setup\n#or:scripts/dev-test.shcrates/command-contract/src/elapsed.rs\n\n#3.Runawholecrate'sunitsuite.scripts/dev-test.shusesnextestwhen\n#itisinstalled(oneprocesspertest,allcoresbusy,slowtests\n#named;~100sherevs~270swithlibtest).\ncargoinstallcargo-nextest--locked#once\nscripts/dev-test.shtui\nscripts/dev-cargo.shnextestrun--workspace--all-features--locked\n\n#4.TheLinuxsuiteyourPRruns:\ncargotest--workspace--all-features--locked\n```\n\n`.config/nextest.toml`alreadyserializesthePTYsuiteandboundsthe\nintegrationteststhatspawntherealbinary,so`cargonextestrun`is\nsafetouseonthewholeworkspace(nextestdoesnotrundoctests;the\nauthoritative`cargotest`gatedoes).Testsmustnotdependonrunningin\nthesameprocessasanothertest(nextestgiveseverytestitsown\nprocess);ifatestLine truncated
"content":"# Modes and Permission Postures\n\n> 阅读简体中文版:[zh_hans/MODES.md](zh_hans/MODES.md)\n\nCodewhale has three related concepts:\n\n- **TUI mode**: what kind of visible interaction you're in (Plan/Work/Operate).\n- **Permission posture**: how aggressively the UI asks before executing tools.\n- **Workflow**: named steps that coordinate sub-agents, with dependencies and\n results, available in any TUI mode.\n\nModel selection is separate. `--model auto` and `/model auto` route each turn to\na concrete model and thinking level; they are not TUI modes and are not part of\nthe `Tab` cycle.\n\nWorkflow runs named steps through the same sub-agent runtime; Fleet manages\ntheir saved roles and model assignments. A workflow adds ordering, result\nhandoffs, gates and a progress view. The active mode and permission posture\nstill control what each step may execute.\n\nBefore assigning steps, query `agent(action=\"roster\")` for the saved Fleet\nmodels and roles. A plan child can select a listed model with `model`, or use\nthe saved `role`/`profile` assignment. An Exact Fleet fixes each member's route.\n\n## TUI Modes\n\nPress `Tab` to complete composer menus or cycle through the visible modes\nwhen the composer is empty: **Plan → Work → Operate → Plan**. `Tab` never sends\nor queues composer text; use `Enter` to send or queue it.\nPress `Shift+Tab` to cycle permission posture (Ask → Auto-Review → Full Access).\nEvery change of effective permission writes a `Permissions changed to …` line\nin the transcript.\nPress `Ctrl+T` to cycle reasoning effort.\nRun `/mode` to open the mode picker, or switch directly with `/mode work`,\n`/mode plan`, or `/mode operate`.\n\n- **Plan**: design-first prompting. The stable primitive names remain familiar, but the runtime centrally refuses file mutation and shell execution. Read-only inspection and policy-allowed research, including deferred Web search/fetch, remain available. When a Plan turn successfully finishes a nonempty response, including a prose-only plan, the TUI asks how to continue: Work (Ask), Work (Auto-Review), or keep planning. Work sends the exact approved response as a normal follow-up and preserves that turn's existing To-dos, or adds one pending plan item without replacing unrelated work.\n- **Work** (internally `agent`): ordinary multi-step execution. The first-turn toolbox includes `read`, `write`, `edit`, `file_search`, `bash`, `agent`, `workflow`, `todo_write`, and `load_skill`, plus `create_goal`, `get_goal`, `update_goal`, and `task_shell_wait` so goal and background-shell controls are available without discovery. The agent calls `create_goal` when a request is a durable objective; the host never infers a goal from wording, and the contract must not tell the model otherwise. Approval, sandbox, repository law, and managed policy decide what may execute.\n- **Operate**: Work at full strength, the \"ultra\"mode.SametoolsandauthorityasWork;thedifferenceishowtheyareused.Eachsubstantiverequestbecomesagoal(`create_goal`),theplanstaysvisible(`todo_write`),multi-partworkrunsthrough`workflow`andparallel`agent`workers,non-trivialchangesgetanindependentreviewerbeforetheyarecalleddone,longcommandskeeprunninginthebackground,andrecurringorwatch-typeworkisofferedasan`automation`(createdafterapproval).Itkeepsgoinguntilthegoalisverified,blockedonyou,orpaused.\n\n`Act`and`/modeact`remaincompatibilityaliasesforWork.Savedsettings\nstillnormalizetotheinternalvalue`agent`.\n\n###Toolavailabilitybymode\n\n|Toolfamily|Plan|Work|Operate|\n|:---|:---:|:---:|:---:|\n|`read`andpolicy-alloweddeferredresearchtools|yes|yes|yes|\n|`write`and`edit`|visiblenames;executiondenied|approval-andpolicy-gated|sameasWork|\n|`bash`|visiblename;executiondenied|approval-andpolicy-gated|sameasWork;delegationispreferredwhenparallelismorisolationhelps|\n|`agent`|yes,subjecttochild-depthauthority|yes,subjecttochild-depthauthority|yes,subjecttochild-depthauthority|\n|Deferrednative,MCP,andplugintools|discoverablethrough`tool_search`whenpolicypermits|same|same|\n|Paidorexternal-servicetools|followspermissionposture|followspermissionposture|followspermissionposture|\n|Accessoutsidetheworkspaceroot|explicittrustedpathsonly|onlythroughtrustedpathsortrustmode|sametrusted-path/trustpolicyasWork;fleetprofilesneverwidenit|\n\nOperatechangesschedulingemphasis,notauthority.Itneitheraddsa\nmode-specifictooldenialnorbypassestheactiveapproval,sandbox,shell,\nask-rule,repository-law,ormanaged-policyboundary.Planremainsthe\nmode-specificexecutionboundaryforshellandwrite-capabletools;that\nauthoritydifferencedoesnotrequireadifferentprimitivevocabulary.\n\n###Operateloop(onescreen)\n\n```text\nUserLine truncated
"content":"# Modes and Permission Postures\n\n> 阅读简体中文版:[zh_hans/MODES.md](zh_hans/MODES.md)\n\nCodewhale has three related concepts:\n\n- **TUI mode**: what kind of visible interaction you're in (Plan/Work/Operate).\n- **Permission posture**: how aggressively the UI asks before executing tools.\n- **Workflow**: named steps that coordinate sub-agents, with dependencies and\n results, available in any TUI mode.\n\nModel selection is separate. `--model auto` and `/model auto` route each turn to\na concrete model and thinking level; they are not TUI modes and are not part of\nthe `Tab` cycle.\n\nWorkflow runs named steps through the same sub-agent runtime; Fleet manages\ntheir saved roles and model assignments. A workflow adds ordering, result\nhandoffs, gates and a progress view. The active mode and permission posture\nstill control what each step may execute.\n\nBefore assigning steps, query `agent(action=\"roster\")` for the saved Fleet\nmodels and roles. A plan child can select a listed model with `model`, or use\nthe saved `role`/`profile` assignment. An Exact Fleet fixes each member's route.\n\n## TUI Modes\n\nPress `Tab` to complete composer menus or cycle through the visible modes\nwhen the composer is empty: **Plan → Work → Operate → Plan**. `Tab` never sends\nor queues composer text; use `Enter` to send or queue it.\nPress `Shift+Tab` to cycle permission posture (Ask → Auto-Review → Full Access).\nEvery change of effective permission writes a `Permissions changed to …` line\nin the transcript.\nPress `Ctrl+T` to cycle reasoning effort.\nRun `/mode` to open the mode picker, or switch directly with `/mode work`,\n`/mode plan`, or `/mode operate`.\n\n- **Plan**: design-first prompting. The stable primitive names remain familiar, but the runtime centrally refuses file mutation and shell execution. Read-only inspection and policy-allowed research, including deferred Web search/fetch, remain available. When a Plan turn successfully finishes a nonempty response, including a prose-only plan, the TUI asks how to continue: Work (Ask), Work (Auto-Review), or keep planning. Work sends the exact approved response as a normal follow-up and preserves that turn's existing To-dos, or adds one pending plan item without replacing unrelated work.\n- **Work** (internally `agent`): ordinary multi-step execution. The first-turn toolbox includes `read`, `write`, `edit`, `file_search`, `bash`, `agent`, `workflow`, `todo_write`, and `load_skill`, plus `create_goal`, `get_goal`, `update_goal`, and `task_shell_wait` so goal and background-shell controls are available without discovery. The agent calls `create_goal` when a request is a durable objective; the host never infers a goal from wording, and the contract must not tell the model otherwise. Approval, sandbox, repository law, and managed policy decide what may execute.\n- **Operate**: Work at full strength, the \"ultra\"mode.SametoolsandauthorityasWork;thedifferenceishowtheyareused.Eachsubstantiverequestbecomesagoal(`create_goal`),theplanstaysvisible(`todo_write`),multi-partworkrunsthrough`workflow`andparallel`agent`workers,non-trivialchangesgetanindependentreviewerbeforetheyarecalleddone,longcommandskeeprunninginthebackground,andrecurringorwatch-typeworkisofferedasan`automation`(createdafterapproval).Itkeepsgoinguntilthegoalisverified,blockedonyou,orpaused.\n\n`Act`and`/modeact`remaincompatibilityaliasesforWork.Savedsettings\nstillnormalizetotheinternalvalue`agent`.\n\n###Toolavailabilitybymode\n\n|Toolfamily|Plan|Work|Operate|\n|:---|:---:|:---:|:---:|\n|`read`andpolicy-alloweddeferredresearchtools|yes|yes|yes|\n|`write`and`edit`|visiblenames;executiondenied|approval-andpolicy-gated|sameasWork|\n|`bash`|visiblename;executiondenied|approval-andpolicy-gated|sameasWork;delegationispreferredwhenparallelismorisolationhelps|\n|`agent`|yes,subjecttochild-depthauthority|yes,subjecttochild-depthauthority|yes,subjecttochild-depthauthority|\n|Deferrednative,MCP,andplugintools|discoverablethrough`tool_search`whenpolicypermits|same|same|\n|Paidorexternal-servicetools|followspermissionposture|followspermissionposture|followspermissionposture|\n|Accessoutsidetheworkspaceroot|explicittrustedpathsonly|onlythroughtrustedpathsortrustmode|sametrusted-path/trustpolicyasWork;fleetprofilesneverwidenit|\n\nOperatechangesschedulingemphasis,notauthority.Itneitheraddsa\nmode-specifictooldenialnorbypassestheactiveapproval,sandbox,shell,\nask-rule,repository-law,ormanaged-policyboundary.Planremainsthe\nmode-specificexecutionboundaryforshellandwrite-capabletools;that\nauthoritydifferencedoesnotrequireadifferentprimitivevocabulary.\n\n###Operateloop(onescreen)\n\n```text\nUserLine truncated
"content":"# Codewhale Architecture\n\n> 阅读简体中文版:[zh_hans/ARCHITECTURE.md](zh_hans/ARCHITECTURE.md)。\n\nCodewhale Engine is the existing Rust execution runtime. The\n[Runtime API](RUNTIME_API.md) is its client interface, and\n[TypeScript mods](EXTENSIONS.md) contribute reviewed extensions.\n\nCurrent boundary note (read the workspace version from `Cargo.toml`; this\nboundary has held since v0.9.1):\n- `crates/tui` is still the live end-user runtime for the TUI, runtime API, task manager, and tool execution loop.\n- Other workspace crates are being split out incrementally, but they are not yet the sole runtime source of truth.\n- `crates/net` owns network policy/auditing, destination and DNS guards, proxy resolution, and Claude import planning. Host tool context, transport grants, redirects and response limits stay with their callers. Pure extension-host settings belong to `crates/config`.\n- `crates/notify` owns shared notification payload redaction, attention/category gates, sound policy, and local audio dispatch. TUI retains terminal sinks and native hosts retain banner submission.\n\n<img src=\"assets/architecture.webp\" alt=\"Codewhale architecture: clients reach the one turn loop, Engine::run_turn, through the CLI or the Runtime API; the engine uses crates/core to build requests, runs tools under approval and sandbox policy, routes to any provider through crates/config, and logs everything model-visible to the session store.\" width=\"1000\">\n\nThe diagram draws the Runtime API and the task manager as their own boxes; today\nboth are hosted inside `crates/tui`, as the note above says. The GPUI desktop\napp and the VS Code extension live outside this repository. The arrow from the\nengine to the session log follows the \"model-visible means logged\"contract\nratherthanatracedwritepath.\n-`crates/tui`isbeingsplitintocratessizedasagentworkpartitions:\ncontracts,utilities,services,providers,runtime,leaffeaturecrates,\nTUIviewsandhosts,intheorder`docs/design/TUI_DECONSTRUCTION.md`\nrecords.TheTUIstaystheonlycratethatwritestotheterminal.Untila\nmodulehasmoved,itspathunder`crates/tui/src`isstillwhereitlives.\n-TheLSPsubsystem(`crates/tui/src/lsp/`)isfullywiredintotheengine's\npost-tool-executionpath(`core/engine/lsp_hooks.rs`),providinginline\ndiagnosticsafter`File`write,edit,andpatchactions.\n-Theswarmagentsystemwasremovedinv0.8.5.Theactivesub-agentsurfaceis\nthesingle`agent`tool;persistentRLMsessionsareavailablethroughthe\ndeferred`rlm`actionfamily.\nNomodel-visibleswarmtoolremainsintheactivecodebase.\n\n##High-LevelOverview\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│UserInterface│\n│┌─────────────────┐┌─────────────────┐┌────────────────┐│\n││TUI(ratatui)││One-shotMode││Config/CLI││\n│└────────┬────────┘└────────┬────────┘└────────┬───────┘│\n└───────────┼─────────────────────┼────────────────────┼──────────┘\n│││\n▼▼▼\n┌─────────────────────────────────────────────────────────────────┐\n│CoreEngine│\n│┌─────────────────────────────────────────────────────────┐│\n││AgentLoop(core/engine.rs)││\n││┌─────────┐┌─────────────┐┌──────────────────────┐││\n│││Session││TurnMgmt││ToolOrchestration│││\n││└─────────┘└─────────────┘└──────────────────────┘││\n│└─────────────────────────────────────────────────────────┘│\n└─────────Line truncated
"content":"# Codewhale Architecture\n\n> 阅读简体中文版:[zh_hans/ARCHITECTURE.md](zh_hans/ARCHITECTURE.md)。\n\nCodewhale Engine is the existing Rust execution runtime. The\n[Runtime API](RUNTIME_API.md) is its client interface, and\n[TypeScript mods](EXTENSIONS.md) contribute reviewed extensions.\n\nCurrent boundary note (read the workspace version from `Cargo.toml`; this\nboundary has held since v0.9.1):\n- `crates/tui` is still the live end-user runtime for the TUI, runtime API, task manager, and tool execution loop.\n- Other workspace crates are being split out incrementally, but they are not yet the sole runtime source of truth.\n- `crates/net` owns network policy/auditing, destination and DNS guards, proxy resolution, and Claude import planning. Host tool context, transport grants, redirects and response limits stay with their callers. Pure extension-host settings belong to `crates/config`.\n- `crates/notify` owns shared notification payload redaction, attention/category gates, sound policy, and local audio dispatch. TUI retains terminal sinks and native hosts retain banner submission.\n- `crates/util` owns shared string/path/atomic-write helpers, confined workspace file access, link and file-identity checks, bundle file readers, the `.git` name rule and the exclusive file lock.\n- `crates/dependencies` owns external-tool resolution and bounded subprocess probes (git, python, node, bun); `crates/snapshot` the pre/post-turn side-repo snapshots; `crates/lsp` the language-server client; `crates/repl` the Python REPL runtime and RLM context files.\n- `crates/skill-install` owns the community-skill installer (GitHub and tarball sources, the curated registry, bounded extraction, install and trust markers), the package content digest and the shared `SKILL.md` frontmatter reader. Its SSRF DNS pin and shortened timeouts are relaxed only under its dev-dependency-only `test-support` feature.\n\n<img src=\"assets/architecture.webp\" alt=\"Codewhale architecture: clients reach the one turn loop, Engine::run_turn, through the CLI or the Runtime API; the engine uses crates/core to build requests, runs tools under approval and sandbox policy, routes to any provider through crates/config, and logs everything model-visible to the session store.\" width=\"1000\">\n\nThe diagram draws the Runtime API and the task manager as their own boxes; today\nboth are hosted inside `crates/tui`, as the note above says. The GPUI desktop\napp and the VS Code extension live outside this repository. The arrow from the\nengine to the session log follows the \"model-visible means logged\"contract\nratherthanatracedwritepath.\n-`crates/tui`isbeingsplitintocratessizedasagentworkpartitions:\ncontracts,utilities,services,providers,runtime,leaffeaturecrates,\nTUIviewsandhosts,intheorder`docs/design/TUI_DECONSTRUCTION.md`\nrecords.TheTUIstaystheonlycratethatwritestotheterminal.Untila\nmodulehasmoved,itspathunder`crates/tui/src`isstillwhereitlives.\n-TheLSPsubsystem(`crates/lsp/src/`)isfullywiredintotheengine's\npost-tool-executionpath(`core/engine/lsp_hooks.rs`),providinginline\ndiagnosticsafter`File`write,edit,andpatchactions.\n-Theswarmagentsystemwasremovedinv0.8.5.Theactivesub-agentsurfaceis\nthesingle`agent`tool;persistentRLMsessionsareavailablethroughthe\ndeferred`rlm`actionfamily.\nNomodel-visibleswarmtoolremainsintheactivecodebase.\n\n##High-LevelOverview\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│UserInterface│\n│┌─────────────────┐┌─────────────────┐┌────────────────┐│\n││TUI(ratatui)││One-shotMode││Config/CLI││\n│└────────┬────────┘└────────┬────────┘└────────┬───────┘│\n└───────────┼─────────────────────┼────────────────────┼──────────┘\n│││\n▼▼▼\n┌─────────────────────────────────────────────────────────────────┐\n│CoreEngine│\n│┌─────────────────────────────────────Line truncated
"content":"# LSP: PHP Support & Custom Language Server Extension\n\n> 阅读简体中文版:[zh_hans/LSP_PHP_CUSTOM.md](zh_hans/LSP_PHP_CUSTOM.md)\n>\n> v0.8.65+ | `codex/lsp-php-custom-servers`\n\n## Overview\n\nThis feature adds **PHP** to the built-in LSP language registry and introduces a\n`[lsp.custom]` config section so users can register arbitrary LSP servers by\nfile extension — covering languages absent from the built-in `Language` enum\n(Ruby, C#, Swift, Lua, etc.).\n\n## Changes\n\n### 1. PHP built-in support\n\n- `Language::Php` variant added to the enum in `crates/tui/src/lsp/registry.rs`\n- `.php` files are detected and routed to `intelephense --stdio` by default\n- User can override via `[lsp.servers].php`\n\n### 2. Custom LSP server extension\n\nNew struct `CustomLspDef` (defined in `crates/tui/src/lsp/mod.rs` and mirrored\nin `crates/config/src/lib.rs`):\n\n```rust\npub struct CustomLspDef {\n pub language_id: String, // LSP languageId for textDocument/didOpen\n pub command: String, // executable to spawn\n pub args: Vec<String>, // arguments (default empty)\n}\n```\n\nNew config field `LspConfig.custom: HashMap<String, CustomLspDef>` — keyed by\nfile extension (without dot), e.g. `\"rb\"`, `\"cs\"`, `\"swift\"`.\n\nIn `LspManager::diagnostics_for`, when the built-in registry returns\n`Language::Other`, the manager checks the user's custom table before giving up.\nCustom servers get their own lazy-spawn transport map and once-per-extension\nmissing-binary warnings (no log spam).\n\n### 3. Transport generalization\n\n`StdioLspTransport::spawn` now accepts `&str language_id` instead of\n`Language`, so both built-in and custom servers share the same transport\nimplementation. The old `Language` import is removed from `client.rs`.\n\n### 4. Polling pipeline extracted\n\n`poll_diagnostics` is a new private method that both built-in and custom\ndiagnostics paths share — eliminating duplicated call/wait/filter/sort/truncate\nlogic.\n\n## Configuration\n\n### Built-in PHP (enabled by default if `intelephense` is on PATH)\n\n```toml\n# No config needed — PHP .php files are detected automatically.\n# Override the server if desired:\n[lsp.servers]\nphp = [\"phpactor\", \"language-server\"]\n```\n\n### Custom language servers\n\n```toml\n[lsp.custom.rb]\ncommand = \"ruby-lsp\"\nargs = [\"--stdio\"]\nlanguage_id = \"ruby\"\n\n[lsp.custom.cs]\ncommand = \"csharp-ls\"\nlanguage_id = \"csharp\"\n\n[lsp.custom.swift]\ncommand = \"sourcekit-lsp\"\nlanguage_id = \"swift\"\n```\n\nKeys are file extensions (no leading dot). The `args` field defaults to empty.\n`language_id` must match what the LSP server expects in `textDocument/didOpen`.\n\n## Architecture\n\n```\nedit_file / write_file / apply_patch success\n │\n ▼\n LspManager.diagnostics_for(file)\n │\n ├── custom_for_extension(file) ── found? ──► transport_for_custom(ext, def)\n │ │\n ├── detect_language(file) ── Other? ──► return None (skip)\n │\n └── transport_for(lang)\n │\n ▼\n poll_diagnostics(file, text, transport)\n │\n ▼\n DiagnosticBlock → injected into session message stream\n```\n\n## Verification\n\n```\ncargo test -p codewhale-tui --lib lsp::\n# 32 tests passed (3 new: detects_php_extension, language_ids_for_php,\n# server_for_php_is_intelephense)\ncargo clippy -p codewhale-tui --lib\n# lsp module: zero new warnings\n```\n\n## Files touched\n\n| File | Change |\n|------|--------|\n| `crates/tui/src/lsp/registry.rs` | +Php variant, detection, server mapping, tests |\n| `crates/tui/src/lsp/mod.rs` | +CustomLspDef, LspConfig.custom, LspManager custom fallback |\n| `crates/tui/src/lsp/client.rs` | spawn accepts &str language_id |\n| `crates/tui/src/config.rs` | LspConfigToml.custom + into_runtime |\n| `crates/config/src/lib.rs` | LspConfigToml.custom + CustomLspDef |\n| `config.example.toml` | PHP docs + custom extension examples |\n"
"content":"# LSP: PHP Support & Custom Language Server Extension\n\n> 阅读简体中文版:[zh_hans/LSP_PHP_CUSTOM.md](zh_hans/LSP_PHP_CUSTOM.md)\n>\n> v0.8.65+ | `codex/lsp-php-custom-servers`\n\n## Overview\n\nThis feature adds **PHP** to the built-in LSP language registry and introduces a\n`[lsp.custom]` config section so users can register arbitrary LSP servers by\nfile extension — covering languages absent from the built-in `Language` enum\n(Ruby, C#, Swift, Lua, etc.).\n\n## Changes\n\n### 1. PHP built-in support\n\n- `Language::Php` variant added to the enum in `crates/lsp/src/registry.rs`\n- `.php` files are detected and routed to `intelephense --stdio` by default\n- User can override via `[lsp.servers].php`\n\n### 2. Custom LSP server extension\n\nNew struct `CustomLspDef` (defined in `crates/lsp/src/lib.rs` and mirrored\nin `crates/config/src/lib.rs`):\n\n```rust\npub struct CustomLspDef {\n pub language_id: String, // LSP languageId for textDocument/didOpen\n pub command: String, // executable to spawn\n pub args: Vec<String>, // arguments (default empty)\n}\n```\n\nNew config field `LspConfig.custom: HashMap<String, CustomLspDef>` — keyed by\nfile extension (without dot), e.g. `\"rb\"`, `\"cs\"`, `\"swift\"`.\n\nIn `LspManager::diagnostics_for`, when the built-in registry returns\n`Language::Other`, the manager checks the user's custom table before giving up.\nCustom servers get their own lazy-spawn transport map and once-per-extension\nmissing-binary warnings (no log spam).\n\n### 3. Transport generalization\n\n`StdioLspTransport::spawn` now accepts `&str language_id` instead of\n`Language`, so both built-in and custom servers share the same transport\nimplementation. The old `Language` import is removed from `client.rs`.\n\n### 4. Polling pipeline extracted\n\n`poll_diagnostics` is a new private method that both built-in and custom\ndiagnostics paths share — eliminating duplicated call/wait/filter/sort/truncate\nlogic.\n\n## Configuration\n\n### Built-in PHP (enabled by default if `intelephense` is on PATH)\n\n```toml\n# No config needed — PHP .php files are detected automatically.\n# Override the server if desired:\n[lsp.servers]\nphp = [\"phpactor\", \"language-server\"]\n```\n\n### Custom language servers\n\n```toml\n[lsp.custom.rb]\ncommand = \"ruby-lsp\"\nargs = [\"--stdio\"]\nlanguage_id = \"ruby\"\n\n[lsp.custom.cs]\ncommand = \"csharp-ls\"\nlanguage_id = \"csharp\"\n\n[lsp.custom.swift]\ncommand = \"sourcekit-lsp\"\nlanguage_id = \"swift\"\n```\n\nKeys are file extensions (no leading dot). The `args` field defaults to empty.\n`language_id` must match what the LSP server expects in `textDocument/didOpen`.\n\n## Architecture\n\n```\nedit_file / write_file / apply_patch success\n │\n ▼\n LspManager.diagnostics_for(file)\n │\n ├── custom_for_extension(file) ── found? ──► transport_for_custom(ext, def)\n │ │\n ├── detect_language(file) ── Other? ──► return None (skip)\n │\n └── transport_for(lang)\n │\n ▼\n poll_diagnostics(file, text, transport)\n │\n ▼\n DiagnosticBlock → injected into session message stream\n```\n\n## Verification\n\n```\ncargo test -p codewhale-tui --lib lsp::\n# 32 tests passed (3 new: detects_php_extension, language_ids_for_php,\n# server_for_php_is_intelephense)\ncargo clippy -p codewhale-tui --lib\n# lsp module: zero new warnings\n```\n\n## Files touched\n\n| File | Change |\n|------|--------|\n| `crates/lsp/src/registry.rs` | +Php variant, detection, server mapping, tests |\n| `crates/lsp/src/lib.rs` | +CustomLspDef, LspConfig.custom, LspManager custom fallback |\n| `crates/lsp/src/client.rs` | spawn accepts &str language_id |\n| `crates/tui/src/config.rs` | LspConfigToml.custom + into_runtime |\n| `crates/config/src/lib.rs` | LspConfigToml.custom + CustomLspDef |\n| `config.example.toml` | PHP docs + custom extension examples |\n"
comingLede:{en:"Merged on main and not in a published release yet. Build main to try it now.",zh:"已合并到 main,尚未包含在已发布版本中。现在可从 main 构建试用。"},
changelogLink:{en:"Read the changelog",zh:"查看更新日志"},
items:[
{title:"Steer mid-turn",body:{en:"Ctrl+Enter closes the in-flight model request and continues the same turn with your message. Tab and Shift+Tab change mode and permissions while the agent works; the change applies at its next step.",zh:"Ctrl+Enter 会立即结束正在进行的模型请求,并带着你的消息继续同一轮。智能体工作时也可以用 Tab 和 Shift+Tab 切换模式和权限,改动会在它的下一步生效。"}},
{title:"MCP",body:{en:"MCP servers now connect through the official MCP SDK (2.4) behind Codewhale's Rust broker. Newer servers are discovered with server/discover; older stdio and HTTP servers fall back to the legacy handshake.",zh:"MCP 服务器现在通过官方 MCP SDK(2.4)连接,由 Codewhale 的 Rust 代理把关。较新的服务器通过 server/discover 发现;较旧的 stdio 和 HTTP 服务器回退到旧版握手。"}},
{title:"MCP fixes",body:{en:"Older servers that reject the discovery probe still connect. A server that refuses sign-in shows its real 401 and the /mcp login hint, and one whose command cannot start says why.",zh:"拒绝发现探测的旧服务器仍可连接。拒绝登录的服务器会显示真实的 401 和 /mcp login 提示;命令无法启动的服务器会说明原因。"}},
{title:"DeepSeek Harness plugins",body:{en:"Reviewed DSH plugins run in the Native extension host. Tool output is checked against its declared schema, and unsupported options are refused instead of ignored.",zh:"经过审核的 DSH 插件在 Native 扩展宿主中运行。工具输出按声明的 schema 校验,不支持的选项会被拒绝而不是被忽略。"}},
{title:"Computer Use",body:{en:"No longer bundled in the binary. Install it from the codewhale marketplace, which points at its own release; every decision still needs your approval.",zh:"不再内置于二进制文件中。可从 codewhale 插件市场安装,市场指向它的独立发布版本;每个决定仍需你批准。"}},
{title:"Image-heavy sessions",body:{en:"Older images are left out of an outbound request with a receipt, and an HTTP 413 is retried once with a smaller body. Saved images stay intact.",zh:"较早的图片会从发出的请求中省略并留下记录;遇到 HTTP 413 时会用更小的请求体重试一次。已保存的图片保持不变。"}},
{title:"Instruction budgets",body:{en:"Global and project instructions get separate budgets, and every trim, skip or refusal shows in /context report.",zh:"全局指令和项目指令分别拥有各自的预算,每次截断、跳过或拒绝都会显示在 /context report 中。"}},
{title:"codewhale uninstall",body:{en:"On Unix, previews the release files the installer recorded; --yes removes only those. Your data and package-managed installs are kept.",zh:"在 Unix 上会预览安装程序记录的发布文件;--yes 只删除这些文件。你的数据和包管理器安装的版本会保留。"}},
{title:"codewhale uninstall",body:{en:"Previews the release files the installer recorded, on Unix and Windows; --yes removes only those. Package-managed copies print their own removal command. Your data stays unless you add --purge-data. Windows removal is compile-checked but not yet exercised on a Windows host.",zh:"在 Unix 和 Windows 上预览安装程序记录的发布文件;--yes 只删除这些文件。包管理器安装的版本会给出各自的卸载命令。除非加上 --purge-data,否则你的数据会保留。Windows 上的删除已通过编译检查,但尚未在 Windows 主机上实际运行。"}},
{title:"/rc",body:{en:"codewhale rc attaches to the hosted control plane for web Chat again: it accepts the exact released runtime identity instead of only the retired 0.9.13 one.",zh:"codewhale rc 可以再次连接托管控制平面以使用网页 Chat:它接受确切的已发布运行时身份,而不再只接受已退役的 0.9.13。"}},
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.