发布说明

Codewhale 0.10.2

发布于 2026年10月22日。以下是该版本的全部条目,取自仓库中的 CHANGELOG.md,条目原文为英文。

Latest fixes242

  • Linux sandboxed terminals deliver Ctrl-C to the foreground program without killing the bubblewrap wrapper. A program that handles SIGINT can keep running and accept more input. PTY jobs and persistent terminals retain their sandbox and process-tree cleanup; this path requires util-linux setsid.
  • Full Engine integrations now point explicitly to codewhale app-server --http. Compatibility HTTP, stdio and socket turns require allowed_tools: [] and reject interactive execution and goal starts before work begins, closing the approval and clarification dead end. ACP new/load rejects unsupported supplied MCP servers instead of silently ignoring them; ACP v1 MCP support remains partial. The Runtime SDK guide states its Fleet/event coverage and provides authenticated HTTP examples for the remaining client controls.
  • tokio moves to 1.53.3, which retires RUSTSEC-2026-0386. The advisory covers tokio::io::unix::AsyncFd's safe constructors accepting a file descriptor they do not own; the lock now sits in a range the advisory lists as patched, and Codewhale never calls AsyncFd at all.
  • A signed-in ChatGPT account refreshes its model list at launch. The plan roster was only fetched at sign-in or on an explicit models --update, so an account that never re-authenticated kept reporting models it no longer offers and never heard about new ones; the launch sweep that refreshes the other catalog layers now refreshes a missing, stale or invalid roster too, at the cost of one freshness probe when it is current. A roster past its 24-hour limit also lists its last known models instead of none, and only a fresh fetch supplies the preferred default.
  • Two sessions can share one folder again. The embedded TUI runtime mounted its delegated-coordination lock exclusively, so a second codewhale in a workspace that already had one running was refused with another Codewhale process owns delegated coordination for <workspace>; codewhale resume <session B> beside a running session hit the same wall. The exclusive holder is now only codewhale serve, which the architecture doc already reserved it for (#7042).
  • A reasoning effort the route cannot honor is no longer sent to it. OpenAI wire requests resolve the session's effort through the row's declared ladder and clamp to the nearest rung upward, because gpt-5.5-pro declares only ["medium","high","xhigh"] and was being handed off and low, while gpt-5.5 and gpt-5.3-codex start at none and gpt-5.6* add max. An effort the row already declares is passed through untouched (#6396).
  • ChatGPT-plan routes report their reasoning controls. The plan roster carries only ids and labels, so every openai-codex row advertised reasoning_effort: unsupported with no levels at all. Rows are now joined against the merged catalog for the fields the roster leaves blank, and gpt-6-astra reports ["low","medium","high","xhigh","max"]. Context windows are deliberately not filled from that join: the plan snapshot's 272,000 describes a different wire than the 1,050,000 the catalog lists.
  • A boot that never reports back no longer claims to be connecting forever. The launch card's prediction for configured MCP servers now carries the moment it was made and retires after five minutes without a receipt, so a pass that dies before posting its finished event settles on the last known snapshot instead of leaving rows that never resolve (#7035).
  • python3 scripts/catalog_models_dev.py defaults audit is the release step that staleness needs: it re-reads a models.dev payload and reports every provider whose shipped default a newer stable row in its own namespace has overtaken, failing the run on an unrecorded one and taking an explained hold from DEFAULT_AUDIT_REASONS otherwise. And the anthropic default moves to claude-sonnet-5-5: a forced tool_choice is now softened to auto for Opus 5.5 and Sonnet 5.5, which reject it, instead of being sent and refused.
  • The model picker's browse views list models you can talk to. Catalog, New, Coding, Cheap and LongContext now skip image, embedding, video, speech, transcription, reranking and realtime rows — 445 of the 8,849 live catalog entries — instead of threading them between the chat models you were scanning for. Configured is untouched, so a route you already set up stays visible, and a search still reaches everything: typing an image model's id finds it.
  • The model picker can be read one provider at a time. Sort: Provider now prints a provider header for each block instead of one flat run of names, and ⇧T narrows the list to one provider at a time and clears on the next cycle; the title names the active filter and the footer advertises ⇧T beside ⇧A, so a shortened list is never unexplained. Choosing a provider sort also browses the whole roster rather than the rows the current view admitted, so one keystroke turns the Configured view into a full catalog grouped by vendor — which is what "sort by provider to find models" needs to mean.
  • openai-codex defaults to gpt-6.1-sol. Its ChatGPT plan roster served seven ids and no bare gpt-5.6, which the descriptor defaulted to: a fresh roster redirected the choice, but a stale, expired or absent roster sent a model the account does not serve and the request failed. codewhale models also stops claiming "availability not verified" for a route that did use a fresh snapshot, and now reports the real snapshot layer, fetch time and row count. The offline seed check compares every descriptor default against the seed default and refuses to write when they disagree, and seed lock --dry-run reports providers whose default a newer upstream id has overtaken, plus locked rows the spec no longer references. docs/CATALOG_REFRESH.md states the limit plainly: nothing offline can detect that a vendor shipped a model.
  • A persisted /models partition from an official endpoint no longer hides a newer catalog snapshot. openai listed a two-generation-old roster while the shipped snapshot already carried gpt-6-astra, gpt-6-luna, gpt-6-sol and gpt-6.1-sol, and refreshed anthropic and deepseek ids were suppressed the same way. A route that owns its live catalog (a relay, a private endpoint, a custom base URL) stays authoritative however old the fetch; an official endpoint's partition must be fresh to shadow the snapshot, and an unfresh one still contributes its own ids as an offline tail so a withdrawn model does not vanish by omission.
  • One catalog row without a price no longer costs you every model in its provider. models --update reported failed / cache_write_failed with model_count 0 for OrcaRouter while the endpoint answered 468 rows, because a row whose price was dropped still carried a live cost stamp and one such row rejected the whole refresh as invalid_response; the same all-or-nothing rule also discarded an entire cached scope on the next read. Rows are now judged one at a time, a refresh fails only when rows arrived and none survived, and a cached scope that loses every row to validation is still dropped rather than loaded. A failed refresh names its typed reason instead of cache_write_failed and still reports the rows you have left.
  • A new OrcaRouter session with no saved wire model defaults to deepseek/deepseek-v4.1-flash-1017. Every OrcaRouter catalog row has default_for_provider false, so the descriptor was the only thing deciding the default and it named an older model. The deepseek-v4-pro and deepseek-v4pro shorthands still select deepseek/deepseek-v4-pro on this provider, so naming a pro model never silently lands on Flash.
  • POST /v1/threads is replay-safe. A retry under the same operation_key returns the original thread — after a restart too — instead of minting a second one and orphaning the conversation; a changed request under the same key is refused with 409 rather than replacing or duplicating. The capability is advertised as thread_create_idempotency, and clients must require it.
  • A sandboxed shell can read a tool's own auth config again. The credential deny-list still refuses those files to Codewhale's file tools, but it no longer refuses them to the programs that own them, so gh, glab, aws, npm, cargo, docker, kubectl and git can authenticate from a read-only posture. Key material, keychains, other agents' credential stores and Codewhale's own secret stores stay denied to subprocesses.
  • The website and README link the supplied Codewhale × OrcaRouter offer graphic to its redemption page, with readable link text and referral disclosure.
  • Development test builds use a boxed future at the shared Engine event-loop boundary, keeping its large concrete async type out of callers. One local warm-build comparison fell from 29m 31s to 2m 24s with the same compiler, profile and features; this is not a cold-build or cross-platform guarantee.
  • Delegated workers no longer inherit model-selected turn, time or output caps, and the default 30-minute child deadline is removed. Launch receipts identify ignored legacy limits and show the limits that actually apply. The 75% child "wrap up" and 80% parent "stop exploring" prompts are removed, as is the instruction to give up after two failed tool calls. Explicit owner limits are no longer silently shortened to 100,000 turns or 24 hours. The stopship example also drops forced response counts and its two-call discovery limit. Children can use the final allowed turn for useful work; the host preserves partial results without reserving time or issuing an extra model request for a forced summary. Default child and workflow nesting caps are removed; explicit owner bounds still apply. Existing installations receive the updated delegation guidance while keeping customized or deleted skills intact (#7044).
  • Workflows can continue independent steps after a child fails, with dependent steps recorded as skipped. The cumulative 1,000-child cutoff is removed; owners can still configure a total child limit. Recursive work no longer stops at 25 rounds, three replies without code or printed output, or an invented enclosing or subquery deadline. Code-mode scripts can make more than 50 admitted tool calls. Cancellation, permissions and inherited owner deadlines still apply. Long-running live children are no longer treated as abandoned merely because 35 minutes passed.
  • Read-only workflow children receive their response schema in the first request; write-capable children keep the verification report contract. Unmetered workflow usage is shown as unknown instead of zero. Mode history follows changes between Plan and Operate, and /goal resume can restart an idle active goal without replacing its identity or clearing stall evidence.
  • ChatGPT sign-in opens your regular browser and returns to Codewhale with credentials and a model list for the account you selected. The unsupported originator parameter that caused invalid_authorize_request is removed (#6925). PKCE, account binding and granted-scope validation remain in place. A real browser sign-in, account model list and model response were verified for this release candidate.
  • Renaming a session in /sessions shows its title prompt once, preserving the validation and saved-title messages (#7054). Thanks @Lstarsky0.
  • Deferred-tool admission measures schemas after the provider's wire conversion. Search results show the active toolbox, soft-limit overflow and readmission state. Per-request receipts join those wire measurements with the current prefix change and reported usage, including separate transparent retries. Missing cache usage remains unknown; these receipts do not add charges.
  • The community website uses Next.js 16.4.1, which includes the upstream security fixes for cache deserialization, image optimization and Server Actions.
  • Haiku 4.5 metadata preserves its image input and extended-thinking support, keeping review output reserves consistent with its provider capabilities.
  • Clearing or replacing an OrcaRouter key cancels pending browser sign-in, including a code exchange already underway. A late callback can no longer restore the cleared key, and disconnecting the client does not interrupt credential cleanup.
  • Cloud Runtime provider keys can stay in process memory. Session-only mode disables saved-key, environment and OAuth fallback, keeps keys bound to their exact endpoint, and advertises support for memory-only set and clear. Clearing affects subsequent turns; already running turns retain their key. In-process subagents remain available; external Fleet execution is refused in this mode because its processes do not share the session-key overlay. Supervised HTTP servers can adopt a validated inherited loopback listener, preserving supervisor ownership across Engine restarts.
  • Opening a folder in the desktop Runtime no longer fails because a terminal session is already using it, including when attaching a second folder. Delegated workers still respect the folder's writer lock, including after a restart. If the Runtime starts without its own coordination lock, stop and restart its process after the other session exits to regain delegated writes. It cannot overwrite newer coordination records with the snapshot it opened earlier.
  • Credentials in tool-call arguments are now redacted before a session is saved. A command the model wrote with a key in it (curl -H 'Authorization: Bearer …', API_KEY=… ./run, a .env write) was stored verbatim in the saved session and journal and replayed on resume; only tool output was redacted. codewhale sessions scrub-secrets now also cleans tool arguments in sessions already on disk. [redaction] model_bound = false still lets the model see exact file bytes for edits, but no longer turns off redaction of what is written to disk.
  • Provider requests follow redirects only on the same host. A cross-host redirect or a downgrade from HTTPS to HTTP now stops the request, so an open redirect on a configured base_url can no longer collect an x-api-key header. The network guard also refuses IPv6 forms that reach private addresses: NAT64 (64:ff9b::/96, checked as its embedded IPv4 address), 6to4, Teredo, site-local and IPv4-compatible addresses. An MCP server can no longer grow the resource-template cache without bound, and a prefix allow rule no longer matches a command that adds shell metacharacters after the allowed prefix.
  • On Windows, a session in Russian or another language written in a non-Latin script no longer crashes the TUI with start byte index N is not a char boundary when Codewhale checks a shell command before running it (#7048). Thanks @8sero.
  • Computer Use can be authorized in Full Access. Asking for an app grant was refused before it ran, so the most permissive mode was the one mode where Computer Use could never work. Ask and Full Access now show the approval card; Auto-Review and Never still refuse, because nobody is there to answer it. A grant still always needs your answer and is never approved automatically.
  • A plugin state file larger than 1 MiB no longer makes every plugin fail to load. The limit is now 16 MiB, and the read stays bounded.
  • The OrcaRouter model list now shows only models OrcaRouter serves over Chat Completions, the protocol Codewhale uses with it. Models offered only through another protocol, such as Gemini-only image models, no longer appear and fail when chosen. OrcaRouter price estimates now include its long-prompt price tiers instead of quoting every prompt at the base rate; a model whose tiers cannot be read is shown without a price.
  • The first /pet on in a new session no longer shows Source changed; review the current source before interacting. The pet view acted on a frame older than the source it had just selected and sent a second, stale selection.
  • Resuming a session after Codewhale was killed mid-turn no longer undoes a rename or archive made while it was down, for example from the desktop app or the Runtime API. The interrupted turn is still restored. A restored session also no longer shows Codewhale's internal note about sub-agents still running in the background as a message you typed.
  • The Web tool now tells the model which JSONPath its fields option accepts ($, .field, [index], [*], ['field'], for example $.items[*].name) and that recursive descent (..) and filters are not supported, so it stops sending projections that fail. Thanks @zhuowp (#7046).
  • MCP servers are started, reconnected and stopped more carefully: - Editing your MCP config, or changing a plugin's MCP servers, restarts only the servers whose own entry changed. /mcp reload still restarts all of them. - /mcp retry no longer freezes the session while a slow server connects. - A tool call that loses its stdio server stops the dead process before reconnecting, so no second copy runs beside it. Sub-agents no longer start or supervise the parent's servers a second time. A Streamable HTTP server whose connection was cancelled reconnects. - list_mcp_resources, the resource-template list and /mcp validate (/mcp doctor) without a name report the servers already connected and the failures already recorded, instead of connecting every configured server. - /mcp login is no longer offered when the server's authorization server has no dynamic client registration and no oauth.client_id is set; the row says to set bearer_token_env_var or oauth.client_id instead. A token refresh no longer undoes a logout made in the meantime, and a token rotated by another process is picked up. - ACP sessions no longer start MCP servers they cannot use. With [features] mcp = false, MCP tools are neither listed nor run. The Runtime API's MCP management uses your [network] policy and OAuth callback settings. codewhale exec --resume starts MCP servers once instead of twice.
  • @git and @diff mentions and the review Git-config check stop after 10 seconds instead of freezing the TUI on a stalled git. They say "git command timed out" instead of "not a git repository", and one slow check no longer leaves later reviews asking you to upgrade Git. On Wayland, wl-paste and wl-copy get 2 seconds and are stopped if they hang, so a stuck clipboard no longer freezes the interface. Refs #6561.
  • The provider lists in first-run setup and /provider line up their status column; before, each status started wherever the provider name ended. Thanks @Lstarsky0 (#6984).
  • Runtime API: each pending_approvals[] entry, and approval.required on the authenticated thread surface, now carries the captured tool input. An omitted input means nothing was captured; an explicit null is a captured value.
  • The WeChat bridge (integrations/weixin-bridge) now stays inside what Tencent's ClawBot allows. A bot may reply only within 24 hours of your last message and a handful of times per message, so the bridge sends at most 8 replies per message you send (WEIXIN_MAX_SENDS_PER_MESSAGE). A longer answer ends with a "继续" prompt: reply 继续 for the rest. An answer that finishes after the window waits for your next message. An expired WeChat session (errcode -14) now pauses the bridge for an hour, as Tencent's own client does, instead of retrying forever. A rejected or rate-limited reply is held or backed off rather than resent every second. A reply that WeChat accepts without a message ID is reported by /status as possibly filtered.
  • WeChat approvals are now answered with a short code: reply 1 k7m2fz to allow or 2 k7m2fz to deny. Codes are single-use, expire after 30 minutes, and /status issues fresh ones; /allow and /deny still work. Questions the agent asks now reach WeChat, and your next message answers them, by option number or in words. A typing indicator shows while the agent writes. Chinese command aliases (/状态, /新对话, /停止, …) and /stop are available.
  • The WeChat bridge now accepts only the WeChat account that scanned the login QR code unless WEIXIN_CHAT_ALLOWLIST says otherwise. Other chats get one refusal that names their user ID, where they used to be dropped silently. A lock file stops two bridges from sharing one state directory, and dev-up.sh no longer allows every user by default.
  • Skill and plugin downloads and skills registry sync now check the first request and every redirect. They refuse localhost, loopback, private, link-local and cloud-metadata IP addresses and hosts the network policy denies, refuse a redirect from HTTPS to HTTP, and stop after five redirects. Without a proxy, Codewhale resolves each host itself, refuses private answers and connects only to the address it checked. With HTTPS_PROXY or HTTP_PROXY set (lowercase works too), these downloads go through the proxy unless NO_PROXY matches the host; Codewhale then leaves host-name checks to the proxy and checks only IP addresses written in the URL. ALL_PROXY is not used. If your [network] default is deny, allow codeload.github.com as well as github.com for GitHub skill and plugin installs.
  • NO_PROXY now accepts space-separated entries and * for MCP servers you configure and for skill and plugin downloads, an empty HTTPS_PROXY no longer hides HTTP_PROXY, and a socks5:// or socks4:// proxy is asked to resolve host names itself instead of Codewhale resolving them locally.
  • Local state no longer follows links planted inside a workspace or session directory. The continual-harness lock file must not be a link, workspace notes are appended without following links below the workspace, session snapshots refuse a linked or multiply linked session file, and saving a project Fleet profile checks existing project identities without following a linked profile directory or file. New lane records and lane logs are readable only by their owner.
  • The command splitter behind the destructive-command checks treats a backslash-escaped quote outside quotes as an ordinary character, as the shell does.
  • Outside Full Access, background and headless runs now stop for review before a disk- or filesystem-destroying command placed inside a subshell or a command substitution, including one inside a sh -c script.
  • Read-only agents and Fleet workers can now reach the network. In Full Access, bash with read_only: true allows outbound connections, so curl, git ls-remote and HTTPS clients work, while all local file writes stay blocked. read_only does not stop requests that change things on remote services. Ask and Auto-Review keep the mode offline, as do a [network] policy that defaults to deny and a role without the network grant. On macOS it reaches internet hosts over IPv4 and a local proxy set in HTTP_PROXY, HTTPS_PROXY or ALL_PROXY, but not IPv6 or any other port on the Mac's own addresses. On Linux it shares the host network namespace, including loopback and abstract unix sockets, like a networked workspace-write shell. A networked run is marked sandbox_network: true in its tool result, and codewhale run sandbox run --policy read-only --network now honors --network. Refs #7040, #5904.
  • Plugin suggestions no longer treat Codewhale's own vocabulary as a reason to offer a plugin. A message about MCP servers stuck at connecting, or one that mentions agents, code, data, models, sessions or tools, no longer offers an unrelated vendor plugin; distinctive names, phrases and domains still match. The first-party marketplace check rejects the same words as manifest keywords. Refs #7036.
  • When a route declares its own output limit in [[custom_models]], on a named custom (openai-compatible) route or a built-in provider such as OpenRouter pointed at your own endpoint, CODEWHALE_MAX_OUTPUT_TOKENS can now raise a request up to that limit instead of stopping at the bundled limit for a model with the same name. Automatic requests keep their usual size. Without a declared limit the bundled limit still applies, and on a named custom route run receipts label it unverified rather than documented. Refs #6396.
  • When a route publishes its own reasoning levels, Codewhale no longer refuses a level the route lists. It sends the level you chose, or the nearest level the route publishes, on Chat Completions routes and on named custom endpoints that use the Responses or Anthropic Messages wire, including /cache warmup. When a level still cannot be sent, the error names it and lists the levels the route publishes. Refs #6396.
  • codewhale resume and codewhale fork now size a saved session the way it is handed over: compact JSON, with the conversation counted once instead of also as its derived message copy. A session that is over 8 MiB on disk only because of that copy, indentation, abandoned branches or finished shell operations opens again. A session whose current conversation and Work state alone exceed 8 MiB is still refused before anything is written: its file and archive are left unchanged and the refusal gives the size it would hand over. Reading the history through the Runtime API or the desktop app still applies the 8 MiB limit to the whole document. Refs #6955. Thanks @7jrxt42BxFZo4iAnN4CX.
  • Saved sessions and crash checkpoints are now written as compact JSON instead of indented JSON. Files are smaller (16–27% on the two measured sessions from the report), and a session that was over the 8 MiB resume limit only because of indentation resumes again. Refs #6955. Thanks @7jrxt42BxFZo4iAnN4CX.
  • A codewhale resume or codewhale fork that is refused before it reserves anything no longer tells you to recover it with an operation key. Refs #6954.
  • The input, output and context limits your Codewhale account states for a model now apply to its requests. The desktop app and interactive sessions take them from the account's model listing, and codewhale exec, codewhale review and the workflow tool read that listing once before their first request; if it cannot be read, the run continues with built-in limits and says so on stderr.
  • When a route states an output limit larger than half its context window, as a server that shares one window between input and output does, Codewhale compacts the conversation to keep a quarter of the window (at most 64K tokens, and never more than the route's request cap) free for the reply, instead of reserving the whole request cap, which on a small window left about a thousand tokens for the conversation. A request is still admitted while at least 128 tokens of output fit, so Codewhale's own instructions and tools can fill more of a small window when there is nothing to compact. Every request on such a route asks for no more output than the window has left after its input, up to the route's usual request cap, so a long prompt gets a shorter reply allowance instead of overflowing the window. When too little is left, nothing is sent: a turn compacts or stops with the usual context message, a compaction summary leaves out its oldest history until at least half the reserved allowance fits, and any other request fails with a context-length error. Other routes are unchanged.
  • Once a session file passes 8 MiB, autosave moves all of its abandoned branch history to the session's journal archive, instead of keeping up to 4,096 off-branch entries in the document. /branch can still restore archived entries. Refs #6842. Thanks @7jrxt42BxFZo4iAnN4CX.
  • When a tool result is longer than the share of the context window one result may take, the model sees its head and tail and is told to read the rest with retrieve_tool_result. That tool is now offered whenever a result names a saved copy, and codewhale exec --allowed-tools no longer filters it out. A model on a small window, where most tool output is cut, is no longer told to recover output through a tool it does not have.
  • A window that cannot save its queued messages because it holds no queue lease for the current session now logs both session ids, and failed session, checkpoint and queue writes log the raw OS error code. Refs #6978. Thanks @SergiuSSoluS.
  • When the Linux sandbox cannot be set up (a bubblewrap mount error), the shell result says the command did not run, quotes the bubblewrap error and gives the ways forward, instead of the generic escalation hint. Nothing runs outside the sandbox, and each sandboxed call still fails while the cause remains. Refs #7007. Thanks @rafacouto.
  • Auto-Review stops a turn after three guardian denials in a row, or ten of the turn's last fifty reviews, and the status line says why; the remaining calls in that batch are refused without another review. Timeouts and failed reviews do not count. Refs #6478.
  • Runtime API: POST /v1/threads/{id}/read records the newest item a client has shown, and GET /v1/threads/summary now reports last_read_item_id and unread for each conversation. Marking a conversation read does not change updated_at or list order, and a marker never moves backwards. Refs #6164.
  • On Linux, a Runtime owner record from before the last reboot no longer blocks recovery when its process id has been reused.
  • The HarmonyOS guide now says the Linux ARM64 release runs inside the HarmonyOS PC Linux subsystem, an openEuler virtual machine, and lists Huawei's documented limits for it. It no longer describes a "glibc-compatible userspace", and native HarmonyOS stays on the source build. Refs #1072. Thanks @SakuraNeko.
  • On native HarmonyOS, npm still installs the Linux build as a best effort. If it cannot start, Codewhale prints directions to use the Linux subsystem or build from source. The install script also warns that the build is untested there; npm 7 and later show that warning only with --foreground-scripts. Refs #1072.
  • Fetching a page that builds its content with JavaScript no longer ends in a "no readable page content" error when the page has a title or description. Web fetch and web.run return those, marked partial, with a note that says why and what to try next. When a Playwright, Puppeteer, Chrome DevTools or Computer Use browser tool is connected, the note names it so the agent can render the page there. Refs #7038.
  • Web search through a model provider's own search tool now checks each cited link before returning it, so Codewhale contacts the cited sites directly. The check uses the same protections and [network] policy as Web fetch, runs at most four checks at a time for five seconds each, and never requests a link that repeats your search query. Links that do not load are dropped and listed in the search receipt. The provider's written answer moves to a separate unverified_synthesis field, and the result says how many of the requested sources passed. When none pass, or when you ask for recent results only, the search falls back to your configured search provider. A cited site your [network] policy denies is dropped; one the policy would ask you about stays in the results, marked as not checked, until you allow its host. A backend that returns fewer results than asked is reported as a shortfall instead of an honored result cap, and a cited page the provider left untitled is named by its path or host rather than shown as a bare domain. Refs #7039.
  • Searching for tools no longer unloads tools the agent is using. When the deferred toolbox is full, tool_search makes room from tools that were never called, then the least recently called, and keeps any tool called in the current or previous turn. Matches that do not fit, and tools it removes, come back with the exact tool_search input that loads them again. Refs #6969.
  • Rendered markdown keeps nested list indentation, a to-do row keeps its status word when its title is long, and the approval footer's separators sit between its hints. Thanks @Lstarsky0 (#7030, #7033, #7034).
  • Fleet tasks can choose an execution environment by declared data, capabilities, capacity, persistence and cost, with a preview explaining each decision (experimental). Configured Tailscale workers use a pinned node identity; placement and transport receipts preserve the selected environment and attempt. Declared resources do not reserve capacity.
  • A runnable WhaleNet example uses real DeepSeek tasks, Python and a TypeScript MCP server to create a bounded analysis capability and reuse it in a fresh task after the first worker exits. The example records usage, process lifecycles, content hashes and a one-hour capability lease.
  • ACP session history uses shared message recognition without depending on terminal rendering. Malformed archived-context text stays visible instead of panicking during history restoration.
  • Linux and OpenHarmony credential storage can traverse directories that allow access without directory listing. The private credential directory still requires current-user ownership and protected permissions; symlinks remain refused. Filesystem-root errors now include the OS cause.
  • Each file read and search keeps its own details when activity is grouped. Expanding the group and opening a selected item shows that call’s input and output instead of an arbitrary sibling’s.
  • Local Skills setup creates its example in the project folder Codewhale discovers, and its setup and doctor output explain the workspace trust requirement. Skills help now points to the searchable Skills view and distinguishes it from management.
  • Stopped shell jobs read as stopped instead of failed. Their detail view stays available after completion, a missing terminal exit code reads as unavailable, and delegated jobs identify their named agent. Refs #6931.
  • model list respects the selected route's catalog instead of adding unrelated bundled models. app/models reads the captured Runtime's current catalog, including named custom routes, regional routes, limits and capability facts. Model listing remains available during a running task and reports an unavailable owner instead of returning a stale static list. Refs #6396.
  • The model picker distinguishes stale catalogs and stale, unverified or unavailable pricing instead of calling them live or priced. Unknown reasoning support stays unknown, and unusable rates do not drive price sorting.
  • Automatic Rust formatting no longer inherits Engine or provider credentials. The formatter keeps its normal toolchain and project configuration.
  • If an exec session cannot be saved, text, JSON and streaming JSON now report the failure and exit unsuccessfully. The answer remains in the output, and the lifecycle receipt also records failure. This is not a retryable provider error: actions may already have completed.
  • Unrelated or malformed requests to the local OAuth callback no longer abort sign-in. The listener keeps waiting within the original deadline; state and issuer checks still apply, and an authenticated provider denial still ends the attempt.
  • Automatic goal turns no longer start with an obsolete objective when the goal is paused, completed, cleared or replaced while the turn is preparing.
  • Updated certificate validation, MCP, and web dependencies to address dependency security advisories.
  • Shell cards in the default view drop their output: and time: labels. Output rows follow without a label, and a command that ran for a second or more shows its duration after its status. Hidden output reads … (+27 lines) · Alt+V:output, translated, instead of 27 lines omitted. A thought shorter than a second reads Thought. A notice that mentions "cycle" is no longer drawn as a bold divider.
  • A shell card in the default view leads with the model's description, as written, and shows the command on its own $ row underneath, in every state and at every width. A card without a description leads with its $ command. A finished, successful command shows only ✓ (ASCII Y), without done; running, waiting for approval, queued, failed and "loaded, not run" keep their word, and a narrow terminal shortens the headline before the status. A failed card shows its whole command, up to six rows. The ▶ run marker, the note: label and the ╭ │ ╰ rail shared by neighbouring tool cards are gone in this view; card rows are indented under their headline instead. docs/ACCESSIBILITY.md now says that every status carries a glyph and every state except this one also carries a word. With show_tool_details = true and calm_mode = false the labeled card is unchanged.
  • ACP editors loading a saved session now receive its earlier messages and tool results instead of an empty conversation. Sessions saved by codewhale exec can also resume through ACP and the Runtime API. Saved reasoning and images are not replayed to the ACP editor.
  • Replayed ACP tool results and Runtime receipts created from saved history now use the live receipt masking rules: private question answers become User input submitted, and configured credentials are redacted. This also covers history import, fork and rewind. Saved model history and the owner's session-export view keep their existing behavior.
  • serve --acp refuses a second ACP owner in the same Codewhale home while still allowing an editor to attach to the desktop or HTTP Runtime. If that Runtime exits, the ACP guest exits with a recovery message instead of waiting for another line from the editor. An unsupported approval_policy = "never" is refused at startup, before it can fail every new session.
  • A web fetch stopped at max_bytes returns the readable text received so far, marked as truncated. If the cap arrives before readable text, the error names the cap and the available recovery instead of making a second request and misdiagnosing the page as JavaScript-only. Complete pages retain their normal extraction rules.
  • Windows state-file publication allows a longer retry window for transient sharing, locking and access-denied errors, reducing failures when another process briefly holds the destination. Permanent errors are still reported; the retry window is now about 1.27 seconds.
  • codewhale doctor --help lists the doctor's actual options. Account and dispatch help no longer promise unavailable account-key storage or cloud execution. codewhale review rejects --post and --repo with local-diff options before loading credentials or contacting a model.
  • /model reuses provider catalog data and route-readiness results instead of rebuilding them for every row. Its Auto hint no longer constructs the full model inventory. Thanks @SparkofSpike (#7026).
  • /feedback marks shortened descriptions, including with ... in ASCII-safe mode; /statusline shows a scroll rail when its list does not fit and then drops its padding rows, so a short terminal shows more items; and wide /keys layouts leave descriptions in the detail pane instead of repeating clipped fragments beside it. Thanks @Lstarsky0 (#7025, #7027, #7028, #7029).
  • DeepInfra lists newer DeepSeek model IDs alongside its existing defaults. The defaults remain unchanged pending a live route check, and the new selections do not reserve bare model names that other providers accept.
  • /undo takes back the latest request and its file changes without requiring trust mode, while refusing ambiguous snapshot matches. Trailing whitespace in a prompt label no longer prevents a match, and an empty first line in another request no longer blocks the whole conversation.
  • exec --auto help and documentation now state its default Full Access: automatic tool approvals, no Codewhale shell sandbox, and trust mode on. Selecting any sandbox other than danger-full-access, by flag or config, keeps trust mode off. This includes external-sandbox, which relies on host-managed isolation and no longer grants file tools trust-mode access. Stream metadata reports whether the requested sandbox is actually enforced.
  • Exec flags go before the prompt. A known long flag or --flag=value after the prompt now produces an error instead of silently becoming prompt text; use -- for literal flag text or a prompt starting with -.
  • Exec runs that offer tools save sessions in every output format. Exec and interactive sessions each keep their own retention allowance, so CI runs cannot archive interactive conversations. Live and saved receipts include retained terminal failures, and conversation rewinds discard outcomes from removed turns so they cannot be attributed to later requests.
  • Onboarding lists Ollama, LM Studio, and vLLM even before a local runtime is detected, so they can be selected and configured. The L filter is available during onboarding after local-runtime detection.
  • /fork <id> now shows the forked conversation. Before, the screen kept the previous conversation while the model already had the fork's history.
  • With /translate on, each translated thinking block lands in its own cell. Before, two translations finishing out of order could swap them.
  • Pasting text that contains an escape sequence written out, such as print("\x1b[?25l"), keeps it as pasted. Before, part of it was removed from the message box as if it were a stray mouse report.
  • A question that appears while you are typing no longer takes an Enter you pressed for your message as its answer.
  • /new and /clear start without the previous conversation's goal. Before, a paused goal followed you into the new conversation, where /goal resume picked it up again. The old session keeps its saved goal.
  • After /edit, sending the revision with Ctrl+Enter replaces the earlier message as Enter does. Before, it was appended instead, and the next message then undid the wrong exchange.
  • In /resume, pressing d and then scrolling with the mouse before answering y could delete the session you scrolled to instead of the one you chose. The prompt now ignores the mouse, and y deletes only the session d was pressed on.
  • Typing a stop word (stop, wait, pause by default) while a turn is running cancels it at once. Before, Enter queued the word behind the turn it was meant to stop.
  • Runtime API fixes: - POST /v1/threads/{id}/undo accepts {"turn_id": "turn_…"} to remove that user turn and everything after it. A client that edits a message can name it, instead of counting messages back, so a turn another client appends meanwhile can no longer make it edit the wrong message. - Goal events on a thread's event stream now follow the order the goal changed in. A set and a clear racing each other could leave the stream reporting an active goal after it was deleted. - PUT /v1/sessions for a thread with a queued or running turn now answers 409. Before, it waited for that turn to finish while blocking new turns, steering and compaction on every thread. - PATCH /v1/threads/{id} with a new system_prompt now takes effect on the next turn. Before, a thread whose engine was already loaded kept the old prompt. The change is refused while a turn is running. - POST /v1/threads/{id}/retry with a blank prompt now answers 400 without first creating a fork. - Connecting a remote computer stops reading the probe response at 64 KiB instead of buffering all of it first. - The computer event cursor can no longer move past an event that has not been published yet. - POST /v1/stream ends when the turn's own record fails to save, instead of sending keepalives forever.
  • web_search can use DeepSeek's new Search API: set [search] provider = "deepseek" and give it your DeepSeek key through [search] api_key or DEEPSEEK_API_KEY. It returns raw results without a model round trip. DeepSeek bills $0.75 per 1,000 searches from November 1, 2026.
  • In the desktop and web apps, a conversation stays compacted after Codewhale restarts or unloads it. Before, reloading replayed every earlier turn and then added the summary, so the next request carried everything compaction had removed. Each compacting turn now stores the history the model continued from, and forks, /undo and session exports start from it as well.
  • When a provider stream fails before any content and Codewhale quietly resends the request, the tokens the failed attempt reported are now added to the session, goal and sub-agent totals instead of being merged away. The context meter still reflects only the request that succeeded.
  • Esc, or a Runtime interrupt, now stops a tool_call_before hook that is still running: its process tree is killed and reaped, hooks queued behind it are skipped, and the turn stops at once. Before, the turn waited for the hook to finish, and the hook could still change files after the turn was reported as stopped.
  • With a sub-agent open in the main pane, scrolling and redraws reuse its rendered transcript instead of re-rendering every message on every frame, and a finished sub-agent's transcript file is no longer reread from disk every 400 ms.
  • While a slash command is in the composer, the TUI rereads your command folders and config.toml at most once a second instead of on every frame. A command file you add still shows up in completion within about a second.
  • In a session long enough to fold its oldest transcript cells (past 5,000), tool details, expanded tool runs, sub-agent cards and a streaming reply keep pointing at the right rows. Each fold had shifted them one row too far, so the inspector opened the previous cell's details.
  • A sub-agent started with the parent's context that ends without writing anything no longer reports the parent's last message as its own result.
  • When one reply carries several text blocks, as the Responses route sends for separate message items, the conversation now keeps all of them. Before, each new block replaced the previous one in the history sent back to the model, so it forgot what it had just said even though you saw it. Text a provider puts in a block's opening event is also shown now.
  • codewhale serve --insecure and codewhale app-server --insecure-no-auth answer only requests addressed to 127.0.0.1, ::1 or localhost. Without auth, a website could point its own domain at 127.0.0.1 (DNS rebinding) and drive the Runtime API from your browser; such requests now get 421 Misdirected Request. Servers with auth are unchanged.
  • Sandboxed commands can no longer reach Codewhale's Runtime daemon socket. On Linux with bubblewrap, and on macOS with sandbox network access on, a command the agent ran (a test script or a postinstall hook, say) could read the owner receipt and attach to the socket that codewhale serve, the desktop app, the VS Code extension or an ACP session holds. From there it could change the sandbox mode, the approval policy or a provider's base URL in your config, or start an unsandboxed turn. The daemon's default run directories are now on the sandbox's default deny-list, and on macOS no socket under a denied path can be connected to. Turning the default deny-list off (sandbox_read_denylist_defaults = false) also turns this off.
  • codewhale web no longer gives its request proof to whoever holds the session cookie. The cookie is scoped to the host, not the port, so a listener on another 127.0.0.1 port could receive it, and GET / then returned the proof that unlocks the whole Runtime API. The proof now stays in the tab that opened the session, which keeps working across reloads when the browser allows session storage; a new tab opened by typing the address needs a fresh codewhale web.
  • The codewhale web approval card shows the request summary, Codewhale's reason for asking (such as a sandbox escalation) and every argument of the call in full, with the model's own description below, labeled as such. Before, when the model had written anything, the card showed only that text and never the command, so a prompt-injected model could describe a harmful command as a harmless one.
  • /settings choice lists that don't fit, such as Language and Theme, show a scroll rail. Thanks @Lstarsky0 (#7024).
  • During an /mcp search that finds nothing, the status line says "No matches" like the list does, instead of "Nothing on this tab". Thanks @Lstarsky0 (#7023).
  • Read and list cards show a path inside the workspace relative to it ("Reading src/lib.rs") instead of the full absolute path the model sent.
  • /statusline shows its last two items, Workspace and Git branch, without scrolling. The picker had not counted its padding rows. Thanks @Lstarsky0 (#7022).
  • A shell or gate command that the safety check will refuse, such as one spanning several lines, is refused at once instead of first asking you to approve it.
  • Diffs in the TUI number each line only on its own side: a removed line shows its old line number and an added line its new one. Unchanged context lines keep their indentation instead of starting at the left edge.
  • A shell card shows a multiline command one line per row instead of running the lines together.
  • A shell card whose command is waiting on your approval now says "waiting for approval" with a still mark, instead of "running (Ns)" with a spinner. A command queued behind it in the same step says "queued". Elapsed time starts when a command actually begins to run.
  • /color gives a chat's composer box its own color. Bare /color cycles through red, orange, amber, green, cyan, blue, purple and pink; /color <name> picks one and /color off returns to the theme. The color is saved with that session and survives resume; other chats and the theme are untouched. It shows while you are typing, so the focus signal stays.
  • Importing a session container or starting a new chat from the launch screen no longer carries the previous chat's /title onto the new one.
  • Shell cards in the TUI: - A tool card that finished inside a turn that is still running opens its raw detail (tool id, input, output) with Alt-V or a click, instead of a rendered message view. - The work dock no longer shows a ✓ for a background job that was killed or timed out. Killed jobs get a neutral mark; timed-out jobs get the failure mark. - The keybinding docs now say what Alt-V opens with nothing selected, and that clicking a card keeps Alt-V on it while newer cards arrive.
  • The TUI uses less CPU while it waits. With an approval, elevation or question prompt open, or with only background shells still running after a turn, the status spinner and elapsed-time labels refresh once a second instead of five times a second.
  • On Windows, Codewhale processes that start at the same moment no longer lose the built-in plugins. The rename that publishes the built-in plugin snapshot now retries a brief sharing or access refusal, as the other atomic writers already did, instead of starting without built-in plugins.
  • Six fixes from @asto18089, several ported from the Pinvou/CodeWhale fork with @zhuowp: - Claude 5 models and Haiku 5.5 no longer receive temperature/top_p on routes without exact catalog facts (custom or proxy base URLs, dated snapshot ids, Messages-wire gateways), which those models reject with a 400 (#7014). - Kimi keeps a tool whose schema has an empty items: the empty node is dropped, as Moonshot's schema rules allow, instead of excluding the whole tool (#7015). - In a session that already has a stamped compaction checkpoint, a user turn that pastes a legacy summary header stays an ordinary turn: it anchors the round, is kept verbatim and no longer counts as a duplicated summary (#7017). - Turn-complete events carry their own turn_id, submission_id and compaction_id. A send whose route fails to install, and a manual compaction whose route is rejected, now end with a failed terminal event instead of only an error, so waiting hosts no longer hang (#7018). - Anthropic redacted_thinking blocks are captured and replayed byte-exact on native Anthropic routes, so a tool loop after a redacted block no longer fails with the same 400 on every retry. Other hosts withhold the block (#7019). - A named [providers.<name>] table with wire = "responses" or "anthropic" now uses that wire on every turn and across model switches, not only for the first request. The app-server's legacy [providers.custom] table now refuses a non-Chat wire with provider_wire_format_unsupported instead of forwarding a Chat body (#7020; Refs #6997).
  • A background shell job that finishes while the agent is still working now reaches the model before its next step, instead of only when the turn ends. In codewhale exec, which stops at the end of the turn, that output used to be lost. The background notice now says that a job still running when the turn ends is stopped unseen in a headless run, so the model knows to wait explicitly when its answer depends on it. Sub-agents no longer pick up the parent's finished jobs, and the parent no longer consumes a sub-agent's.
  • codewhale review --base <ref> gives the reviewer the base..HEAD commit messages as the author's stated intent, in a field of their own that it checks against the diff and reports on when the two disagree. They are treated as claims, not instructions, and capped at 8,000 characters.
  • codewhale --resume <id> after the TUI was killed mid-turn keeps the interrupted turn. Before, the resume stamped the older saved document as newer than the crash checkpoint, and the checkpoint, the only copy of that turn, was then discarded as stale. --continue was not affected.
  • Three session data-loss paths are closed: - /load of an older exported copy of a session no longer replaces the newer saved conversation with the same id. It refuses and points to /resume. Before, the next autosave deleted every turn made after the export. - A journal archive append that was cut short (disk full, or a kill) is trimmed back to its last complete line before the next append. Before, the next save glued new entries onto the torn line. That made the whole archive unreadable, and the document had already dropped those entries. - Launching with a legacy crash checkpoint keeps it when migrating it to the per-session format fails, instead of deleting it.
  • Sub-agents stay within a turn's tool allow-list. exec --allowed-tools, a Runtime API allowed_tools, and a command's allowed-tools: frontmatter narrowed only the parent. A sub-agent it started got the full tool surface, including bash, write and edit.
  • A workflow plan written with nodes (the declarative shape in docs/WORKFLOW_AUTHORING.md) is now judged for approval from its compiled plan, the same one the run uses. The old reader missed fields nested inside agent and branch nodes. A plan with write children could then start with no approval card, the card could say "Read-only plan", and the receipt recorded the run as approved.
  • The other whole-file writers now refuse to replace an existing file that is unread or stale, as write does: apply_patch with replace, and the write_file and File action=write paths that older prompts still call. A successful patch counts as a read, so patch-then-write still works. fim_edit honors the read deny-list. It also refuses to write when the file changed while its completion was running, which used to overwrite your edit.
  • grep_files (also File search_content) aimed at a single file, rlm open with file_path, and the cache-maximal working set now honor the read deny-list. Each read files such as .env past the check and returned their lines to the model. A deny-listed working-set file is skipped with a note.
  • A tool_call_before hook that answers ask now always shows the approval prompt, as docs/HOOKS.md promises. Before, an earlier "approve for session" or a conversation grant for the same command answered it silently, so a hook could not re-gate a command the person had already approved once.
  • validate_data, review and verify honor the read deny-list, as read does. They read files such as a workspace .env, or in trust mode ~/.aws/credentials, without the check. validate_data's TOML parse error could quote a line of such a file back to the model, and review and verify sent the whole file to the provider.
  • Commands that start outside the shell tool now get the same sandbox as shell commands: - terminal_* PTY sessions used a default sandbox with no credential deny-list, so on macOS they could read ~/.ssh or ~/.aws while bash could not. On Linux they skipped bubblewrap, so workspace-write refused them. They now use the session's shell sandbox, and they refuse to start when commands run in an external sandbox backend. - Runtime API thread jobs (POST /v1/threads/{id}/jobs) started before the thread's first turn ran without bubblewrap and without the deny-list. They now get both, and they are refused when an external sandbox backend is configured, since a job starts a local process. - codewhale run sandbox run ignored prefer_bwrap and the deny-list. When no OS sandbox could enforce the policy, it ran the command unconfined. It now refuses. - On Windows, bash with interactive: true skipped the read-only check that every other command path applies. It is now refused like the others. - A sub-agent's posture line could say the local OS sandbox applied when its shell did not use one. It now reports what that shell actually uses.
  • write refuses to replace an existing file that has not been read in this session, or that changed after it was read. The File edit action already made this check. Before, a whole-file write could overwrite contents the model never saw, or a change you or another agent made after the model's last read. Creating a new file is unchanged, and a file Codewhale wrote itself counts as read. The refusal names the recovery: read the file, then write again.
  • codewhale exec warns again when the sandbox posture asks for confinement but no OS sandbox can enforce it, for example on a Linux host or container where bubblewrap cannot start. With no external sandbox backend configured, which is the default, the check read the absent backend as present, so the warning never printed and commands ran unrestricted with no notice on stderr. Found while proving the #7007 fix end to end in a container.
  • The middle working mode is called Work everywhere in the TUI: the footer chip, the mode name and description, the hotbar action, settings errors, /context and exports, and the matching locale strings, which now use each language pack's existing word for it. The hook contract is unchanged: DEEPSEEK_MODE and DEEPSEEK_PREVIOUS_MODE still report ACT, and saved settings still read and write agent (Refs #6466). The /statusline Mode hint says Work too. Thanks @Lstarsky0 (#7012).
  • The model catalog now carries current models from Anthropic, Google and Meta. Anthropic: claude-opus-5-5, claude-sonnet-5-5, claude-haiku-5-5 and claude-fable-5-1; the Auto router's cheap tier and the Scout companion stay on claude-haiku-4-5. The anthropic default moves to claude-sonnet-5-5, and no default uses claude-sonnet-4-5, which retires on 2026-11-30. OpenAI's GPT-6 family (gpt-6-sol, gpt-6.1-sol, gpt-6-luna and gpt-6-astra) is left out of the direct route because OpenAI does not support normal tool calling for them over Chat Completions. Google: gemini-4-argon and gemini-3.8-flash. Z.ai: GLM-5.3-FlashX is not offered because the Coding Plan endpoint the zai route defaults to does not serve it. Meta: muse-spark-1.3, muse-spark-1.3-contributor and the muse-wonder-1.0 preview join the route, which stays on its previous muse-spark-1.2 default. Several ids are retired. Xiaomi MiMo now defaults to mimo-v2.6-pro, and configs naming mimo-v2.5-pro or mimo-v2.5 send mimo-v2.6-pro and mimo-v2.6-flash, because Xiaomi rejects the old names from 2026-10-21. A [vision_model] that names either old id gets the same mapping. gemini-3.7-flash and gemini-3.5-flash, which Google already serves as gemini-3.8-flash and gemini-3.6-flash, are now selector aliases of those models. qwen3.8-max-preview is gone from the Model Studio rosters. MiniMax M2.7 and M2.5 (including highspeed) leave the fallback picker before MiniMax closes them to new users on 2026-10-19, and keep working for existing configs until they retire on 2026-11-18.
  • Direct DeepSeek routes now send deepseek-flash for deepseek-chat, deepseek-reasoner, the flash, deepseek-v4flash, flash-vision and deepseek-v4flashvisionexp shorthands, and the Auto router's fast tier. codewhale model set and /provider now write deepseek-flash for those shorthands too, matching what model = "flash" and /model flash resolve to. DeepSeek has retired the V4 Flash and V4 Flash vision models. It still accepts deepseek-v4-flash and deepseek-v4-flash-vision-exp, but serves them with V4.1 Flash, bills them at the Flash price, and calls that routing temporary. Turns on either name from 2026-09-10 04:00 UTC are now priced at the Flash rates ($0.003 cache hit, $0.15 cache miss, $0.60 output per million tokens off-peak, doubled at peak) instead of the old V4 Flash rates, which overstated a cache hit by about 2.3 times. The vision name was not priced at all before. Earlier turns keep the rates they were billed at, including turns recorded under a shorthand. On NVIDIA NIM, OpenRouter, Novita, Fireworks, SiliconFlow, SGLang, vLLM, DeepInfra and Together, deepseek-flash selects that host's V4 Flash model, so the flash shorthand keeps working there. On OpenCode Go, deepseek-flash and the flash shorthand select Go's deepseek-v4.1-flash; until this fix, /provider opencode-go flash was rejected as an invalid model.
  • When $SHELL is zsh, the bash tool now runs commands with zsh's NOMATCH and EQUALS options off. Common Bash idioms such as grep --include=*.rs and [ "$a" == "$b" ] now run instead of failing with no matches found or = not found. In 310 local DeepSeek sessions, 334 commands had failed this way, which silently dropped searches the model believed it had run.
  • task_shell_wait is now in the first-turn toolbox. A bash command that moves to the background now tells the model to call it directly. Before, every long build or test cost a tool_search round trip and a tool-catalog re-pin, and models often polled with sleep instead.
  • codewhale exec receipts no longer report an empty final answer when a background shell finished after the model answered. This happened in 52 of 185 DeepSeek exec runs, and a fleet worker then recorded no answer.
  • A reasoning-only response cut off at the output limit is no longer re-sent up to two more times on Responses routes such as deepseek-flash. It now fails with the output-limit message. The engine's own check missed the incomplete: prefix that the Responses parser adds.
  • tool_choice: "none" now reaches the provider on Responses routes and on DeepSeek Chat routes with thinking on. Compaction and final-report requests rely on it; DeepSeek documents it as valid in thinking mode. required and named choices are still not sent while DeepSeek is thinking, because that returns a 400.
  • A DeepSeek Chat response that ends with insufficient_system_resource or aborted is now treated as incomplete, not as a finished answer.
  • On DeepSeek, the Auto-Review guardian now asks for low reasoning effort. It used to leave thinking at DeepSeek's default (high), so the reasoning could use up the guardian's 4,096-token answer budget, report the review as unavailable, and stall auto-approval.
  • Durability and blocking-call fixes from the #6553 and #6555 audits: - On Windows the updater syncs the staged binary, tries an atomic replace first, and reports where the previous binary is if restoring it fails. - Config writes sync the temp file before the rename. - The task store, Fleet run and receipt reads, and session listing now run off the async runtime. - Worktree names that are empty, start with -, or contain .., \ or control characters are refused. git worktree add gets a -- separator before the path. - The boot snapshot prune repairs a HEAD that names a missing commit before pruning, instead of logging "bad object HEAD" (Refs #6978).
  • Typing into a terminal dock that has no sessions no longer shows the "reset or lost" error. Thanks @Lstarsky0 (#7010).
  • The /mcp Extensions panel's detail pane grows to fit its wrapped text, up to a third of the panel, so names, descriptions and details are no longer cut off at 80×24. Thanks @Lstarsky0 (#7011).
  • When a tool_search activation pushes an earlier deferred tool out of the bounded conversation toolbox (8 tools, 16 KiB of schemas), the search result now names it under evicted_tool_references. Before, the tool silently disappeared from the next request, and a model could go on calling it. A tool called in the current or previous turn is never evicted, so the toolbox can briefly hold more than that. Thanks @asto18089 for the cost and correctness analysis (Refs #6969).
  • An ACP client that asks how to turn on Full Access is now told the routes that work: start the server with codewhale --yolo serve --acp, or set yolo = true in config.toml. The hint used to recommend --approval-policy full-access or approval_policy = "full-access" in config.toml. Both are refused when Codewhale starts, because config.toml's approval_policy only accepts on-request, untrusted, never, auto and suggest. Thanks @harryvizcaino-oss for the Paseo report (Refs #6992).
  • On Linux, a credential directory the sandbox hides no longer breaks every sandboxed command when it is reached through a symlink, such as ~/.kube linked into a synced dotfiles folder or a ~/.config that links elsewhere. Each command used to abort before running with a bubblewrap mount error ("Can't mount on symlink destination"), because the mask was placed on the link. The mask now goes on the directory the link resolves to, so the credentials stay hidden through the link. Thanks @rafacouto for the report and the standalone bubblewrap reproduction (Refs #7007).
  • /help keeps its head-noun shortening to English. In German and Indonesian it had kept the first and last words of a long description, which can say something else (Periksa penyedia aktif instead of Periksa saldo akun). Other languages now shorten to whole words from the start. Thanks @Lstarsky0 (#6995).
  • /theme right-aligns its row numbers, so names, swatches and taglines in rows 10 and later line up with rows 1–9. Thanks @Lstarsky0 (#6998).
  • GET /v1/settings/schema accepts ?locale=<tag> and resolves row labels, descriptions and option labels in that locale, with the configured locale as the default. The desktop sends the interface language it shows, so a desktop opened from the Finder or the Dock on a Chinese system, which has no LANG, no longer lists its Settings rows in English under Chinese headings.
  • codewhale --continue reopens a session whose terminal was closed or killed mid-turn. It used to print "Recovered interrupted session" and then exit with "session … is open in an interactive Codewhale session": the recovery had registered the session as this process's own live session, and the resume step that follows refused it. Recovery now holds the session's lease only while it promotes the checkpoint, as --resume <id> does.
  • Queued messages restored from an earlier launch or another session are no longer sent automatically. They wait in the queue until /queue send <n> sends one or /queue clear discards them. The restore notice says so and is now also written to the transcript, because the "Resumed session" status used to hide it. Messages queued in the current session still send in order after each turn, ahead of the held ones. Before, restored messages went out one by one after your next message. On a machine where the queue file could not be cleared, that re-sent the same old messages at every launch (#6978). Editing a held message with ↑ and cancelling the edit puts it back as an ordinary queued message. A failed queue write is logged with the OS error and session id. Thanks @SergiuSSoluS for reporting the re-delivered turns (#6978).
  • A long session whose history holds more images than its model accepts in one request no longer becomes permanently unsendable. When a provider refuses the number of images (for example vLLM's "At most 3 image(s) may be provided in one prompt", "too many images" or "maximum number of images"), Codewhale learns that limit for the provider and model (the number the provider states, otherwise half the images sent) and resends with only the newest images attached. Each older image is replaced by a fixed note telling the model it remains in the session and not to guess what it showed; a tool image's note says to take a fresh observation, such as a new screenshot, rather than repeat the action. Each resend carries strictly fewer images, there are at most three per turn and never an unchanged one; after that the turn ends with an image_count_exceeded error and the next message uses the learned limit. A stated limit of 0 sends images as text, as for a model without image input. Before, a count rejection either ended every later turn the same way or was misread as "no image input" and stripped every image. The window moves in steps of a quarter of the limit, so the cached history prefix changes only once every few new images. Each change is recorded as a request_image_window event (runtime threads store it as a status item with that code, exec --output-format stream-json prints it and the TUI shows it), and /preview-request and the compaction summary request apply the same window. A summary request refused for its image count teaches the limit too, and the context recovery that sent it retries under that limit. A sub-agent no longer retries a count rejection as a transient failure. Known limits: nothing changes until a provider has refused once, and no documented per-model limits are applied; the learned limit is kept in memory per engine and per sub-agent, so a restart learns it again with one refused request; the oldest images go first, user attachments included; a refusal that arrives mid-stream ends that request and only the next send uses the limit; a gateway that reports the refusal as a 5xx is retried unchanged by the transport first; a request-body size (HTTP 413) refusal on an ordinary turn still has no recovery; and the context budget estimate still counts every stored image, including those the window sends as notes, so a small context window can still trip context recovery.
  • Switching provider is now refused while a turn is running, as model, thinking and permission changes already were. The refusal covers /provider <id>, the provider picker, a custom provider, setup and login flows, and adopting a local Ollama. The status line reads "Provider is locked while a turn is running — press Esc to interrupt first". Before, a mid-turn /provider <id> replaced the engine under the running turn (Refs #2982).
  • /init now asks the model to write AGENTS.md in the interface language (for example Simplified Chinese when the TUI runs in zh-Hans), headings included, keeping commands, file paths and code identifiers as they are. Before, the prompt always said "Write in English". The non-interactive codewhale init template is unchanged and still English (#6964). Thanks @Asteria1028.
  • A shell command, shell input or verifier that contains an invisible or bidirectional Unicode character is now refused before any approval card or reviewer call in Ask, Auto-Review and Never. This covers zero-width spaces and joiners, bidi marks, overrides, embeddings and isolates such as U+202E, tag characters, stray variation selectors and terminal control characters; ASCII control keys sent as input to a running program, such as Ctrl-C or an arrow key, stay allowed. The refusal names the code point and its position, because the approval card and other clients cannot show the character: the terminal drops it and other renderers may reorder the line around it. To use the character on purpose, resend the command with it written as a shell escape, for example $(printf '\342\200\256'). Emoji sequences, keycaps, subdivision flags and one variation selector after CJK or emoji text are unaffected; a joiner or mark inside Persian, Arabic-script, Indic or Hebrew words is refused too. The executed command is never rewritten, and Full Access is unchanged.
  • A curl or wget whose request body uploads a credential is now held by the built-in safety gate. This covers -d/--data*/--json/-F/ --url-query/-T/--upload-file/-H @file/--post-file/--post-data (and wget's abbreviations of them) carrying .env, ~/.ssh/id_* (public .pub keys excepted, judged per comma or brace alternative), ~/.aws/credentials, .netrc, a key file, a secret-named variable such as $GITHUB_TOKEN or $OPENAI_API_KEY, or stdin fed from one of those, from env/printenv, or from echo/printf/<<< of a secret-named variable. A shell command, shell input or verifier over 64 KiB or 4,096 words whose text contains curl or wget anywhere, or one nested too deeply to read, is held the same way under its ordinary heading, with a reason saying it was too large or too deeply nested to check. Ask shows a card headed "Upload credentials (…) with …" that a session grant or saved allow rule cannot answer; Auto-Review and Never deny the call. Runtime clients receive the same heading as the approval summary. A literal request header (-H "Authorization: Bearer $TOKEN") is not affected, and other upload tools (scp, rsync, nc, httpie, aws s3 cp), secrets inside an ordinary file, here-documents, $(printenv NAME) inside a value and a credential name split across a brace or quotes (.net{rc,}, .n""etrc) are not detected. Full Access is unchanged.
  • Switching provider, model route, profile or workspace, or changing plugins, while a /compact is running or queued no longer leaves the session stuck. The pass on the replaced engine is stopped and the transcript says "Making room stopped; the conversation was not changed". Before, /new, /new --force and /resume were refused with "context compaction is running" or "a manual compaction is queued", and /compact answered "Already making room.", until Codewhale was restarted. A /compact still waiting for a free engine slot is carried to the new engine as before. A context purge caught by a switch cannot be stopped: the replaced engine may still finish and bill its request, and the transcript now says "Session cleanup was abandoned with the replaced engine; the conversation was not changed" instead of blocking /new with "session cleanup is running". A turn still running when the engine is replaced is not covered and can keep /new refused. Thanks @luestr for reporting the refusal in #6981; this is one way to reach it, and the report stays open until the blocker that 0.10.2 names confirms its cause (Refs #6981).
  • DeepSeek on the Responses route (the deepseek-flash default) no longer fails with 400 reasoning_text must be passed back when a session replays a tool call that has no stored DeepSeek reasoning: a turn that was interrupted, ran with thinking off, came from another provider, or where the model wrote text before its tool calls without visible reasoning. Codewhale now sends each assistant turn's reasoning first, ahead of its text and tool calls, using the same (reasoning omitted) placeholder the Chat route already uses when there is none. Live probes on 2026-10-19 returned 400 for text → reasoning → tool call and for no reasoning, and 200 for reasoning → text → tool call. The same multi-step task that failed in 2 of 4 runs on the first 0.10.2 candidate passed 6 of 6 with the fix. On Chat, DeepSeek enforces this only for tool-call turns, which were already covered.
  • At reasoning effort max, the first-party DeepSeek route now asks for up to 131,072 output tokens, DeepSeek's documented default at that effort, instead of 65,536. Every other provider and effort keeps 65,536, and explicit overrides and route limits still apply.
  • codewhale exec --output-format stream-json adds the provider's finish_reason to each turn_usage record, so a tool-call stop can be told apart from an output-limit stop or a provider abort. The field is omitted when the provider reports none.
  • The /statusline picker's item hints are localized in all 15 UI languages instead of always showing English.
  • A custom OpenAI-compatible relay's model list is now discovered. Four separate defects kept it out of /model: a roster answering both data and models was rejected as a duplicate field; only the active route was probed; /v1/models was authenticated with x-api-key whenever the route declared wire = "anthropic", which a relay that rejects that header answered with 401 missing_api_key; and the picker's default view then hid the relay's own rows. The startup probe now covers every configured relay, a built-in provider name pointed at a private endpoint ([providers.openai] against a relay) counts as a relay, and the provider panel no longer reports its catalog missing while listing it. Thanks @SparkofSpike (#7013).
  • The footer preview in /settings now uses the footer's own words and colours, in the UI language: Startup mode Work previews ● ask work and Plan previews ● read only plan, as the footer under the composer shows them. Thanks @Lstarsky0 (#6993, Refs #6466).
  • /resume, /load, and a provider, profile or plugin change keep configured stdio MCP servers running, as /new already did: the replacement engine adopts each live process when its workspace, MCP backend and server config are unchanged. A workspace switch still restarts every server, and servers added at runtime still close.
  • Provider lists no longer show two "MiniMax" rows or four "Alibaba Cloud Model Studio" rows. The variant endpoints are labelled "MiniMax (Anthropic API)", "Alibaba Cloud Model Studio (Token Plan, Anthropic API)", "Alibaba Cloud Model Studio (Coding Plan)" and "Alibaba Cloud Model Studio (Coding Plan, Anthropic API)"; the default MiniMax and Model Studio rows keep their names.
  • Compaction no longer fails with "Chat API response missing choices" on gateways that wrap a non-streaming Chat Completions response as {"data": {"choices": ...}, "success": true}, such as Sub2API in front of Cline. A response with top-level choices parses as before, and an envelope without success: true still fails. Thanks @luestr for the response headers and sanitized body in #6981; the /new refusal reported there is not changed by this fix.
  • Experimental extension host: a plugin can no longer provide the core subagents service. Its activation fails with "extension may not provide core service subagents", as it already did for agents, approval and the other core names. Codewhale's own sub-agents and the tools they can use are unchanged.
  • OpenHarmony builds on Windows select Ninja, with an SDK-bundled fallback and a clear error when it is unavailable. The CLI keeps its download and Work context integrity checks available on OHOS by sharing an ungated SHA-256 helper (thanks @shenjackyuanjie, #6989; reported in #6988).
  • Windows mouse-wheel scrolling is restored after returning from the external editor. The handoff now releases both Windows console mouse capture and terminal mouse modes. Thanks @SparkofSpike for distinguishing terminal scrollback from transcript scrolling in #6652; the separate hours-long scrolling slowdown still needs reproduction.
  • Shell classification accepts PowerShell’s call operator, quoted ampersands and combined output redirection without losing destructive commands in nested shell payloads or after command separators. Thanks @SparkofSpike for the diagnosis and fix in #6929, and @jayanthvee for the detailed Windows report in #6963.
  • Windows commands that cannot be classified use the normal approval path with a direct explanation. Ask can request approval and Auto-Review can consult its reviewer; an unclassified command is no longer reported as an npm-launcher kill. Actual unbounded node.exe image kills keep their hold in reviewing modes; Full Access continues to bypass that floor. Thanks @jayanthvee for separating these cases in #6963.
  • Pasting while a modal is open no longer changes a history-search query hidden underneath it. Existing modal key ownership and hidden-caret guards remain in place. Windows Terminal IME preedit is still controlled by the terminal; native IME retesting remains open (#2323).
  • codewhale model list, model resolve, the model picker, sub-agent model validation and Runtime facts read endpoint-scoped catalog facts. model set saves the exact route selection, and app/models projects the captured Runtime's catalog. Compatibility aliases, advisory route checks, the agent ModelInfo capability flags and HTTP app-server route admission still read the bundled curated overlay; admission uses it only to reject a model the catalogue knows for a *different* provider. model resolve now prints limit_overrides whenever the resolver applied a sourced override, so a context or output limit names its origin instead of looking catalog-native. Cost estimates preserve complete price tiers, calculate exact decimal amounts per request, and freeze rates at dispatch. Missing rates or required usage breakdowns stay unpriced; public prices do not establish account access. A model priced only by a live models.dev refresh gets a cost estimate at the same confidence as bundled models.dev prices instead of showing as unpriced. The offline seed records its source snapshot and keeps absent default wire IDs as dated compatibility fallbacks. Refs #6396.
  • Desktop and HTTP app-server turns feed an existing shared pet companion when its followed session has no live producer. Automatic selection is checked atomically by the owner; a live TUI keeps its source. The Runtime producer forwards activity metadata only and releases its connection after a 12-second completion tail. Refs #6155, #6139.
  • bash accepts an optional description, shown on its card. It never changes execution, approval matching or Auto-Review input.
  • A first launch with no key or route now opens the composer. Codewhale asks for a provider when you send your first message, keeps the message in the box, and offers a local model only when a local Ollama server answers. The provider list now shows what you type to filter it during first-run setup.
  • Removed the own-sandbox cloud dispatch (--own-sandbox, /dispatch, agent runtime:"cloud", the cloud-agent alias, and the --confirm, --remote, --branch, --cwd, --status and --list options). codewhale dispatch "<task>" now runs only through the signed-in account, with its quote and EU-compute consent. Cloud computers and accounts are paused for new users, so codewhale dispatch is not available to them.
  • codewhale dispatch uses the account's neutral wording for cloud errors, runs for the quoted seconds unless --seconds is given, and asks for consent only when both stdin and stdout are terminals. It refuses a message that was not read as new Work, and prints the Message ID.
  • MCP servers now connect when a session starts, including servers from enabled plugins; set lazy = true on a server you configure to connect it on demand instead. Finishing an OAuth login reconnects just that server, and /mcp reload redials every server that is not lazy and reports how many are not connected out of the configured total.
  • The MCP status no longer stays at "connecting" after the servers have finished. The final status was lost when it arrived while a reply was running, when the interface was busy, or when the last server was removed; the newest status is now kept until the interface can show it. Refs #7035.
  • /new keeps configured stdio MCP servers running: the next conversation adopts each live process when its workspace, MCP backend and server config are unchanged, and dials only what is missing. HTTP/SSE servers reconnect so they pick up current credentials and network policy; servers added at runtime and plugin-contributed servers are closed with the conversation. A workspace switch still restarts every server, and the MCP panel and /mcp now show the new engine's status instead of staying stale.
  • The mobile page retires an approval card's Allow and Deny buttons when that approval is decided from another client, cancelled or timed out, and shows which happened.
  • Settings name compaction "Compact at" with a plain-language hint, explain Input history as the number of sent messages kept for recall, and label the Anthropic-compatible DeepSeek endpoint "DeepSeek (Anthropic API)".
  • Running shell commands open an inspector with their output and status. It follows new output until you scroll back, and drops Stop once the command ends. Alt+V opens the card you clicked, even after newer cards arrive or a tool run collapses around it. /jobs wait and /jobs poll open the same inspector instead of freezing the screen for up to 5 s, a shell row in the work dock opens it too, and a task row opens /task show instead of failing with "Job … not found" (#6931).
  • In /setup, u and d act only on the working-agreement step. Pressed on another step they no longer close the wizard and switch your agreement off.
  • /setup no longer says "You're ready." when no model is connected; its last step asks for a provider and lists the P and C keys it accepts. A rejected API key's reason stays visible at narrow widths.
  • First run with a local Ollama model continues to the trust question and the ready screen instead of ending onboarding, and the next launch no longer starts onboarding again.
  • A turn that ended in failure reads as an error, live and after resume. Retry notices stay in the transcript instead of flashing a red error that hid the recovery.
  • File edits show as patches with their change summary once. Tool status words read done, failed and loaded, not run everywhere, and a tool that only loaded no longer gets a done check.
  • Delegated agents' cards name the tool they are running instead of "Core tool <call id>".
  • Markdown: a line like #6235 fixed it is no longer a heading, headings render inline code and emphasis, and tables draw one rule under the header instead of one between every row.
  • The approval card shows its field labels and description in your language in every locale, not only Simplified Chinese.
  • /mode work says "Switched to Work mode.", and /zidong says it switched to Full Access. /overview and /setup call the mode Work.
  • The language screen points to /config locale <tag> --save, the Korean Never chip says it allows nothing, and the elevation dialog's Abort says it skips only that tool call.
  • Less work on the UI thread and less memory per turn: - the context meter keeps its estimates for unchanged history; - tool calls share the turn's history instead of copying it; - compaction checks pressure with one pass; - write_atomic sweeps a directory for stale temps at most hourly; - the pet costs nothing while hidden; - GET /v1/usage reads the turn store once, not once per thread; - each save's session cleanup no longer reads every session's cost ledger; - sub-agent checkpoints copy only the tail they keep; - the underwater theme paints its background once per frame.
  • /resume, /load and other session changes that cannot run yet now list what is still busy and how to stop it. Thanks @SparkofSpike (#6948).
  • Sessions that ended without a clean exit show interrupted with their age in the session list.
  • codewhale logout also deletes a stored legacy sandbox token.
  • codewhale lane list prints an empty list instead of failing when no lane has been started, codewhale completion no longer errors when its output pipe closes early, and session-diagnostics, receipts and features help and errors say what to pass and where to find saved sessions.
  • A missing --config file, a missing -C workspace directory and an unknown --profile now fail at startup with a clear message.
  • codewhale web works when $HOME sits under a root-owned symlink.
  • Typing /exi and pressing Enter now completes the command instead of running a different destructive command (/exit, /clear, /new, /logout, /restore).
  • The Shift+Tab permission hint stays in the footer while in Auto-Review and Full Access.
  • An idle pet view no longer builds animation frames while nobody is looking at it (#6728).
  • On the pet main view, Ctrl+] cycles the pet's views: the companion whale, a crisp local cove whale without the fog, braille, pixels (kitty graphics), particles, whale-girl and installed avatar packs. Terminals with the kitty keyboard protocol can also send Ctrl+Tab and Ctrl+Shift+Tab to move forward or back; Terminal.app uses those to switch terminal tabs, so use Ctrl+] there. The footer names the view, and clicking it cycles. A view that cannot draw shows its fallback and says what it needs, for example pixels needs kitty graphics · showing particles. /pet avatar <key> jumps to a view, and the /pet usage lists every view, style and language.
  • F6, F8 and F9 work on the pet main view, not only in the F5 inspector. Every F-key hint on macOS, including the help overlay, reads fn+F5, fn+F8 and so on, including in ASCII-safe mode. /pet on, F8 and F9 restart a companion view that stopped, so "/pet on retries" is true. A failed launch shows its own reason, a successful one says habitat open, and pressing F8 several times while the companion starts opens one tab. F8 and F9 also restart a stopped companion from the inspector.
  • The live dot whale stays dense in large panes, the whale-girl sprite scales by whole pixels, and avatars, the particle grid and the pixel view no longer show the whale through them. Avatars follow your theme and CODEWHALE_ASCII_SAFE, the pixel view's image is a whole fraction of the terminal's pixel size, and the pet's view worker sleeps until its next deadline instead of waking every 2 ms.
  • The terminal dot whale respects studio brightness and sleep dimming. Normal companion startup no longer shows a missing-service notice, avatar atlas notices match the current frame, and pet fallback descriptions are translated.
  • README: codewhale exec --auto is shown for headless runs that edit files or run commands.
  • bash now moves a foreground command to the background after 30 s and reports the elapsed time and how long ago it last printed output. task_shell_start is removed.
  • Every change of effective permission now writes a Permissions changed to … line in the transcript, and runtime threads record it as a status item and a thread.permissions_changed event.
  • The bundled first-party catalog pins marketplace revision 2e3a6fba453c9b34d5b1444ab5bd6edc7b119189 with 19 catalog entries, including the bundled Skills pack. Installed bundles carry the reviewed Computer Use and bridge fixes and the MIT license.
  • codewhale app-server no longer serves GET /jobs, which was always empty; background jobs are GET /v1/jobs on the Runtime API (#6513).
  • codewhale app-server started inside a project no longer writes .deepseek/events.jsonl there; with no configured path the hook log sits beside the state database in the Codewhale home. Thanks @Lstarsky0 (#6921, Refs #6513).
  • Streaming requests honor the configured retry count even when provider backoff or Retry-After exceeds the response-header timeout. Chat, Responses and Anthropic apply that timeout to each physical request; waiting between attempts does not consume it. HTTP/1.1 responses receive the same error classification and retry handling. Explicit weekly, five-hour and plan-reset usage exhaustion stops as a quota error, while temporary request-rate limits remain retryable. Closing retry receipts label each per-kind counter so it does not imply which failure ended the turn. Failed Chat opens retain the provider's reasoning_content diagnostic. Ambiguous transport failures can still replay a request the provider accepted and incur a second completion charge; protocol fallback remains limited to one HTTP/1.1 attempt per transport open. Refs #7045. Thanks @7jrxt42BxFZo4iAnN4CX.
  • Body text on a screen that paints its own background now uses the theme's primary text colour, and on a terminal that does not report a background colour it uses the terminal's own foreground instead of an assumed ivory tone. The System and Blue Stage themes showed ivory text on a light terminal because Codewhale could not measure the ground it was drawing on; modals, the nested underwater surfaces, fleet setup, the automations view, the live transcript and the worktree manager now carry body ink explicitly. A theme that never sets an ink colour for one of its own surfaces can still be hard to read. Refs #7043. Thanks @Statter.
  • A saved session that cannot be resumed because the provider it recorded is gone now says how to keep its history: the refusal names codewhale sessions export <session id> with that session's real id. The hint now appears at three resume sites - the TUI resume, the executor resume and the Runtime API - instead of only one. A Runtime resume refused because the persisted provider route needs an exact custom provider is now reported as a bad request rather than an internal error. Other persist refusals keep their current status; codewhale resume and fork on the mount path still refuse without the hint. Refs #6996. Thanks @luestr.
  • A read-only role whose shell command is refused now reads that the run has no network, that a read-only command reaches the network only in Full Access with an allowing session sandbox, a [network] policy that does not deny by default and a network grant, and that it should use a web tool or report the source unreachable. That replaces a child reporting "bash denied for non-admitted programs". The same hint covers a command that starts with cd ... && and the contract bash path as well as the legacy one. A network attempt made from Python or gh still gets no hint. A read-only child's own briefing states up front that its shell has no network and that web is its only route to a page, so it reports a source it could not fetch with the error it saw instead of blaming a blocked program. Refs #7040.
  • A codewhale resume or codewhale fork that is refused no longer leaves a half-bound session behind that blocks the next attempt. A saved session whose beginning changed after an earlier resume, through a compaction checkpoint, contract pruning or a restored sub-agent handoff, now resumes instead of failing with "saved holder checkpoint differs from the saved history" or "saved holder has a successor outside the selected document". Refs #6954. Thanks @7jrxt42BxFZo4iAnN4CX.
  • On Windows, Python run through the shell tool no longer garbles Chinese and other non-ASCII output. Windows shells were meant to start with PYTHONIOENCODING=utf-8, but adding hook variables replaced the whole environment and dropped that default on every run, so piped Python output used the system code page while Codewhale read UTF-8. The default now survives. A shell_env hook can still set its own value (on Windows, variable names match regardless of case), and the default replaces a different PYTHONIOENCODING inherited from your environment. Refs #4202. Thanks @zhuowp (#7041).

Added29

  • Herdr pane integration reports Codewhale's idle, working and blocked state, releases the pane on quit, and supplies the current session's resume command to Herdr 0.9.2 or newer. Thanks Dhruv Singal (@dsingal0) (#7064).
  • The desktop app can connect an OrcaRouter account without a terminal. The Runtime API's POST /v1/providers/orcarouter/connect returns OrcaRouter's consent link, waits for the browser to come back and saves the key the same way codewhale auth orcarouter does; GET and DELETE /v1/providers/orcarouter/connect/{attemptId} report and cancel the attempt, and GET /v1/providers marks the route with browserConnect.
  • codewhale review, the review agent tool and /review now share one reviewer. It can read the repository with read-only tools (read, list, grep, file search and git status/diff/log/show/blame) when the checkout is clean and, for a pull request, HEAD is the PR head; otherwise it reviews the diff alone and says so. Findings use one severity scale, blocker, concern and nit; the old error/warning/info words map onto it. Review effort follows the change's risk: sensitive paths (auth, billing, migrations, secrets, sandbox, schema and similar) or large changes get more steps and tool calls, small low-risk changes get one pass over the diff.
  • Every review body now ends with a severity tally as one HTML comment, <!-- codewhale-review: {"blocker":0,"concern":0,"nit":0,"introduced":0,"preexisting":0} -->, so a repository can gate a merge on "no blockers" without scraping prose or granting Codewhale checks: write. Findings also say whether the line they point at was introduced by this change or was already there, decided from the diff rather than from the model's own label. codewhale review, codewhale review --pr --post and the extension-host path write the same body. --money-cap-usd, with --input-usd-per-mtok and --output-usd-per-mtok, stops a review at a spending cap; without both prices the receipt says the cap could not be applied. A review that stops early names the limit and says that files it did not reach were not reviewed. Each finding says whether it was reproduced, traced or only suspected; suspected ones move to a short "worth a human look" list, and on high-risk changes a second pass tries to refute each finding and can only remove findings, never add them. A defect in code the change did not add is labelled pre-existing, kept out of inline comments and listed separately, and on its own does not raise the merge risk. The summary lists what the reviewer checked and found sound under "Checked, nothing wrong".
  • Runtime API: GET /v1/workspace/status reports workspace_trusted, and POST /v1/workspace/trust with {"trusted": true|false} records the server workspace's project trust in the same record /trust on|off --save writes. It takes no path and needs write authority; watch tokens can read but not write. The answer is the decision read back, with the config_path that holds it. Revoking trust does not remove AGENTS.md or project rules, project hooks still need their own approval, and project MCP servers change only after the engine restarts. Thanks @gaord (#6959).
  • Runtime API: when capabilities.account_model_owner is true, a turn can name the signed-in account in account_model_owner, with provider codewhale and an exact provider/model route. That turn runs only on that account's credential, never a local key, an environment variable or another provider, and is refused if the account's model access is missing, expired or revoked. The Chat relay takes the same field as accountModelOwner.
  • The model can hand a goal back at a milestone: update_goal with status: "yield" ends the turn with the goal still unfinished, and your next message resumes it. A goal the model reported blocked, or one you paused, still needs /goal resume. Thanks @SparkofSpike (#6930).
  • Bundled Computer Use can re-read only what changed in an app (get_app_state with since) and run up to eight steps in one run_actions batch. Each step can target a unique element found just before it runs, and the batch receipt says which steps completed and whether input was sent, so a failed batch is not replayed. On Linux, keys and pointer events go only to the window that will receive them, and are refused when that window cannot be determined (including under Wayland) or while a menu is open. Linux also gains AT-SPI focus, value reading and text selection, app-window capture, ffmpeg screen recording, kill_app and list_sessions. Computer Use remains a preview.
  • Standard Compute is available as a bundled compatible provider, with the standardcompute router default and authenticated model discovery. Its billing basis remains Unknown (#6985).
  • Sub-agents retain permitted code-mode tool composition. Nested calls keep the child's approvals, write scope, tool timeout and work deadline; approval waits do not consume that tool timeout. Refused nested calls still do not count toward Fleet's denial-loop guard. Refs #6841.
  • /connect [<provider>] signs in to a model provider that a plugin adds, inside the TUI, and /disconnect <provider> removes that sign-in. /login and /logout are for your Codewhale account only.
  • codewhale install <source> installs a plugin from the terminal through the same installer as /plugin install, without starting a model or needing model credentials. Both accept git:github.com/<owner>/<repo>[@<ref>] and npm:<package>@<exact version> as well as a local folder, GitHub archive or tarball URL. The plugin stays disabled and untrusted until you review and enable it; no Git hooks, npm lifecycle scripts or dependency installs run. Experimental. Thanks @LIghtJUNction (#6950).
  • codewhale auth claude and /auth claude add Claude subscription sign-in to the existing Anthropic route, with protected owned credentials, refresh before requests, a provider-picker choice and local sign-out. API-key billing remains an explicit separate choice. This is experimental: live subscription grant and inference acceptance have not been qualified (#6932).
  • /pet on makes the animated GPUI whale the main terminal view, with the existing message box, queued messages and permission controls always available. F5 or /pet inspect opens streamed replies, errors and the current session's agents; Escape returns to the same pet view and draft. /pet off restores the ordinary shell. Whether /pet on is active is remembered across launches, and the inspector can copy the last finished reply with c or its footer action. Motion preferences and unknown usage stay truthful (#6920, #6907), using the shared codewhale-ratatui components (#23, #25).
  • The pet view uses the latest Ratatui particle-whale renderer. Choose a smooth aurora or pixel whale with /pet style smooth|pixel, and choose English, Simplified Chinese, Traditional Chinese or Japanese activity words with /pet language auto|en|zh-Hans|zh-Hant|ja. Language follows the interface by default; a fixed choice lets you learn another language beside the normal status text. The 980 drones form the same full phrases as the interface, including 读取, 搜索 and 调用工具, then return to the whale. The appearance studio saves the same choices. Reduced motion uses a stable pose, and the reply inspector keeps priority on small terminals.
  • A Terminal work dock (/workbar terminal) shows the model’s live PTY sessions in the current workspace, with ANSI-styled output, session selection, resize and direct keyboard input. Ctrl+N starts a separate shell; Alt+Down and Alt+Up switch sessions, and Esc returns input to the composer. Input remains bound to the selected shell’s identity across resets. Available on macOS and Linux; Windows names its current PTY limitation. The view shows a bounded output tail rather than emulating full-screen terminal programs (Refs #6912).
  • When a Plan turn finishes with an answer, the TUI asks "How do you want to continue?". Work (Ask) and Work (Auto-Review) switch to Work with that permission and send the plan as the next message (a plan written only as prose adds one pending To-do); Keep planning, or Esc, stays in Plan and sends nothing; typed feedback is sent as the next message in Plan. The question appears only when the composer is empty, no message is queued, no other view is open and no agent is focused. If the chosen permission cannot be applied (for example it is locked by config), the session stays in Plan and the reason is shown (#6902).
  • /undo force undoes a request whose end was never recorded, including edits made to its files since it started. Any other /undo option is reported as unknown and nothing runs.
  • /diff opens the changed lines in a pager titled "Changes since session start", rendered like an edit in the transcript, under the file list and stat it already printed. Patch text is cut at 256 KiB and left out past 200,000 changed lines; the message then says "The diff is too long to show in full. The file list above is complete."
  • The model can stop a background shell command it owns: task_shell_wait takes cancel=true. That call needs approval, its card reads "Stop a running shell command", and it is refused when sent together with gate. The notices for a command moved to the background now name cancel=true.
  • Each turn tells the model which configured MCP servers it may load, so a question can reach a server you never named. The note lists enabled, allowed server names only (at most 24), asks the model to tool_search a name before searching files or saying no tool exists, and is recorded again only when the list changes or a compaction dropped it. No server is started and no schema is loaded until the model searches.
  • codewhale mcp --help lists the mcp subcommands with their descriptions and shows Usage: codewhale mcp [OPTIONS] <COMMAND>.
  • A file-edit approval card in a folder with no Git repository says "No Git repository here, so edits ask first." on its question row. It appears only for write_file, edit_file and apply_patch in the posture where the same edit runs without a card inside a repository.
  • Clients that start codewhale serve can declare a telemetry surface with CODEWHALE_TELEMETRY_SURFACE, including vscode-extension. This changes the session label while preserving collection settings and opt-outs (#6916).
  • codewhale account computers files saves a Computer's workspace file (up to 16 MiB) to account storage, lists its versions, and restores (up to 4 MiB) or downloads one. Restoring over an existing file needs its current --expected-revision; a download verifies size and SHA-256 and never overwrites a local file. codewhale account computers delete now asks for --discard-files. This is experimental.
  • Runtime API: GET /v1/goals lists goal records across threads, newest update first, with status and cursor paging. Goals whose thread no longer exists are left out, and a cursor issued under a different status is 400.
  • Runtime API: GET /v1/approvals rows add a redacted target (a URL's host or a workspace path) and a one-line summary, plus standing_rule (allow or deny) when a remembered rule or grant answered instead of a person. A shell command keeps only its program name and plain arguments. Rows recorded earlier omit these fields.
  • Runtime API: automations carry a revision. PATCH, run, pause and resume accept expected_revision and answer 409 revision_conflict on a mismatch. Create and those four accept an Idempotency-Key; a retry replays the first success instead of creating or running twice. DELETE honors neither. Clients check capabilities.automation_mutation_preconditions.
  • The first start after an update says what changed, once: the version you moved to, how many features, fixes and other changes its notes list, and a link to that version's release notes on codewhale.net, in the UI language. The TUI shows it on the startup card, so the recent-sessions card no longer disappears on the first launch after an update; it moves into the transcript when the card leaves. Report and setup commands such as codewhale doctor print it to stderr in a terminal. exec, JSON output and non-terminal runs never show it, a fresh install or a downgrade shows nothing, and [update] show_whats_new = false turns it off. codewhale.net has a page for every version at /en/changelog/<version> and /zh/changelog/<version> with all of its entries.

Changed23

  • transcript_spacing has two settings, compact and spacious, and spacious is the new default. comfortable drew the same conversation as compact everywhere except between activity rows, so the settings list offered a choice that did nothing. spacious leaves two blank rows between activity rows and three between turns. A saved comfortable (or default, normal) now reads as spacious; set compact to keep the denser layout.
  • The OrcaRouter consent link that codewhale auth orcarouter and /auth orcarouter open now carries Codewhale's public ref identifier.
  • The OrcaRouter sign-in origin can no longer be moved to another HTTPS address. ORCA_AUTH_BASE_URL and ORCAROUTER_AUTH_BASE_URL accept only a plain-HTTP loopback address, for local test fixtures, and ORCA_BASE_URL now moves only the inference origin.
  • codewhale account agents work-quote and work-launch quote and start Work on your computer balance as well as the trial. --seconds picks whole seconds within the served offer; without it work-launch uses the default its quote showed instead of a fixed 300 seconds, so a balance-funded launch can no longer disagree with its quote. --recovery-from <workspace id> recovers a failed workspace on a fresh computer under the same Work ID. codewhale account agents work accepts --context-file (UTF-8, at most 64,000 UTF-16 units) and up to ten --file FILE_ID@VERSION saved files, so Work needs no repository. account computers create --computer-trial replaces --boat-trial, which still works. Experimental, and available only to existing accounts while new accounts are paused.
  • Goal mode has no step limit when [goal].max_steps is omitted or 0. Positive values still limit the goal, with values above 100000 clamped to 100000 (#6512).
  • MCP and provider browser sign-in allow 15 minutes for the callback instead of five (#6865).
  • /undo takes back your last request in one step, in every access mode: every file the request changed, plus the request and its reply. It no longer asks for /trust on. Its report names the request and lists each file as restored, brought back or removed, then says whether the request and its reply were removed from the conversation. It changes nothing if one of those files was edited after the request, and names the file. For a request whose end was never recorded it changes nothing and points to /undo force. /undo no longer steps back one tool call at a time; /restore still reaches those points. When only the conversation is rolled back, the message adds "No file changes to undo." or says that workspace files were not reverted.
  • /restore without trust mode or Full Access now says that it rolls every file in the folder back to the chosen point, including later edits, that nothing was changed, and that /undo takes back only your last request.
  • /diff compares the workspace with this session's first restore point, so it works in a folder that is not a git repository and includes files created since. Before the session has a restore point it shows the workspace repository's uncommitted changes. With neither, it says "Nothing to compare yet: this session has not saved a restore point here, and this folder is not a git repository." instead of "No changes since session start".
  • /trust on and /trust off leave a line in the transcript saying what changed; with --save the line also says what was saved for the folder.
  • After Esc Esc the footer reads "Files not changed. Use /restore. Conversation rewound.", replacing "Rewound to previous user message — edit and Enter to resend" and the "/undo puts them back" promise it used to carry. /restore rolls the whole folder back to a point you pick and needs /trust on or Full Access; /undo still takes back the last request's files where it can prove which snapshots belong to this conversation. Refs #6970. Thanks @luestr.
  • /relay writes the session relay to .codewhale/handoff.md, the path a new session reads first, instead of .deepseek/handoff.md. A relay left at the legacy path is still read when the primary file is absent, and the prompt block names the file that was actually read.
  • The highlighted option on an approval card is tagged (Enter), so the default [3 / d / n] Don't allow (Enter) row shows what Enter does.
  • The edit approval card shows only the lines an edit changes, as - and + rows. Lines shared at the start and end of the old and new text are left out, the "replace this" and "with this" sub-labels are gone, and a single edit is no longer headed "edit 1". Lines left out on a side are counted (... (+2 more lines)); several edits are numbered and each shows its first changed line.
  • The three-row preview of a successful command shows one opening row and two closing rows, preferring closing rows that say something passed or failed. Blank rows no longer take a slot, and lines hidden after the last row shown are counted in the … (+N lines) marker too.
  • An MCP server the session has not needed yet shows as not connected in /mcp instead of "not started", with its transport and "Not connected in this session yet. Connects when a tool is needed, or connect it now." in place of zero tool counts.
  • codewhale doctor adds "works without an API key (limited quota; set FIRECRAWL_API_KEY or [search] api_key to raise it)" to the search_provider line when Firecrawl is the provider and no key is set.
  • The stalled-tool notice now ends "Run /jobs to see it and /jobs cancel <id> to stop it." instead of naming exec_shell_cancel.
  • A DeepSeek Harness (dsh) package refused with "No portable components in this package" now lists the skipped rows, each with its package and reason, and the Native composition refusal names the unresolved rows. Both name at most five rows and count the rest.
  • Full Access runs the calls it grants. The built-in Auto-Review floor (publish-like commands, destructive background or headless work, and the Windows npm-launcher hold) applies only in Ask, Auto-Review and Never, and no longer blocks a call under Full Access, including a detached agent's.
  • file_search is one of the model's default tools from the first turn instead of being loaded through tool_search (#6934). It also accepts globs (src/**/*.rs) and several space-separated terms that must all match. Literal matches rank above fuzzy ones, build and dependency folders are skipped by default, and limit goes up to 200. An exclude list replaces the default exclusions, and [] turns them off.
  • fim_edit is offered only on routes that can run it: Chat Completions routes other than OpenCode Zen. The default DeepSeek Flash route speaks Responses and no longer lists it (#6933).
  • Runtime session grants ("remember": true) are stored in the Runtime data directory instead of memory. After a restart a thread's grants stay suspended, and matching calls ask again, until an authenticated client resumes the thread. A grant store that cannot be read holds no grants, so every call asks.

Fixed55

  • Delegated work uses the full explicit turn and time limit. Default child nesting and Workflow plan depth caps are removed; explicit owner restrictions remain. The host no longer reserves the last turn or part of the deadline for a forced report, or makes an extra reporting request after the limit; recorded work and files remain available in the partial-result receipt.
  • Runtime child completions retain their original parent turn after the parent becomes idle or starts a newer turn; terminal receipts remain durable and deduplicated.
  • Windows Native extension hosts resolve DeriveCapabilitySidsFromName at runtime and return an unsupported error during LPAC setup when the export is unavailable (#6953). Windows 10 1607 startup and Native-host acceptance remain unverified.
  • codewhale resume no longer refuses a session whose saved history still holds a raw sub-agent handoff (#6954).
  • Snapshot restore and /undo work with older git, such as the 2.43 that Ubuntu 24.04 ships. They failed there with "only one reference expected".
  • When the model cancels its own background job, it no longer gets a "finished" event or starts a new turn from it; when you stop a job the model started, the model is told it was killed. Cancelling a job that had already exited keeps its real exit status instead of reading "killed, exit 0", and /jobs cancel all no longer reports exited jobs as cancelled.
  • A shell command that moves to the background after 30 seconds shows the same "keep running in /jobs" notice as Ctrl+B, and its card no longer shows the instructions written for the model.
  • todo_write returns a short receipt (counts and the item in progress) to the model instead of repeating the whole list on every call.
  • Goal usage counts the turn that completes, yields or blocks the goal, so tokens_used and time_used_seconds no longer stay at 0. update_goal accepts a progress estimate with yield.
  • Waiting on a running shell job reports how long ago it last printed and whether it is still compiling or already running tests or the program. Stopping a job from /jobs, and the completion the model then receives, say whether build artifacts already on disk survive the kill (#6944).
  • A shell command that has printed nothing for a minute still reads as running ("no output for 1m 05s"), keeps its Stop action and is reachable through the Runtime API; only a job whose process is gone after a restart is stale. /jobs poll and /jobs stdin no longer consume the output the model has not read yet (#6931).
  • /constitution: ratify checks the digest you reviewed in suggestions, so a file that changed after your review is refused as documented; preview shows the block exactly as the model receives it; messages no longer claim a ratify or migrate moves the prompt-cache prefix; the setup wizard no longer lists an authority order that contradicts the base prompt, and it caps your own note so saving never cuts its end. The Simplified Chinese manager uses the glossary term 宪章 throughout. The manager checks whether your signed-in account profile takes precedence and labels an active local file as standby; the Runtime API returns the same guidance body from GET and preview. doctor reports autonomy only from an active local constitution and leaves account checks to sign-in. The context inspector shows the personal constitution as a recorded session message outside the system-prompt layer.
  • The pet shows sub-agents while they run, and a finished one no longer stays "working". Half-block pet sprites are drawn crisply instead of blurred.
  • A rate-limit 429 with a body retry delay of up to 120 s retries the interrupted model request. This includes ambiguous current-quota wording with billing guidance when the body supplies a bounded delay; explicit exhausted account, billing and subscription limits remain terminal (Refs #6923, thanks @Statter).
  • Claude sign-in keeps its PKCE verifier out of the sign-in URL and gives its pasted authorization code one terminal input reader. Failed input restores the TUI; live subscription sign-in remains experimental (Refs #6932).
  • Oversized-session refusals preserve compaction errors and no longer assume that the active conversation alone caused the remaining size limit (Refs #6955, thanks @7jrxt42BxFZo4iAnN4CX).
  • A Codewhale home reached through a symlink or Windows junction keeps saving artifacts and compacting (#6947).
  • Sub-agent state and transcripts also save through a relocated Codewhale home when its junction target already exists. Containment checks use the same resolved state root throughout the operation (Refs #6949, thanks @SparkofSpike).
  • Saving a DeepSeek key in the TUI writes the provider's durable-key marker, so its saved credential remains visible after restart while another provider is active. Older saves missing that marker need one re-save (Refs #6972, thanks @gaord).
  • A workflow gate that blocks its own role is rejected when the plan is admitted instead of deadlocking the run (#6945).
  • Auto-Review gives its guardian an output budget a reasoning model can think inside.
  • Skills are deduplicated across roots by file, ignored-key warnings are grouped, and in-workspace skill links are followed. A session warns once when a [tools] always_load entry matches no tool, and codewhale doctor names a bundled skill whose installed text matches no shipped version. Bundled skills you have not edited now update to the current version even when your Codewhale home is several releases behind; edited ones are still left alone. Bundled skills are installed only into Codewhale's own skills folder, so a custom skills_dir and a legacy ~/.deepseek/skills folder are no longer written to, and codewhale serve, the desktop app and other Runtime hosts now install them there too, as the TUI does.
  • Opening a conversation in a Git repository no longer adds an untracked .codewhale/ to git status or the desktop app's Review panel. The sub-agent coordination folder .codewhale/state now holds a .gitignore that ignores only that folder. Files you keep elsewhere under .codewhale/ are unaffected, an existing .gitignore there is left alone, and the file is never written through a link, so a cloned repository cannot redirect it to your global git ignore file.
  • TUI messages and cards say what happened, once. Provider readiness reads "endpoint reachable · model not checked" instead of "models endpoint 2xx", since some providers list models for a bad key. A failed /rc reads as failed, not "not available", including in /setup. Copy and cut say "Copied to the clipboard", and a failed copy says "Clipboard copy failed: …", in every language. The provider-fallback notice leads with the switch so it fits at 80–100 columns, and the effort field reads auto→high. Alt+V:full error appears only when an error is cut short. The elevation card no longer repeats its heading or a Tool: exec_shell row, and the checklist card drops its checklist: row and shows translated statuses (in progress, not in_progress). A failed read or search names its reason, card bodies no longer repeat their header, run summaries say read file, and MCP calls are no longer folded into a run summary, because their side effects are unknown.
  • DeepSeek V4/V4.1, deepseek-chat, deepseek-reasoner and R-series models on a custom Chat Completions provider now receive your reasoning effort (low, high, max) and thinking setting, as on the direct DeepSeek route. Before, both were dropped from every request.
  • grep_files reports matches relative to the workspace when the workspace path goes through a symlink, such as macOS /tmp or /var or a symlinked project folder. Before, every match came back as a full /private/... path.
  • On Android (Termux), workflow journals, compaction checkpoints, saved tool output and skills work again. Confined file access opened / for reading, which Android's SELinux policy refuses; on Linux it now uses path-only handles that need no read access, with the symlink and escape checks unchanged. Compiled Android builds and on-device use are not yet qualified. Thanks @printf033 (#6980, #6983).
  • Runtime API servers that use different stores on one machine no longer refuse each other with "authenticated Runtime owner belongs to another selected store". On macOS and Linux a store with its own runtime directory gets its own control socket; the default store keeps its usual path. A second Runtime API server that tries to drive a workspace another one already drives is refused and told which process holds it. Watch-only clients are not limited. Windows keeps its current transport, and the standalone TUI and CLI do not take this workspace lease yet. Thanks @gaord (#6924).
  • In Spanish (Latin America), Japanese, Brazilian Portuguese, Vietnamese and Simplified Chinese, /provider's description now matches the English "Switch provider or model" instead of listing only deepseek, nvidia-nim and ollama. Thanks @Lstarsky0 (#6922).
  • MCP servers reconnect when a session sync drops the eager connection pool.
  • The shared pet owner exits after ten minutes with no client.
  • Tool headers keep their clipped part visible at narrow widths, /jobs prints plain exit codes and a three-line tail, and a collapsed tool output shows a single hidden row instead of a "1 line omitted" marker.
  • The shared pet pauses its world and periodic checkpoint writes after its viewers, producer and audio leases expire. Authenticated clients wake it through the existing request queue; its active clock waits for the next frame instead of polling every two milliseconds (Refs #6728, #6155).
  • Ctrl+B and steering input release foreground and background shell waits without stopping their commands. Requests apply only to active waits in the current session, including waits on several tasks; a later wait starts fresh (#6909).
  • Concurrent starts and reconnects for one workspace converge on one Engine owner. A receipt retired during a reconnect is observed again before attaching; files with unsafe ownership, permissions or multiple links are still refused.
  • Local plugin updates retain a private recovery backup while replacing the installed version. Plugin actions marked as requiring approval keep that requirement in Full Access, and internal installation paths are excluded from discovery.
  • Concurrent Files API creates publish a workspace file exclusively. A competing creator gets HTTP 409 and cannot overwrite the winning file. Within one Runtime, writes to an existing file are applied one at a time, so two clients sending the same expected_revision can no longer both succeed. Writes from another process or a shell are not covered.
  • Cache usage accounts for cache-write tokens as well as cache hits when deriving cache misses. Missing cache details remain unknown, and explicit zero counts stay zero (#6913).
  • /profile usage, switching, success and failure replies follow the UI language across all 15 complete locale packs (#6919).
  • On Windows npm installs, the model's environment identifies node.exe as the launcher and warns that killing it by name also stops npm-launched Codewhale sessions. It points to stopping servers by PID or port instead (#6906).
  • Persistent terminal commands keep interactive stdin available while preserving current-shell variables, directories and aliases. Human answers no longer consume the command's completion marker. Oversized raw input batches are refused before writing in canonical line-input mode, across the Terminal dock, terminal/send and the Runtime API.
  • A stream request that receives no response headers in time now adds that the provider may still be loading the model, and names codewhale config set stream.open_timeout_secs 180 (up to 300). codewhale doctor --probe-api reports a live check that ran out of time as "Not confirmed" with "API check got no answer in time", not as a failed credential, and no longer points at replacing the key (#6889, thanks @BX166).
  • When the same model fails with the same upstream HTTP status on two or more requests in a row, the error adds how many times it has failed, that a provider can list a model that is not serving requests, and to choose another model with /model. The count starts over when a request opens its stream, fails another way, or uses a different model or status (#6889, thanks @BX166).
  • A Chat Completions response that reports stop while its reported completion tokens equal the output ceiling the request asked for is treated as cut at the output limit. A partial answer is kept and continued; an empty one fails after that single request instead of being asked for again. The "Model reached the response output limit with no answer or tool call" error no longer depends on the provider having streamed reasoning (#6889, thanks @BX166).
  • A shell command with a descriptor redirect such as npm test 2>&1 or cargo build > /dev/null 2>&1 is no longer classified as a destructive action: its approval card reads "Runs a command" without "Can't be undone". rm -rf /etc 2>&1 is still held as destructive, and a command after a bare & (echo x&rm -rf /etc) is still checked.
  • A plugin command or skill typed on the startup screen resolves for the session that submit begins, instead of reading as an unknown command. The submit waits up to 2 seconds for the engine to install the new session.
  • A session saved in Operate by v0.10.0 and resumed on this build has that release's internal Operate instructions recognized as a runtime message rather than as something you typed. Compaction keeps only the current instructions, so the two no longer disagree about who creates the goal.
  • The agent tool's rejection of an invalid thinking value lists xhigh and ultra, the same values its schema offers. Its description now says that in Operate a child the main session starts edits files and runs the Run tool's built-in checks without a second approval, and that any other shell command follows the session's approval settings.
  • A long line of tool output wraps between words instead of mid-word, and the first row, which sits after the result: or output: label, is no longer wrapped a second time when drawn.
  • A running task's unsaved progress is written to its task record on the deadline set by its first unsaved event. Tool heartbeats and store polls no longer restart that wait, and heartbeats are kept in memory only.
  • On Windows, when the app-server that owned a Runtime has died, the next start now replaces it automatically, as on macOS and Linux. A live owner, a reused process ID, or a publication from another user, store or config is still refused (#6915).
  • /network allow <host> and /network deny <host> take effect on the next tool call without a restart (#6928). Under a managed [network] overlay or a Fleet network_access = false, editing your own [network] table cannot widen the policy: a denial from either layer stands, a deny-by-default authority keeps its own allow list, proxy and fake-IP exceptions, a prompt-by-default authority adds your hosts to its own, and audit logging stays on if either layer asks for it.
  • A workflow's final receipt is no longer dropped when its completion inbox is full, and each agent's queue of messages to its parent holds at most 64; a send past that returns an error instead of growing without bound (#6560).
  • cargo +<toolchain> build, scripts/dev-test.sh and scripts/dev-cargo.sh, also through a wrapper, count as heavy commands for resource admission (#6560).
  • Sub-agent state is written atomically, with the file and its directory flushed before the rename (#6555), and image search reads its seed and result bodies through the size cap (#6554).

Known limits8

  • From a pre-release security review of the local network surfaces, not yet fixed: codewhale serve --insecure and codewhale app-server --insecure-no-auth do not check the Origin header, so with either flag a page on an allowed development origin (localhost:3000, :1420) can drive the Runtime API; use them only on a machine you trust. The one-time codewhale web and --mobile bootstrap capability passes through the browser launcher's arguments, where another local OS user can read it. The opt-in control socket ([control_socket] enabled = true) does not check the connecting user and can be reached from sandboxed commands.
  • The sandbox deny-list for the Runtime daemon socket covers its default locations as this process sees them. It does not cover a daemon started with --socket-path or with a different XDG_RUNTIME_DIR or CODEWHALE_HOME; a run directory created after a long-running sandboxed command started is not hidden from that command; and on macOS, when the workspace is your home directory or another folder above the daemon's directory, a sandboxed command can still move that directory out of the denied path.
  • Ambiguous current-quota 429s without a body retry delay of at most 120 s still end the turn; a header alone does not change that classification. Explicit exhausted account, billing and subscription limits remain terminal regardless of a retry hint. Gemini limits without an accepted body delay are not automatically retried (#6923).
  • Idle CPU has not been measured on FreeBSD or Linux for this release (#6728).
  • Shell commands run by delegated agents appear in /jobs and the work dock with their owner, not in the agent's own detail view; named terminal sessions live in the terminal dock (#6931).
  • The pet view chosen with Ctrl+] is not saved across restarts and cannot be changed inside the F5 inspector. The browser studio and the macOS window are not views in the cycle, and Ctrl+] cannot open the work bar while the pet main view is showing.
  • Computer Use is a preview. Its observation diffs, fresh element targets and named action batches were checked against a macOS fixture app only; packaged installs, installed-model use and sharing the desktop with a person working at the same time have not been qualified.
  • The GET /v1/approvals target and summary redaction is heuristic: a secret passed as a plain word argument is not recognized, so treat approval history as sensitive.

Maintenance7

  • 0.10.1 never reached crates.io because the codewhale-tui package was over the 10 MiB upload limit, so cargo install codewhale-cli kept installing 0.10.0. The package now leaves out test sources, and the release checks every package's size before the first upload.
  • The README and its 18 translations were rewritten in plain language and corrected where they described behaviour wrongly: in Ask, file edits at a Git repository's root apply without a prompt, and Ask asks before shell commands that are not read-only; a at an approval allows similar commands for the rest of the conversation; Full Access turns Codewhale's sandbox off; and only AGENTS.md loads by default, while CLAUDE.md and similar files need project_instruction_imports. The README no longer suggests keeping provider keys in a Codewhale account. CONFIGURATION.md and PROVIDERS.md say a [providers.<name>] table can set wire = "responses" or "anthropic" (Refs #6997). Documentation only.
  • The documentation no longer steers new users to Codewhale accounts, account key storage or cloud dispatch, which are paused for new users, and the user guide says codewhale dispatch is not available. The GitHub Action guide opens with a bring-your-own-key DeepSeek example. docs/PROVIDERS.md explains DeepSeek V4.1 Flash (deepseek-flash) and no longer says the Ollama default is deepseek-v4-flash, and the remaining docs say Work instead of Act. Documentation only. Refs #6486, #6466.
  • Main is mirrored to CNB on every push again, and to GitCode once its token is configured.
  • Contributor pull requests get fast checks again: formatting, lint, the Linux test suite, a Windows build, the npm wrapper smoke and the existing issue-link and credit checks. They can merge as themselves without an administrator override. Pushes to main start no GitHub build or test workflow. The manual CI dispatch on a release commit now also runs cargo-deny, the cargo and npm audits and the OpenHarmony check. CONTRIBUTING.md explains each check and what maintainers do with a pull request.
  • SANDBOX.md and CONFIGURATION.md, in English and Chinese, now state that sandbox_mode can only narrow the sandbox the permission mode already allows, so danger-full-access and external-sandbox take effect only in Full Access (yolo). Documentation only; no behavior change. Refs #6992.
  • CI and test harness only, no change to the shipped binaries. The persistence backlog budget takes five samples and judges enqueue time on the fastest one. Linux CI jobs install apt packages through scripts/ci-apt-install.sh, which bounds every wait and drops an unreachable Azure mirror.

Contributors24

  • Dhruv Singal / @dsingal0 — added Herdr agent state, session resume commands and pane release (#7064).
  • @shenjackyuanjie — diagnosed and fixed the Windows OpenHarmony CMake generator and CLI hashing-module build failures (#6988, #6989).
  • @printf033 — replaced the SELinux-denied root-directory anchor of confined-file I/O with an O_PATH walk (Linux-cfg-gated) and a re-materialized final parent, restoring workflow journal, compaction checkpoint and artifact writes on Android/Termux (#6983); reported the Android confined-I/O failure with strace evidence and an on-device reproducer (#6980). Source change; compiled Android and device acceptance remain unqualified.
  • @aboimpinto — moved config-command parsing and replies onto portable contracts while the host retains effects (#6973).
  • @henrikdukefoss — added the Standard Compute compatible-host descriptor, with live model discovery and its billing basis kept Unknown (#6985).
  • @LIghtJUNction — plugin shell install and in-TUI plugin OAuth sign-in (#6950).
  • @SparkofSpike — live network-policy updates and goal milestone hand-back (#6928, #6930), Windows ampersand classification (#6929), and a relocated Codewhale home including sub-agent state (#6947, #6949). Also removed repeated catalog construction and credential-readiness work from the model picker (#7026), listed what still blocks a session switch (#6948), and fixed custom relay model discovery (#7013).
  • @dajiaohuang — cache-write token accounting (#6913).
  • @gaord — embedder telemetry surface support (#6916) and the DeepSeek saved-key marker diagnosis and fix (#6972, #6974). Also gave each Runtime store its own control socket and one driver per workspace (#6924), and added reading and writing a workspace's project trust through the Runtime API (#6959).
  • @Lstarsky0 — localized profile replies (#6919), workflow gates that block their own role (#6952), proxy-independent MCP loopback checks (#6971, #6975), durable steering/child-approval acceptance checks (#6967, #6966), and an app-server hook log that no longer lands in the project directory (#6921). Also made feedback truncation readable in ASCII-safe mode, added a statusline scroll rail, and removed duplicate clipped descriptions from split-view hotbar setup (#7027, #7028, #7029). Kept nested list indentation in rendered markdown, kept a to-do row's status word when its title is long, and put the approval footer's separators between its hints (#7030, #7033, #7034). Also lined up the provider lists' status column (#6984), brought the /provider description in five language packs up to date (#6922), said Work in the /statusline Mode hint (#7012) and fitted more /statusline items on short terminals (#7025).
  • @jayanthvee — Windows npm launcher guidance (#6906).
  • @asto18089 — callback-window reference fix for longer browser sign-in waits (#6865). Also restricted the CNB mirror to the project owner so forks skip it while missing upstream credentials still fail explicitly (#7016, with initial absent-secret handling co-authored by @zhuowp).
  • @BX166 — reported three provider failure modes measured on AICraft's own traffic: a cold model that reads as a dead connection, a listed model that fails on every call, and a response cut at the output ceiling that reports stop (#6889).
  • @harryvizcaino-oss — reported the invalid Full Access configuration guidance shown to the Paseo ACP client (#6992).
  • @rafacouto — reported Linux sandbox mount failures for symlinked credential directories and supplied a standalone bubblewrap reproduction (#7007).
  • @leoca — fixed the command splitter behind the destructive-command checks so a backslash-escaped quote outside quotes is an ordinary character, as the shell treats it (commit 82a14ee2d1).
  • @luestr — reported refusals when starting a new session (#6981) and the /undo notice that reported files reverted when only the conversation had been rewound (#6970), and a session that could not be restored after its provider was deleted (#6996).
  • @zhuowp — found that the Windows shell's Python UTF-8 default was discarded whenever hook variables were applied, and fixed the merge so it survives while explicit overrides still win (#7041), and documented the JSONPath subset the Web tool's fields option accepts (#7046).
  • @Asteria1028 — asked for /init to write AGENTS.md in the interface language (#6964).
  • @SakuraNeko — asked for HarmonyOS PC support, which shaped the HarmonyOS install guidance (#1072).
  • @8sero — reported the TUI crash in non-Latin-script sessions, with the panic signature that located the byte-index slice (#7048).
  • @SergiuSSoluS — reported queued turns being delivered again after a session was restored (#6978).
  • @Statter — reported rate-limit retry behavior that informed the bounded current-quota 429 retry fix (#6923), and black-on-black body text on terminals that do not report their background (#7043).
  • @7jrxt42BxFZo4iAnN4CX — reported oversized-session refusals that informed compaction error preservation and size-limit attribution (#6955), SSE retries capped by the stream-open window (#7045), and a second session that could not be resumed in a busy workspace (#7042).