v0.9.9
windmill-labs/windmillv0.9.9Aug 18, 2026by github-actions[bot]
AI Summary
v0.9.9 prioritizes truth and resilience by honestly labeling unverified context windows and output ceilings. It fixes the shell tool's behavior when the host runs out of disk space or file descriptors.
Key Highlights
- Shell tool no longer wedges when disk is full or descriptors are exhausted.
- Context-window honesty labels guesses at every surface (status line, picker, etc.).
- Output-ceiling honesty labels unverified limits as 'assumed floor'.
- Fleet read-only shell carve-out is now honored by execution envelopes.
- `/rename` and `/title` now apply mid-first-turn.
New Features
- Best-effort spill handling for full temp volumes.
- Context-pressure messages and model picker chips updated to show honesty status.
- Fleet operator/member precedence handling for read-only commands.
- Session checkpoint rebuild for title and rename operations.
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.9 ``` 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.9 Codewhale v0.9.9 is a truth-and-resilience release: the shell tool can no longer wedge a session when the host runs out of disk or descriptors, unverified context windows and output ceilings are labeled honestly at every surface, DeepSeek V4 is priced on the published peak/off-peak tiers, SSE UTF-8 fails closed in every dialect, Fleet shadowing is visible, bwrap gets container essentials and extra roots, the `dsh` skin rides the bundle profile, the `agent` tool schema is down to 12 fields, and README/website locales grow to 18 and 8. ### Fixed - The lowercase `bash` tool no longer wedges when its complete-output spill file cannot be created: a full temp volume or exhausted descriptor table used to fail *every* call — `echo ok` included — with the harness-internal "Failed to create streaming shell output" and never recover until the host was cleaned up. The spill is now best-effort (the bounded tail is still returned and the truncation notice says why the full-output path is missing), and any remaining spawn/stream failure names the exhausted resource — disk, file descriptors, memory — and says the next call is safe to retry (#5465; the wedge that took out the owner's own 0.9.9 session). - A concrete route/offering output limit now outranks the conservative 8,192-token compatibility guess for an uncatalogued model. Routes that publish no output limit remain fail-closed, documented model ceilings stay authoritative, and a route limit can never raise the requested cap (#5460). - Context-window honesty at every surface (#5239, #5441): the `model-name hint` and `fallback` rungs of the context-window ladder are guesses, and every surface that renders one now says so — the status line, `/status`, `/config`, the context-pressure message, the model picker chips, and the auto-router inventory. Unverified windows still drive real budgets (compaction trigger, context meter, output reservation); they just stop reading as capabilities anyone checked. A window parsed from an `_Nk` model-name suffix (`qwen3-32b-256k` → 256K) is now its own `model-name hint` rung below `catalog`, because it is optimistic rather than conservative — a catalog or provider-reported value beats it. The `[providers.<name>] context_window` override remains the hard fix and renders as `configured` with no marker. - Output-ceiling honesty (#5440): an Anthropic-family model the catalog does not describe keeps the 64K Messages floor as its clamp and the ChatGPT/ Codex OAuth route keeps its 4K policy, but `OutputCeilingSource` gained an `unverified` rung for both, so exec-stream receipts and the model picker label them `unverified`/"assumed floor" instead of `documented`. Clamp values are unchanged. - Telemetry default-on is visible (#5441): `codewhale doctor`'s runtime-posture section gained a `telemetry=on (default)`-style row with the source that decided it (cli | env | config | default), and `codewhale config get telemetry` reports the resolved consent with its source instead of `key not found` on a machine whose batches ship. Truth change only; resolution and behavior are untouched. - Fleet: a scout's read-only shell carve-out (#5428) is now honored by both the posture gate and the execution envelope, so `git log`, `find | head`, `npm view` and the other bounded read-only commands run in-place instead of being refused as "Executes" (#5426). Delegation still never widens authority: the role-isolation test and docs/SUBAGENTS.md pin that a child cannot exceed its parent's posture (#5426, #5435). - `/rename` and `/title` now apply mid-first-turn: the session file does not exist until the first autosave, so the rename fell through with NotFound; the shared path now prefers the per-session checkpoint and rebuilds from App state, with a PTY regression test through the live event loop (#5430). - `integrations dsh plan` no longer refuses DeepSeek's default Responses-dialect route (`deepseek-v4-flash`); Responses and Anthropic-Messages routes are carried through pi-ai `openai-responses` / `anthropic-messages` instead of being approximated or refused; only credentialed base URLs are still refused, with an error that names provider and model (#5434). - Session cost no longer sits at `unverified_live_pricing` when live pricing cannot be verified (control-plane 503, Models.dev capabilities-only overlays): provider-docs bundled fallback rates for the DeepSeek V4 family on Fireworks / OpenCode Zen restore a usable figure, live per-provider rows still win, and `kimi-k3` stays unpriced until a published rate exists (#5241; harvested from #5402). - Release assets: `release.yml` asset-freshness checks compare against the release job's own `started_at`, so job-level reruns of the npm step are no longer poisoned by earlier uploads (#5429). - macOS CI: the `agent_focus_pty` auto-review receipt test waited on a worker that had already completed and raced the rail's focus; it now holds the child's wrap-up and waits for a settled live row (refs #5056, #5403). - DeepSeek V4 pricing follows the published peak/off-peak tiers (peak 01:00–04:00 and 06:00–10:00 UTC; off-peak is half of peak) for `deepseek-v4-flash` and `deepseek-v4-pro` in USD and CNY, resolved from each turn's recorded time; the stale single-tier rows understated cost up to ~4×. Because every direct DeepSeek first-party rate is now time-windowed, the scorecard fails closed (`missing_recorded_time`) on an undated DeepSeek turn instead of guessing a tier (#5470; #5241 follow-up, verified against api-docs.deepseek.com on 2026-08-17). - SSE UTF-8 split across HTTP/2 DATA frames now fails closed in every streaming dialect: a shared strict decoder, tail flush, and `decode_failed` propagation (`InvalidSseUtf8`) replace the per-dialect approximations, with byte-chunk decoder tests (#5374; supersedes draft #5404). - CI: `release_four_read_only_fleet_roles_launch_with_canonical_prompts` answered Fleet children with SSE while they call the blocking JSON path; the parse failure was retried and double-counted the worker on slow macOS runners (#5471; refs #5056). - Context: every web tool surface (`Web`, `web_search`, `web.run`, `fetch_url`) now uses the noisy-result soft limit, so large fetches are compacted like shell output instead of consuming the ordinary hard limit (#5474, thanks @h3c-hexin). - Routing: a lowercase saved selector such as `glm-5.2` resolves against the owning Z.ai / DeepSeek catalog row (case-fold fallback, only when exactly one provider-owned wire id matches) instead of being classified as another provider's bare model (#5475, thanks @h3c-hexin; diagnosis by @asto18089 in Pinvou/CodeWhale#14). - Model catalog brought current as of 2026-08-17 against the official pricing pages: gpt-5.6-terra / gpt-5.6-luna rates, `claude-sonnet-5` keeps $2/$10 (the announced September increase was withdrawn), `claude-opus-5` added, `kimi-k3` and `kimi-k2.7-code-highspeed`, `MiniMax-M2.7-highspeed`, Mistral first-party rows, xAI `grok-4.5` / `grok-4.3` with long-context tiers, Gemini and Qwen limits, and RedNote's `dots3-note` preview as an OpenRouter row (no first-party API exists yet) — every number carries its source and a pinned test (#5485). - Website: copy on codewhale.net rewritten in plain declarative sentences — one idea per sentence, numbers from the generated facts, no self-narration — with a voice sheet at docs/design/WEB_VOICE.md (#5483). - CI: the release workflows no longer restore npm/cargo caches after checking out a caller-supplied SHA — the CodeQL cache-poisoning Highs #88–#107 are closed with a contract test over the workflow files (#5463). - Compact TUI rows below 60 columns no longer reserve a hidden session-metrics strip, so narrow terminals reclaim the row instead of clipping the transcript (#5486). - Ghostty's truecolor underwater field now uses a dedicated synchronized 60 FPS lane instead of the legacy 30 FPS compatibility cap, with continuous caustic fades replacing visibly stepped color changes. - Live reasoning's advertised `Space:expand` action now runs before the composer's first-character paste-burst hold, while spaces in an active paste remain payload. The newest reasoning preview also spends only genuinely free viewport rows before truncating instead of stopping at the fixed 10/12-row fallback on roomy terminals. - Strict `cargo doc` builds no longer fail on bare URLs in rustdoc comments; the remaining links are explicit Markdown targets (#5489). ### Changed - The model-facing `agent` tool advertises exactly 12 fields — `action`, `prompt`, `type`, `profile`, `name`, `agent_id`, `message`, `until`, `detached`, `worktree`, `write_roots`, `resume_from` — down from 33 (#5324, refs #5123). Budgets (`max_steps`, `wall_time_secs`, `max_depth`), routing overrides (`model`, `model_strength`, `thinking`), worktree-path knobs, the deliberate/spawn-contract fields and the wait/status/interrupt extras moved off the advertised schema. Every removed field stays parse-accepted and honored unchanged (same contract as `token_budget`), so saved transcripts, ACP/MCP clients and Fleet configs replay as-is; the #5426/#5435 containment clamps are untouched. Child budgets now resolve from role defaults (60/120 turns, 1800 s wall time, unchanged clamps) and new `[subagents]` keys `default_max_steps` / `default_wall_time_secs`. Because the tool catalog is part of the session-pinned prompt prefix (docs/CACHE.md), upgrading re-fills the KV prefix once per session. - TUI prose — user messages, assistant answers, and reasoning/thinking — now wraps at the full content width on wide terminals, matching tool/status cells, instead of stopping at a 105-column rail that left a dead right margin on ultrawide displays (#5436). - Configured skill prompts are stable across session roots and operating systems: only custom configured roots hide their physical path, ordinary workspace/global skills keep a discoverable privacy-safe path, warning replacements are boundary-aware (including non-UTF-8 Unix paths), and Windows separators render as `/`. The skills prompt is also 50 bytes leaner without raising a runtime-contract ceiling (#5492, #5473). - Auto-router classifier requests accept `[auto.router] timeout_secs`, while preserving the existing default when the key is absent (#5494). - Every `ci.yml` job now has an explicit 10–90 minute timeout appropriate to its workload, bounding stale assigned runners instead of inheriting GitHub's six-hour default (#5495). - The docs shell and shared web components now route localized copy through the typed dictionary spine; these are two incremental phases of #5337, not completion of the full epic (#5488, #5490). - Dependency: rusqlite 0.40.2 (#5391). - Documentation: stale A/B/C-tier references, provider defaults, module descriptions, and line anchors now match the current code (#5481). ### Added - `[transcript] prose_measure` (positive integer, optional): caps prose wrap at N columns for owners who want a bounded reading measure on ultrawide terminals. `0` or absent keeps the full width; negative or non-integer values are rejected with a clear config error. Tool, diff, and status cells never inherit the cap (#5436). - Localization: README translations for Français, Deutsch, 繁體中文, हिन्दी, Türkçe, Italiano, Polski, العربية and Català join the existing nine (#5451); codewhale.net routes fr, de, ca, hi, tr, it, pl and ar (with `dir="rtl"` plumbing) as partial locales (#5453). - Docs: README Integrations section (incl. the DeepSeek Harness `dsh` plugin path, docs/INTEGRATIONS_DSH.md) localized across all READMEs; RFC keeping the deterministic-first auto-review hybrid (#5427); Claude Code parity reference for agents/workflows/plugins/skills (docs/design/CLAUDE_CODE_PARITY.md); config.example.toml / SUBAGENTS.md / TOOL_LIFECYCLE.md brought back in line with the code (#5447). - `dsh` integration: the Codewhale palette is applied through the bundle profile via dsh's documented `overrideTokens` (on by default; `codewhale integrations dsh update --skin false` turns it off), replacing the 0.9.8 exported-CSS skin that dsh's inline body variables overrode (docs/design/DSH_BUNDLE_SKIN.md, docs/INTEGRATIONS_DSH.md) (#5469). - `dsh` integration: an ambient ocean scene behind the DSH web UI — slow whale silhouettes, a school of `><>` glyph fish, bubbles — drawn on a canvas under a translucent veil of the Codewhale palette, plus an explicit responsive `WHALE BROTHERS / CODEWHALE × DEEPSEEK HARNESS` lockup; light and dark, ~30 fps capped, paused when hidden, a static frame under `prefers-reduced-motion`; on by default with the skin, `codewhale integrations dsh update --ocean false` turns it off (#5484). - Fleet: agent shadowing is visible — a roster-row badge, a Layers block in agent detail, and a `doctor` "Fleet roster layers" section (JSON `operate_fleet.roster.multi_layer`), in all 15 TUI locales. Layer collapse and `[fleet.profiles]` migration stay for 0.9.10 (#5098). - Sandbox: bwrap containers get the `--dev/--proc/--tmpfs` essentials plus configurable extra roots (`bwrap_ro_roots` / `bwrap_dev_roots`) so toolchains that live outside the workspace stay reachable read-only (#5410). - Tests: `crates/tui/tests/README.md` states the keyless assembled-journey rule and maps the Auto-Review guardian acceptance items to the engine journeys that exercise them (#5361). - OrcaRouter's default endpoint is classified as an aggregator billing surface, so pricing and session-cost reporting use the correct billing posture instead of treating it as a first-party provider (#5493). - Dependencies: ratatui 0.30.2, thiserror 2.0.20. ### Removed - `dsh` integration: the exported-CSS skin file and its "skin export" status line (superseded by the bundle-applied `overrideTokens` skin, #5469). ## Contributors - hexin (@h3c-hexin) — a concrete route/offering output limit outranks the 8,192-token compatibility guess for an uncatalogued model (#5461, closes #5460); web tool results use the noisy soft limit (#5474); owned direct model casing resolves safely (#5475); and configured-skill prompts stay stable across ephemeral roots and operating systems (#5492, #5473). - Gabriel-Degret (@Gabriel-Degret) — configurable auto-router classifier timeout (#5494; first contribution). - @asto18089 — diagnosed the Z.ai `glm-5.2` casing collision and wrote the first provider-scoped fix in Pinvou/CodeWhale#14 (carried upstream in #5475). - Reports and reproductions that shaped this release: @hardy922 (context- window honesty, #5239), @redstar (bwrap extra roots, #5410), @all-lopezg (SSE UTF-8 garbling on DeepSeek Flash, #5374), @alitvak69 (unverified live pricing, #5241), and @wuisabel-gif (the macOS filtered-suite hang investigation on #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.