Skip to content

v0.9.8

Choose a tag to compare

@github-actions github-actions released this 16 Aug 19:25
· 1257 commits to main since this release
f0a5c52

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)

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

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)

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):

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:

# 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.

  • 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 for full notes and docs/CHANGELOG_ARCHIVE.md for older releases.