v0.9.8
Codewhale is the public product from Shannon Labs. The
codewhale
command, npm package, and release-asset names remain lowercase technical
identifiers. The legacy npm packagedeepseek-tuiis deprecated and
receives no further releases. Users coming from v0.8.x legacydeepseek/
deepseek-tuinames should migrate withdocs/REBRAND.md.
Install
Recommended — npm (one command, both entrypoints)
npm install -g codewhaleThe wrapper downloads the matched codewhale and codew command assets
from this Release. Both contain the same compiled runtime.
Docker / GHCR
docker run --rm -it \
-e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \
-v codewhale-home:/home/codewhale/.codewhale \
ghcr.io/hmbown/codewhale:v0.9.8The image exposes the same runtime as both codewhale and codew. The
latest tag is also updated on release.
Cargo (Linux / macOS)
cargo install codewhale-cli --lockedThe 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):
tar xzf codewhale-<platform>.tar.gz
cd codewhale-<platform>
./install.shWindows:
- For the installer path, run
CodeWhaleSetup.exe; it installs
codewhale.exeandcodew.exeunder
%LOCALAPPDATA%\Programs\CodeWhale\binand adds that directory to the
current-user PATH. - Extract the archive for your machine:
codewhale-windows-x64.zipor
codewhale-windows-arm64.zip - Run
install.bat(copies to%USERPROFILE%\bin) - Add
%USERPROFILE%\binto 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:
# 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-missingWhat'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(andsu/setuid helpers) work again for wheel-group administrators
who want Codewhale to be able to escalate: the Linux startup hardening's
irreversiblePR_SET_NO_NEW_PRIVSflag — inherited by every child process —
is now skippable withCODEWHALE_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 statsshows the pin reason, the last-miss
reason, the undeclared-drift count, and the context-update count. See
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|installcompletes the
federated marketplace journey (#5311).addreads 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/showrender every candidate with per-entry diagnostics,
display-only tiers, and honest install plans that say when Codewhale
cannot fetch a source;installroutes through the existing reviewed
installer, so installed bundles still enter disabled and untrusted.
Foreign auto-install policy (CodexINSTALLED_BY_DEFAULT) is visibly
ignored; nothing is auto-installed, auto-trusted, or granted vendor
trust. -
/rcattach now includes an observedowner/namegit 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.3is live on the Coding Plan and is now the default direct
Z.ai model:DEFAULT_ZAI_MODELresolves toGLM-5.3in both
codewhale-tuiandcodewhale-config, and it is the first/modelrow
after/provider zai. ExplicitGLM-5.2selections (model = "GLM-5.2"
and itsglm-5.2aliases) keep their own id — only the default moved.
Limits and reasoning options still inherit fromGLM-5.2until 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-compatiblehttps://ollama.com/v1route. Local
Ollama stays keyless. The exact releasedollama+ 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
codewhaleformula.brew tap Hmbown/deepseek-tui && brew install codewhaleis the install path;brew upgrade codewhale
updates it. The legacydeepseek-tuiformula 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,
aliaseseden-ai/eden_ai) withEDENAI_API_KEY, global and EU base-URL
overrides, a live provider-scoped model catalog, and
deepseek/deepseek-v4-proas 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;plannermay run read-only
shell probes;custominherits 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 helpare 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 workflowand/config goalexplain
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-lineGoal setreceipt with how to pause
or clear it. Bare/goalshows 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|statusare 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 thesession_metricsfooter 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./statusprints 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'sEsc to interrupthint is
localized. Seedocs/design/AUTO_MODE_PARITY.mdfor 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 (dsh0.1.0-rc.6, verified)
through Codewhale using only its documented seams: a--patchoverlay that
pins the exact Codewhale provider/model/endpoint identity (native
deepseek-officialroute, or a hand-declaredopenai-completionsroute
namedcodewhale-<provider>for OpenAI-compatible providers), the
Codewhale permission posture exported asDSH_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-accessonly 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-bundlematerializes a Codewhale bundle package
(codewhale-dsh-bundle, MIT notice retained) and installs it with
dsh plugin --profile codewhale add <path>into a dedicatedcodewhale
profile (pnpm required, reported truthfully when missing;web/headless
untouched), sodsh --profile codewhalealone carries the identity;
updateregenerates the bundle patch andremove-bundlereverses it,
leaving the DSH-owned profile directory in place./setup toolsandcodewhale doctor
show the read-only detection state;doctoralso lists the DSH read-only
credential consent alongside Codex and Grok. The optional--skinexport
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
googleprovider kind resolved to theantigravity
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 afterantigravitydeclared 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_tokensstop 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 documentedlowtier.
/effortpersists 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 (agy1.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_bytesandtool_result_max_bytesraise
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 onunverified_live_pricing(#5241).kimi-k3stays
unpriced until a published rate exists. -
Provider setup ships a SenseNova OpenAI-compatible preset (
S) on
the publishedhttps://token.sensenova.cn/v1host (#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
ultrareasoning effort now maps to each provider's
maximum tier alongside the legacyultracodealias, 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 rustuprustcshim, so the TUI suite no longer depends
on$HOMEor 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 onlyDEEPSEEK_API_KEYfrom the exact granted
$DSH_HOME/.credentials.yamland 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
/models2xx 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
ultrareasoning effort mapped across
provider effort tables (#5409); session titles truncated by character
count, not byte offset (#5415). - Sh1Zuku (@SparkofSpike) —
/titleand 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 for full notes and docs/CHANGELOG_ARCHIVE.md for older releases.