v0.9.8

NVIDIA/cosmosv0.9.8Aug 16, 2026by github-actions[bot]

AI Summary

Introduces a federated plugin marketplace, adds composer multiline mode, and improves terminal hardening and process handling, alongside prompt-cache pinning.

Key Highlights

  • Federated plugin marketplace with add, list, show, remove, and install commands.
  • Composer multiline mode available in settings.
  • Sudo/su support restored via `CODEWHALE_NO_NEW_PRIVS=0` environment variable.
  • Terminal recovery from abort-class process deaths (prevents SGR sequence leaks).
  • Prompt-cache prefix pinning to prevent cache busting during file writes.

New Features

  • Plugin marketplace federation.
  • Multiline composer input.
  • Sudo support restoration.
  • Terminal crash recovery.
  • Prompt cache pinning.

Full Release Notes

> **Codewhale** is the public product from Shannon Labs. The `codewhale`
> command, npm package, and release-asset names remain lowercase technical
> identifiers. The legacy npm package `deepseek-tui` is deprecated and
> receives no further releases. Users coming from v0.8.x legacy `deepseek` /
> `deepseek-tui` names should migrate with `docs/REBRAND.md`.

## Install

### Recommended — npm (one command, both entrypoints)

```bash
npm install -g codewhale
```

The wrapper downloads the matched `codewhale` and `codew` command assets
from this Release. Both contain the same compiled runtime.

### Docker / GHCR

```bash
docker run --rm -it \
  -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
  -v codewhale-home:/home/codewhale/.codewhale \
  ghcr.io/hmbown/codewhale:v0.9.8
```

The image exposes the same runtime as both `codewhale` and `codew`. The
`latest` tag is also updated on release.

### Cargo (Linux / macOS)

```bash
cargo install codewhale-cli --locked
```

The Cargo package installs `codewhale`. Cargo cannot create a second command
alias from one binary target; users who want the shorter spelling can add a
`codew` symlink to that installed executable. The npm, Homebrew, archive,
shell-installer, and container channels install both command names directly.

### Manual download — platform archives (recommended)

Each archive below contains the same runtime under the `codewhale` and
`codew` command names, plus an install script:

| Platform | Archive | Install script |
|---|---|---|
| Linux x64 | `codewhale-linux-x64.tar.gz` | `install.sh` |
| Linux ARM64 | `codewhale-linux-arm64.tar.gz` | `install.sh` |
| Android ARM64 (Termux) | `codewhale-android-arm64.tar.gz` | `install.sh` |
| macOS x64 | `codewhale-macos-x64.tar.gz` | `install.sh` |
| macOS ARM | `codewhale-macos-arm64.tar.gz` | `install.sh` |
| Windows x64 (installer) | `CodeWhaleSetup.exe` | NSIS setup |
| Windows x64 | `codewhale-windows-x64.zip` | `install.bat` |
| Windows x64 (portable) | `codewhale-windows-x64-portable.zip` | — |
| Windows ARM64 | `codewhale-windows-arm64.zip` | `install.bat` |
| Windows ARM64 (portable) | `codewhale-windows-arm64-portable.zip` | — |

**Unix (Linux / macOS):**
```bash
tar xzf codewhale-<platform>.tar.gz
cd codewhale-<platform>
./install.sh
```

**Windows:**
- For the installer path, run `CodeWhaleSetup.exe`; it installs
  `codewhale.exe` and `codew.exe` under
  `%LOCALAPPDATA%\Programs\CodeWhale\bin` and adds that directory to the
  current-user PATH.
- Extract the archive for your machine: `codewhale-windows-x64.zip` or
  `codewhale-windows-arm64.zip`
- Run `install.bat` (copies to `%USERPROFILE%\bin`)
- Add `%USERPROFILE%\bin` to your PATH

The **portable** Windows archive skips the install script — extract and run from any directory. The NSIS installer is currently unsigned and may trigger Windows SmartScreen until a signing certificate is wired into the release pipeline.

Each platform also has **bare, unarchived** `codewhale-<platform>` and
`codew-<platform>` assets. The seven `codewhale-tui-<platform>` filenames
attached to v0.9.5 are byte-identical compatibility copies used only to let
already-installed v0.9.4 clients discover and cross this single-binary
transition; current installers do not expose a third runtime. The legacy npm
package `deepseek-tui` is deprecated and is not republished. For migration
from v0.8.x legacy binary names, see `docs/REBRAND.md`.

### Verify (recommended)

Download the checksum manifests from this Release and verify:

```bash
# Linux — archive bundles
sha256sum -c codewhale-bundles-sha256.txt --ignore-missing

# Linux — individual binaries
sha256sum -c codewhale-artifacts-sha256.txt --ignore-missing

# macOS
shasum -a 256 -c codewhale-bundles-sha256.txt --ignore-missing
shasum -a 256 -c codewhale-artifacts-sha256.txt --ignore-missing
```

## What's in v0.9.8

Codewhale v0.9.8 ships the remaining assigned finish. Remaining web
settings polish moves to v0.9.9. Prefab third-party templates that have
a published OpenAI-compatible host ship here (#5350).

### Fixed

- `sudo` (and `su`/setuid helpers) work again for wheel-group administrators
  who want Codewhale to be able to escalate: the Linux startup hardening's
  irreversible `PR_SET_NO_NEW_PRIVS` flag — inherited by every child process —
  is now skippable with `CODEWHALE_NO_NEW_PRIVS=0` (#5413). The flag stays on
  by default; the no-ptrace and no-core-dump measures are never skipped.

- Abort-class process deaths no longer poison the terminal (#5424). A
  stack overflow, allocation failure, or double panic skips the panic hook
  and every cleanup guard, which is how a v0.9.7 user's mid-turn exit left
  mouse capture leaking SGR sequences into their shell. An
  async-signal-safe handler now restores the terminal modes and appends a
  one-line cause marker to `~/.codewhale/crashes/last-fatal-signal.log`
  before re-raising, keeping the honest 128+signal wait status. A SIGKILL
  (OOM killer) remains uninterceptable by design.

### Changed

- Prompt-cache prefix is pinned for the session. The tool loop no longer
  recomposes the system prompt from disk on every model step, so an agent
  writing a file no longer busts the provider KV prefix cache mid-turn. The
  system prompt and tool catalog are re-composed only on a declared header
  change (`/model`, mode, goal, session resume), which re-pins under a logged
  reason; an undeclared change is reported as drift and the original pin is
  kept instead of silently becoming the new baseline. Workspace, AGENTS.md,
  skills, memory, and goal drift now reaches the model as one bounded
  `<context_update>` user message at the next user turn — a history append,
  not a header rewrite. `/cache stats` shows the pin reason, the last-miss
  reason, the undeclared-drift count, and the context-update count. See
  [docs/CACHE.md](docs/CACHE.md).

- Plugin compatibility is now per-component. A reviewed, trusted, enabled
  bundle that mixes Skills or MCP with unsupported commands, agents, hooks,
  LSP, native, filesystem-roots, or lifecycle-mutation declarations keeps the
  supported adapters active and reports the rest as inactive (`full` /
  `partial` / `unsupported`). All-unsupported bundles still cannot be enabled.
  The capability hash is now v2 and binds this build's activation policy, so
  older v1 receipts and any later adapter-enablement change fail closed as
  needs-review. Skills and each MCP transport re-request their own capability
  at the consumption boundary.

### Added

- Composer multiline mode is available in `/settings`. When enabled, Enter inserts a new line and Shift+Enter sends the message (#5345, reported and tracked by @AiurArtanis).


- `/plugin marketplace add|list|show|remove|install` completes the
  federated marketplace journey (#5311). `add` reads one LOCAL catalog
  document in the real published schemas (Kimi, Claude, Codex, or
  Codewhale native) — no network, regular files only — and persists it
  beside the plugin state with the same hardened, fail-closed store.
  `list`/`show` render every candidate with per-entry diagnostics,
  display-only tiers, and honest install plans that say when Codewhale
  cannot fetch a source; `install` routes through the existing reviewed
  installer, so installed bundles still enter disabled and untrusted.
  Foreign auto-install policy (Codex `INSTALLED_BY_DEFAULT`) is visibly
  ignored; nothing is auto-installed, auto-trusted, or granted vendor
  trust.

- `/rc` attach now includes an observed `owner/name` git remote when the
  folder has a GitHub, CNB, or Gitee origin, so CWC can label the paired
  session. Paths stay off the wire. Reconnect after both this client and
  CWC #202 land to backfill existing empty rows.

- The local Runtime web client keeps the thread rail clipped so **New
  thread** cannot paint over the session fact chips. Chips wrap instead
  of sliding under the rail.

- Z.ai `GLM-5.3` is live on the Coding Plan and is now the default direct
  Z.ai model: `DEFAULT_ZAI_MODEL` resolves to `GLM-5.3` in both
  `codewhale-tui` and `codewhale-config`, and it is the first `/model` row
  after `/provider zai`. Explicit `GLM-5.2` selections (`model = "GLM-5.2"`
  and its `glm-5.2` aliases) keep their own id — only the default moved.
  Limits and reasoning options still inherit from `GLM-5.2` until Z.ai
  publishes distinct 5.3 numbers. No USD price is claimed. A live call
  can still 429 with entitlement code 1311 on accounts that are not
  provisioned for 5.3.

- The TUI transcript renders Markdown blockquotes (`>` lines) with a quote
  rail — nested quotes, inline bold/code/links, wrapped continuation rows, and
  selection copy that keeps the quote text and skips the rail chrome.

- Sub-agent details show the resolved model, fleet role, and type. Labels
  use the session/role name instead of a generic Agent N (#5371, #5287).

- Documented catalogue output ceilings (DeepSeek V4 384K) are honored on
  the request. A clean output-limit stop continues the turn instead of
  killing it (#5373).

- Ollama Cloud is a first-class hosted provider (`/provider ollama-cloud`)
  on the official OpenAI-compatible `https://ollama.com/v1` route. Local
  Ollama stays keyless. The exact released `ollama` + Cloud URL tuple keeps
  a bounded compatibility path across saved sessions, Fleet, and nested
  subagents; neighboring remotes stay custom and fail closed against
  inherited official credentials.

- Homebrew ships a `codewhale` formula. `brew tap Hmbown/deepseek-tui &&
  brew install codewhale` is the install path; `brew upgrade codewhale`
  updates it. The legacy `deepseek-tui` formula remains a deprecated alias
  for one overlap release.

- Terminal tab/window titles now carry the existing saved session name before
  the live state (`Codewhale`, `reasoning…`, `using tool…`, `done`), so parallel
  sessions are identifiable at a glance without a second title setting.
  `/title <name>` is a discoverable alias for `/rename`; both update the one
  session name shown in the picker, composer, and terminal tab. Control,
  bidi, and zero-width format characters are stripped from the saved name
  itself, so `/title`, `/rename`, the picker, the Runtime API,
  `codewhale sessions`, and the OSC 0 tab title all carry the same
  escape-free text (#5419, Sh1Zuku).
- Eden AI is a named OpenAI-compatible Chat Completions provider (`edenai`,
  aliases `eden-ai` / `eden_ai`) with `EDENAI_API_KEY`, global and EU base-URL
  overrides, a live provider-scoped model catalog, and
  `deepseek/deepseek-v4-pro` as the verified default. Generic reasoning fields
  stay omitted because Eden AI routes multiple upstream model families
  (#5422, Kai Nacke).
- Children (sub-agents and Fleet workers) inherit the session's permission
  posture faithfully: Auto-Review's deterministic floor and model guardian
  decide a worker's held calls (fail closed when unavailable, never a
  prompt); under Ask a held call is raised in the parent's approval UI and
  the worker waits visibly; Full Access still fails closed on the safety
  floor. Each prompt-less decision is a one-line note in that worker's
  transcript (focus mode) and an audit-log record.
- Worker role defaults keep what the role does not intend to withhold:
  every built-in role keeps network reads; `planner` may run read-only
  shell probes; `custom` inherits the parent's write/network/shell posture
  and is narrowed only by its explicit tool list or the spawning call.
  Read-only roles (`scout`, `reviewer`, `planner`, `verifier`,
  `consultant`) still never write the workspace. The focused worker's
  header states its effective posture from the runtime snapshot.
- `/workflow status`, `/workflow cancel [run_id]`, `/workflow settings`, and
  `/workflow help` are answered by Codewhale itself from the run journal and
  live run state — no model turn — and `/workflow run <path>` launches a
  checked-in workflow as-is. `/config workflow` and `/config goal` explain
  the effective tables. The workflow tool now honors the session `[workflow]`
  table (`automatic`, `auto_start_read_only`, `require_approval_for_writes`,
  limits) instead of product defaults.
- Goal mode enters as readily as DeepSeek Harness: the agent may create the
  session goal when a direct request describes a verifiable multi-turn end
  state, and Codewhale shows a one-line `Goal set` receipt with how to pause
  or clear it. Bare `/goal` shows plain progress (and how to continue when no
  turn is running), prints usage on an empty session instead of asking the
  model, and `/goal help|status` are reserved words.

- Whale Teams in the terminal: the six Signal Cut whale identities (Scout,
  Patch, Harbor, Echo, Keel, Lantern) appear as species badges on `/fleet`
  roster rows and worker rows, with an identity portrait in the roster detail
  pane and a six-state word (Resting, Thinking, Working, Waiting for you,
  Blocked, Offline) derived only from the child's real runtime status. Colors
  come from the theme tokens, every glyph has an ASCII fallback, and the
  working wake animates only under full motion. See
  `docs/design/WHALE_TEAMS_TUI.md`.
- A session metrics strip on the phase row (`4 turns · 108 steps │ LLM
  11m46s · Tool call 1m52s │ TTFT avg 1.5s · 120 tok/s │ Cache hit 99% │
  Input 9.3M`), on by default as the `session_metrics` footer item
  (`/statusline`, `[tui].status_items`). Every value comes from engine
  receipts — turn starts, per-model-call usage with stream time,
  time-to-first-token and whole-call time, tool start/complete edges, and
  provider-reported cache and input tokens. Cells without evidence are
  omitted, never estimated. `/status` prints the untrimmed line; the phase
  row sheds its lowest-value groups to fit the columns it actually has.
- Auto-Review decisions nobody was prompted for are now visible in the
  transcript as one-line notes: model-guardian allow/deny verdicts with
  their risk tier and stated reason, guardian failures (denied, fail
  closed), deterministic policy blocks, and holds Auto-Review denied
  without pausing. The audit log keeps the full record. `/permissions`
  ends with the active posture, what it decides on its own versus never,
  and the audit-log path. The footer's `Esc to interrupt` hint is
  localized. See `docs/design/AUTO_MODE_PARITY.md` for the Claude Code /
  Kimi Code parity ledger and follow-ups.
- `codewhale integrations dsh status|plan|connect|update|launch|disable|enable|remove`
  connects an existing official DeepSeek Harness (`dsh` 0.1.0-rc.6, verified)
  through Codewhale using only its documented seams: a `--patch` overlay that
  pins the exact Codewhale provider/model/endpoint identity (native
  `deepseek-official` route, or a hand-declared `openai-completions` route
  named `codewhale-<provider>` for OpenAI-compatible providers), the
  Codewhale permission posture exported as `DSH_PERMISSION_MODE`, and an
  append-only receipt. Codewhale writes only under
  `$CODEWHALE_HOME/integrations/dsh/`, never copies API keys or edits DSH
  files, never broadens permissions (`--allow-full-access` only mirrors an
  existing Codewhale full-access posture), and reports not-installed /
  offline / incompatible / detected / connected / stale-config /
  stale-version / disabled honestly. Anthropic Messages and OpenAI Responses
  routes are refused as not carriable. The documented DSH plugin path is an
  explicit opt-in: `install-bundle` materializes a Codewhale bundle package
  (`codewhale-dsh-bundle`, MIT notice retained) and installs it with
  `dsh plugin --profile codewhale add <path>` into a dedicated `codewhale`
  profile (pnpm required, reported truthfully when missing; `web`/`headless`
  untouched), so `dsh --profile codewhale` alone carries the identity;
  `update` regenerates the bundle patch and `remove-bundle` reverses it,
  leaving the DSH-owned profile directory in place. `/setup tools` and `codewhale doctor`
  show the read-only detection state; `doctor` also lists the DSH read-only
  credential consent alongside Codex and Grok. The optional `--skin` export
  writes a Codewhale token stylesheet generated from the TUI palette
  (Blue Stage dark/light, ombre water column, mode/permission/state colors,
  reduced-motion fallbacks); DSH exposes no custom-theme API, so the sheet is
  labeled an unsupported overlay and is never injected. See
  `docs/INTEGRATIONS_DSH.md`.

### Fixed

- Selecting the `google` provider kind resolved to the `antigravity`
  TUI identity (and vice versa): the agy provider entry was inserted at
  different positions in the config-level enum and the TUI's
  discriminant-indexed lookup table. The table now matches the enum, so
  provider pickers, sorted display, and kind round-trips are correct.

- The provider picker's key-entry stage accepted typed input and pastes
  for OAuth-only providers after `antigravity` declared OAuth
  acquisition; those gates now key off the OAuth acquisition class
  instead of a hard-coded provider identity.

- The webhook hook sink no longer panics when its HTTP client fails to
  build; it falls back to a default client (#5381, EvanProgramming).

- Session-index JSONL writes are serialized behind a process-wide mutex
  so concurrent state stores cannot drop an append during compaction
  (#5382, EvanProgramming; complements the cross-process file lock).

- A billed `max_tokens` stop followed by a transport error fails the turn
  instead of continuing into a second request. A clean output-limit stop
  still continues. Mid-size context windows keep the ordinary 65K internal
  reservation so compaction does not collapse to the 1K headroom floor
  when the catalogue documents a matching output ceiling.

- Thinking cycle, `/effort`, and Settings now walk each model's real ladder
  instead of the DeepSeek off/high/max shortcut. Grok 4.6 is
  auto/low/medium/high/xhigh (cannot disable); Grok 4.5 is
  auto/low/medium/high; first-party DeepSeek keeps a documented `low` tier.
  `/effort` persists and receipts through the same path as Ctrl+T.

- Google Gemini is its own backend (`/provider google`) on the official
  OpenAI-compatible route with thought-signature capture/replay and
  fail-closed replay for thinking models. Antigravity (`agy` 1.1.13) is
  a separate provider: consent-gated read-only import of the official
  CLI's login, then a text-only cloud-code stream
  (`/v1internal:streamGenerateContent`). Tools, images, and unknown SSE
  shapes fail closed. Gemini 3.7 Flash is not advertised until a live
  turn succeeds on this wire. The website 44-count still excludes
  Antigravity.

- DeepSeek Flash SSE on macOS no longer turns mid-character HTTP/2
  flushes into U+FFFD replacement characters (#5374). Invalid UTF-8
  fails the line instead of using lossy decode.

- `[workshop] read_result_max_bytes` and `tool_result_max_bytes` raise
  the model-visible read/tool-result floor; they never lower the
  compile-time defaults and cap at 2MiB (#5367).

- Fireworks and OpenCode Zen DeepSeek V4 Flash/Pro keep a bundled
  family rate when the live control plane is down, so session cost is
  not stuck on `unverified_live_pricing` (#5241). `kimi-k3` stays
  unpriced until a published rate exists.

- Provider setup ships a SenseNova OpenAI-compatible preset (`S`) on
  the published `https://token.sensenova.cn/v1` host (#5350). OpenCode
  Zen/Go stay first-class rows. Agnes has no published URL, so it has
  no preset.

- Privileged release workflows no longer restore rust-cache, sccache,
  or npm caches after checking out a caller-supplied SHA (CodeQL
  cache-poisoning #88–#106). Catalog drift no longer prints raw
  bundled/upstream blobs (#107).

- Cancelling a turn now cancels its foreground child agents with it.

- Empty compaction no longer wipes conversation history.

- Wide terminals and tmux panes fill the full available width again for the
  transcript and composer (#5322). The brief v0.9 session-shell side gutter
  is gone so expanding a pane rematerializes layout the same way shrinking
  does.

- The agent tool schema rejects empty calls.

- The local web client keeps recovered stream gaps closed, user questions
  answerable, manual bootstrap access intact, and streamed prose quiet for
  assistive tech.

- Website zh-Hans copy now says 宪章, matching the TUI pack (#5397,
  Lstarsky0).

- Public website provider facts include Google Gemini and Ollama Cloud
  (44 runnable routes). Antigravity stays credential-plane-only.
  Harvested from #5398 (Lstarsky0) with that correction.

- The website models page carries a truthful read-only settings preview
  built from repository facts; it never implies the site can change local
  configuration (#5370, #5411, mvanhorn).

- The canonical `ultra` reasoning effort now maps to each provider's
  maximum tier alongside the legacy `ultracode` alias, instead of being
  silently dropped (#5303, #5409, buiducnhat).

- Session titles truncate by character count, not byte offset, so
  multi-byte titles (CJK, emoji) cut at the intended width and word
  boundary instead of past the limit (#5415).
- Wide terminals and tmux panes fill the full available width again for the
  transcript and composer (#5322). The brief v0.9 session-shell side gutter is
  gone so expanding a pane rematerializes layout the same way shrinking does.
- The background verifier test drives the current libtest executable
  instead of the rustup `rustc` shim, so the TUI suite no longer depends
  on `$HOME` or holds the process-wide test environment lock across an
  async wait (#5056, #5423, Isabel Wu).

### Removed

- The source-structure budget ratchet (CI step, checker, baseline JSON).
  It measured line counts, not quality: every legitimate feature required
  a hand-edited ceiling and the accompanying "review" was self-review, so
  it bought ceremony, not protection. Behavior-measuring gates (dead-code,
  runtime-contract, persistence-backlog) stay enforced.
- DeepSeek can reuse a key already stored by official DeepSeek Harness
  (`dsh`) after
  `codewhale auth external-consent --provider deepseek --mode read-only`.
  Codewhale reads only `DEEPSEEK_API_KEY` from the exact granted
  `$DSH_HOME/.credentials.yaml` and never writes or refreshes that file.
- The TUI markdown parser now honors CommonMark fence-length rules: a ````
  opener is not closed by a shorter ``` line, so `>` content inside a longer
  fence stays literal code instead of escaping into a quote.
- Sub-agents finalize when the parent session id changes, so a closed
  session cannot block new children as a live owner (#5372).
- Child spawn-route receipts stay live and usage is deduped by response
  (#5366).
- Doctor keeps persisted setup readiness across first-run / update
  checkpoints (#5340).
- Approval default selection is applied and explained; agents are told
  when approvals are disabled (#5293).
- A `/models` 2xx probe is a connection check, not model readiness.
- Site layout uses one container, the ticker no longer implies false
  provider readiness, and install links stay in the active locale.

## Contributors

- EvanProgramming (@EvanProgramming) — webhook client panic fallback
  (#5381); session-index JSONL mutex (#5382).
- Lstarsky0 (@Lstarsky0) — session peek hides internal runtime events
  (#5376); thinking-ladder test re-pin (#5378); provider-count follow-ups
  (#5383/#5384); macOS agy fixture canonicalization (#5392); zh-Hans 宪章
  terminology (#5397); regenerated website facts harvested and corrected
  from #5398.
- Matt Van Horn (@mvanhorn) — read-only models settings preview on the
  website (#5411, fixes #5370).
- Nhat Bui (@buiducnhat) — canonical `ultra` reasoning effort mapped across
  provider effort tables (#5409); session titles truncated by character
  count, not byte offset (#5415).
- Sh1Zuku (@SparkofSpike) — `/title` and the session name in the terminal
  tab/window title, plus the mid-turn title deadlock fix (#5419).
- Kai Nacke (@redstar) — Eden AI provider registration, aliases,
  `EDENAI_API_KEY`, and the global/EU endpoints (#5422).
- Isabel Wu (@wuisabel-gif) — background verifier test isolated from
  rustup and `$HOME` (#5423, slice of #5056).

See [CHANGELOG.md](https://github.com/Hmbown/CodeWhale/blob/main/CHANGELOG.md) for full notes and [docs/CHANGELOG_ARCHIVE.md](https://github.com/Hmbown/CodeWhale/blob/main/docs/CHANGELOG_ARCHIVE.md) for older releases.