This release brings self-hosted runners into the CLI: a new claude self-hosted-runner command group (orchestrator, setup, doctor, code-sign, decode-token) that anyone can reach without a flag, plus claude --environment ccpool_... to start a cloud session on one of your own environments, non-interactively if you pass a prompt. Memory becomes read-write with a memory_write tool that creates or overwrites whole documents, refusing read-only stores, empty content, oversized content and anything a secret scan flags, and requiring CLAUDE_MEMORY_STORES, the allow_memory_sync permission and CLAUDE_CODE_DISABLE_ORG_MEMORY left unset. Cross-session messaging arrives in usable form for the parts that ship on: a /list-agents command, a new crossSessionInbound setting with accept, hold and refuse, coordinator messages delivered by default when it is unset, and a confirmation prompt for cross-machine sends when peer isolation is on. Sandbox credential masking gains JWT decoding, per-claim masking and AWS SigV4 re-signing via awsPairs, and runners can now refuse repo-committed settings that reach outside the workspace, defaulting to warn. Several things are present but switched off: the ListAgents tool and the local messaging inbox need tengu_harbor_kite or CLAUDE_CODE_HARBOR_KITE and a non-Windows machine, artifact document-database actions need tengu_umber_lattice or CLAUDE_CODE_ARTIFACT_DB, untracked-file upload to cloud sessions needs tengu_violin_wood with remoteFileMode set to container_sync, SSE work hints need CCR_SHR_SSE_HINTS, and the attention budget and PR review artifact have no trigger at all in this build.
Official notes✓ syncedPackage@anthropic-ai/claude-codeDiffv2.1.223 → v2.1.224ProviderclaudeModelclaude-opus-5 (effort medium)
44
Use it now
168
You'll notice
41
Not switched on
81
Env Vars / Flags
Official Changelog
Official · Anthropic
Anthropic’s official release notes
Published verbatim by Anthropic for v2.1.224 — shown here alongside the source-level analysis below. Text is unmodified from the upstream changelog.
Added self-hosted environments: claude self-hosted-runner turns your own machines or containers into a place Claude Code web, mobile, and desktop sessions can run, on Team and Enterprise plans
Added archive plugin source: install plugins from a zip over HTTPS without git or npm, with optional SHA-256 pinning
Added a cancel-and-confirm step when removing an unavailable paste changes a command's text
Added ANTHROPIC_BEDROCK_REGION_PREFIX env var for Bedrock to prefer a specific cross-region inference profile over the AWS_REGION-derived one
Added crossSessionInbound and dialogExpiry settings: cross-session messages sent to a session running with bypassed permissions are held for your approval, and messages to other sessions auto-deliver
Added sandbox credential-masking options: extract and onExtractNoMatch for structured env values, decode: "jwt" with maskClaims for JWT-aware masking, and awsPairs/sigv4 for AWS SigV4 re-signing; these need network.tlsTerminate and are honored only from user, managed, or --settings settings
Added cross-session SendMessage: Claude Code sessions can now message each other, on any of your machines, with ListAgents to discover them (macOS and Linux)
Fixed long (>200 char) project paths resolving to another project's session directory under a shared sanitized prefix; session list, rename, fork, delete and /resume no longer cross projects
Fixed SendMessage reporting "Message sent" when the write to a teammate's inbox had actually failed; failed deliveries are now reported as errors
Fixed sandbox filesystem deny entries written with a trailing slash (e.g. denyRead: "~/.aws/") being silently bypassable on Linux and macOS
Fixed sandbox violation details never appearing in Bash tool results; Claude now sees which file or network access was denied and why
Fixed MCP tools that connect mid-turn being deferred for tool search without their names announced to the model
Fixed plugin install records being silently corrupted when the same plugin is installed in multiple projects
Fixed recalled or restored paste content occasionally attaching wrong data or silently losing text when the paste had aged out or placeholder numbers collided
Fixed copy-on-select on Wayland sometimes not reaching the clipboard; the two selection writes no longer race
Fixed the feedback survey's transcript share silently failing on long sessions; a failed share now shows an error instead of a success message
Fixed Remote Control auto-start intermittently failing with "Remote credentials fetch failed" on a cold start with a stale login token
Fixed Remote Control and SDK clients showing a blank "(no content)" message after /clear and other output-less commands
Fixed a Remote Control session recreated after its server session expired uploading prior local conversation history into the new session
Improved fullscreen mode to keep the full pre-compaction history in scrollback across repeated compactions, instead of only the most recent interval
Improved Remote Control: attached web and mobile clients now see compaction progress and the post-compaction boundary instead of a silent pause; /clear resets now propagate to attached clients
Improved Remote Control: connection failures now show a persistent failure indicator with details and a reconnect shortcut, instead of only an 8-second toast
Removed the 200-subagent-per-session spawn cap; long-running sessions no longer refuse new agents (concurrency and depth limits still apply)
Changed managed settings: the approval prompt no longer re-appears after re-login or org switching when the organization's settings are unchanged
Changed the feedback-survey transcript share: with your consent it now also uploads the last request's model settings — the system prompt (which includes your CLAUDE.md instructions), tool definitions, and model parameters. Secrets are redacted as before, and these fields are dropped first if the share is too large
Changed the Bash tool description to always note that command output is displayed to the model, not reliably to the user
Changed recalled paste placeholder numbers to renumber when accepted into the input
Changed Remote Control to archive the stale server session instead of leaving a dead one listed when a fresh session is minted after compaction or /resume
[VSCode] Fixed the extension showing Remote Control as connected after the connection failed
Fixed a session resume silently reconnecting Remote Control after the user turned it off (--resume, SDK hosts, and the VS Code extension)
[VSCode] Fixed sessions not honoring remoteControlAtStartup when explicitly enabled
Source: anthropics/claude-code · CHANGELOG.md · 31 entries · synced automatically when Anthropic publishes official notes for a version.
Source-Level Analysis
Reverse-engineered from a diff of the bundled CLI — deeper, structured detail. Unofficial.
Shipped inside the bundle with its gate off, its guard hardcoded false, or nothing calling it. What the code shows, not a roadmap: no claim about what is released, announced or planned.
Filter
What probably matters to you
109 items
Anything you can use today, anything that visibly changes, and anything worth poking at. One line each, open for detail.
/list-agents shows every Claude session you can message #
Juicy
Type /list-agents or /peers to see every Claude session you can message, with status and age.
/list-agents/peers
Use it now · Slash Commands
What
A new slash command, aliased /peers, lists your subagents alongside other reachable Claude sessions: local ones on the same machine, cloud sessions, and Remote Control bridge sessions. Each row shows status, working directory and age. It appears only when peer messaging itself is available.
Details
Gated by the same check that enables sending messages to peers, so if messaging is off the command is not listed.
Usage
/list-agents
Evidence
List subagents and other Claude sessions you can message
MCP tools that need you to click through are not silently pre-approved #
MCP tools that need you to click through always reach you instead of being auto-approved.
You'll notice · MCP
What
An MCP tool that declares it requires user interaction no longer has its permission re-checked in the background and auto-proceeded when the check returns "allow". Those tools always reach you.
Details
The background re-check bails out when the tool reports requiresUserInteraction, which comes from the MCP metadata key anthropic/requiresUserInteraction.
Separately, the permission-prompt telemetry event now records isMcp, distinguishing MCP tools from built-in ones.
`--teleport` and `--cloud` now show up in `claude --help`.
--teleport--cloud--remote
Use it now · CLI
What
Both options are no longer hidden and now appear in help output. --remote stays hidden as a deprecated alias.
Evidence
--cloud [description|session_id|url]
claude plugin eval writes a report and publishes it by default #
Juicy
Plugin eval now writes report.html and publishes it to claude.ai unless you pass --no-publish.
claude plugin eval--no-publish--publish-report--report
Use it now · Plugin Eval
What
After cases run, report.html is written into the results directory even without --report, and the report is published to claude.ai by default rather than only with --publish-report. Pass --no-publish to keep it local. --no-publish and --publish-report together are an error. Publish-by-default is controlled by a server flag whose built-in fallback is on, so with no server value it publishes; an explicit --publish-report ignores the flag entirely.
Details
The JSON result is now computed once and shared between writing, publishing and printing.
Publishing failures explain that artifacts are turned off for the account, provider or privacy mode, and the failure text names the local copy when one was written.
--publish-report's help text changed to match the new default.
Usage
claude plugin eval ./my-plugin --no-publish
Evidence
tengu_quartz_thimble, --no-publish and --publish-report are contradictory — pass at most one.
Auto mode can classify questions instead of stopping #
Juicy
In auto mode, a question can be classified and handled instead of halting the run.
CLAUDE_CODE_AUTO_MODE_CLASSIFY_ASK_USER_QUESTION
Use it now · Auto Mode
What
In auto mode, deciding to ask on the AskUserQuestion tool no longer automatically counts as needing a human and halting the run; it can be classified and handled instead. CLAUDE_CODE_AUTO_MODE_CLASSIFY_ASK_USER_QUESTION decides this if set; otherwise the server-side auto mode config's classifyAskUserQuestion value applies and is treated as on unless it is explicitly false, so with no server value the new behaviour is active.
Details
The old path logged a tengu_auto_mode_fallback_to_ask event and stopped.
Evidence
CLAUDE_CODE_AUTO_MODE_CLASSIFY_ASK_USER_QUESTION
Cross-machine messages ask first when peer isolation is on #
Juicy
With isolatePeerMachines on, cross-machine messages now stop and ask for your approval.
isolatePeerMachines
Use it now · Cross-Session Messaging
What
With the isolatePeerMachines protection enabled, sending a message to a Remote Control session, to a cloud session, or to a name that could not be resolved because the cloud session list was unavailable, now stops and asks for your explicit approval instead of going ahead.
Details
The three triggering cases are bridge addresses, resolved cloud sessions, and unresolvable names during a failed session-list lookup.
Evidence
isolatePeerMachines is enabled \u2014 cross-machine message requires explicit approval
New dialogExpiry setting for how long forwarded dialogs wait #
Juicy
Set dialogExpiry to control how long a forwarded permission prompt waits before resolving to its safe default.
dialogExpiryCLAUDE_CODE_USER_DIALOG_TIMEOUT_MS
Use it now · Permissions
What
A settings key accepting 60s, 5m, 10m or never sets how long a permission or user dialog forwarded to a remote client stays parked awaiting an answer, and how long a held cross-session message waits for approval, before it resolves to its safe default. Without the setting the timeout is 300000 ms (5 minutes). CLAUDE_CODE_USER_DIALOG_TIMEOUT_MS overrides both.
Details
The setting is read from trusted configuration sources only.
Prompts answered locally are unaffected; this only applies to dialogs sent to a remote client.
Usage
{ "dialogExpiry": "10m" }
Evidence
Max time a permission/user dialog forwarded to a remote client stays parked awaiting an answer
crossSessionInbound accepts accept, hold or refuse for messages arriving from your other sessions.
crossSessionInboundacceptholdrefuse
Use it now · Cross-Session Messaging
What
A settings key controlling what happens when another of your Claude Code sessions sends this one a message. Values are accept, hold and refuse. Left unset, a message is delivered automatically only when the sending session's permission mode is in the same class as yours, and is otherwise held for you to approve.
Details
Held and refused messages produce user-facing text naming the setting, for example Your "crossSessionInbound" setting is "hold".
Sandbox allow and deny rules can now target a specific port instead of the whole host.
Use it now · Sandbox
What
Domain allow and deny rules in the sandbox now parse a host pattern plus an optional port, so a rule can target a single port rather than the whole host.
Details
Matching fails closed on both sides: a port-qualified rule matches a request with an unknown port when denying, and does not match when allowing.
Otherwise the port must match exactly.
Deny rules still come from sandbox.network.deniedDomains plus WebFetch-style domain: permission rules.
Evidence
sandbox.network.allowManagedDomainsOnly is set and
claude plugin eval now publishes the HTML report by default when your account supports it. --publish-report changed meaning to "require publishing", and explains why if it is unavailable; --no-publish keeps the report local. Passing both is now an error. --report now means the report replaces the results directory, implying a default location.
Details
Results from the LLM judge on long inputs now append an advisory suggesting a regex grader instead.
Evidence
Error: --no-publish and --publish-report are contradictory — pass at most one.
Artifact tool now explains exactly which credential is blocking it #
The artifact tool now names the exact credential blocking you, with a fix for each.
ANTHROPIC_API_KEYapiKeyHelper
You'll notice · Artifacts
What
When you are not logged in, both the input check and the tool call stop immediately and name the credential source that is standing in the way: the ANTHROPIC_API_KEY environment variable, the apiKeyHelper setting, a token file descriptor, or a Unix socket, each with its own fix.
Details
for the environment variable the advice is to unset it, or run /logout and decline the API key approval before logging back in
Evidence
Unset the ANTHROPIC_API_KEY environment variable, or claude /logout then say "No" to the API key approval before login.
Clearer denial when a tool needs approval but no prompt can be shown #
When no prompt can be shown, denials now tell the model not to fake success.
You'll notice · Permissions
What
In background and async contexts where a permission prompt cannot be displayed, tools requiring approval are now denied with an explicit instruction not to claim success or retry, replacing the generic "Permission to use X has been denied" wording. A structured decision reason is recorded alongside it.
Evidence
Permission for this tool use was denied: it requires interactive approval, and permission prompts are not available in this session.
Messages from another session now render as a chat line instead of raw XML.
You'll notice · Cross-Session Messaging
What
A message arriving from another Claude Code session used to show as raw XML. It now renders with an "@ name" header and the body indented, with the wrapper tags stripped. Outside verbose and transcript mode, and when not queued, it collapses to a compact peer marker.
Evidence
UserCrossSessionMessage
Feedback tool now covers Claude's own behaviour, not just product bugs #
Claude will now offer to draft feedback when it itself goes wrong in your session.
You'll notice · Feedback
What
The built-in feedback drafting tool used to be scoped to Claude Code the product. It now explicitly handles model-behaviour reports too, and will offer to draft one when Claude itself goes wrong in the session: retracting a confident answer, stopping short of the task, declining something reasonable, spawning too many subagents, tone problems, over-questioning, or scope creep.
Details
Report fields are unchanged: type, title, details, area, failure_mode, task_category.
Evidence
draft product or model-behavior feedback report queue
History search puts the cursor on the text you searched for #
After a reverse history search, the cursor lands on the text you searched for.
You'll notice · Input
What
After accepting a reverse history search, the cursor now lands on the last case-insensitive occurrence of your search term in the recalled line, instead of a fixed position. If the term is not found in the line, the cursor goes to the end.
Details
Leaving the search without accepting now restores the input to its pre-search state.
Linux sandbox violations now show the real command, so ignoreViolations patterns match what you wrote.
ignoreViolations
You'll notice · Sandbox
What
Records of blocked syscalls in the Linux sandbox now carry the actual command text rather than an opaque internal id, using the same lookup macOS already used. This also means ignoreViolations patterns match against the command you wrote.
Evidence
resolveCommandText
Messages from other sessions can be held for your approval #
Messages from a session with a mismatched permission mode are held and shown with an approve/deny dialog.
You'll notice · Cross-Session Messaging
What
When another Claude Code session sends this one a message, it can now be held instead of delivered. Two new reasons for holding: the sender's permission mode does not match yours, and a sender that never stated its mode into a session that bypasses prompts. Held messages appear with an explanation and, where a permission handler is wired up, an approve/deny dialog with a preview. Approving, denying or letting it expire sends a status message back to the sender.
Details
Behaviour is controlled by the crossSessionInbound setting, resolved from policy, flag and user settings, then narrowed to the most restrictive of local and project settings.
With no explicit setting, a session that bypasses prompts defaults to holding messages and every other session defaults to accepting them. An unrecognized permission mode fails closed to hold.
Hold reasons recorded are explicit-setting, mode-unknown, mode-mismatch, no-mode-asserted and bypass-default; held, accepted and refused outcomes are all reported.
The sender-mode matching half is additionally behind the tengu_harbor_kite_mode_emit flag, which is off in this build.
The approval dialog is registered as a new notification type with its own title.
Evidence
A message from another session needs your approval, The sender did not attest its permission mode and this session bypasses prompts. Review it below, or set "crossSessionInbound" to "accept".
Plugins enabled only by repo settings are no longer auto-installed and recorded #
A plugin switched on by repo settings alone is no longer installed into your own records.
You'll notice · Plugins
What
A plugin turned on solely by settings committed in the repository you opened is no longer written into your own plugin installation records. Previously a project or local settings file could get a plugin auto-installed on your behalf. Plugins backed by your own config are unaffected.
Details
Skipped entries are logged with the reason that they were enabled only by repo-authored settings.
Evidence
Skipped auto-recording
Remote Control disconnects appear in the transcript #
Losing Remote Control now adds a transcript warning hinting at `/remote-control` to reconnect.
/remote-control/remote
You'll notice · Remote Control
What
Losing the Remote Control connection now adds a warning message to the conversation instead of failing silently, with a hint to run /remote-control to reconnect. The hint is omitted when the reason already mentions logging in, remote control, a restart, policy or an update, and an identical message is not repeated twice in a row.
Details
only reached while the Remote Control bridge is running
errors now also record whether the cause was the terminal or something else
Blocked network calls in the sandbox now tell you the host, port and reason.
You'll notice · Sandbox
What
When the sandbox blocks an outbound connection, it records a violation naming the host, the port and a reason instead of silently failing. Reasons include sandbox policy unavailable, malformed host, host is on the deny list, host is not on the allow list, user denied, and permission prompt failed.
Details
Blocked HTTP requests get their own violation line with the URL query string redacted.
A per-domain reason override can be supplied through deniedDomainReasons.
Domain rules can now carry a :port suffix, matched against the port of the connection.
Evidence
host is not on the allow list
Tell another Claude session something and hear back when it was not delivered #
If another session holds, denies or ignores your message, you now see a warning instead of silence.
You'll notice · Cross-Session Messaging
What
When you send a message to another Claude session and the recipient holds, denies, or lets it expire, your session now prints a warning line and quietly tells the model not to sit waiting for a reply. Receipts arrive in batches of up to 200 per status and are de-duplicated per recipient address.
Details
Two surfaces per receipt: a visible warning line, and a low-priority note injected into the conversation so the model stops blocking on an answer.
Covers held, denied and expired outcomes.
Evidence
[Cross-session delivery notice]
Memory writes are scanned for secrets before they land #
Memory writes get scanned for secrets and refused, naming what matched and that the store is shared.
Not switched on · Memory
What
Memory document content is scanned before it is written, and a match refuses the write with a message naming what matched and noting that the store is shared with everyone on the project. The tool's own instructions carry the same rule. Behind tengu_haze_glass, which is false in this build.
Evidence
Never write secrets or credentials into a memory \u2014 the store is shared with every collaborator on the project, and such writes are refused.
self-hosted-runner orchestrator polls for spawn hints and runs your own spawn script #
Juicy
An orchestrator subcommand polls for capacity hints and runs your own spawn-runner script to autoscale.
A new subcommand for people running their own Claude Code runner fleet. It polls the server for hints that more runner capacity is needed and runs ${hooks-dir}/spawn-runner once per hint, so autoscaling is handled by a script you write. --hook-concurrency defaults to 4, --hook-timeout to 60s, and --expected-spawn-seconds to 120 (sent to the server as the lease time). --min-idle requests standby capacity, --debug-dir keeps diagnostics.
Details
Hook exit codes are a contract: 0 is success, 1 is retryable and backs off, 2 or higher is non-retryable and trips a circuit break.
The tail of the hook's stderr is forwarded to the server as the failure reason.
It exits non-zero if the poll endpoint returns HTTP 400, 401, 403, 404 or 426.
It refuses to start when the hook timeout plus the 5s SIGKILL grace period exceeds --expected-spawn-seconds. The hooks directory is required.
Evidence
/v1/code/runners/self-hosted/spawn-hints/poll
Advisor tool options and session budgets documented #
Juicy
Bundled API docs now cover advisor tool limits, caching, and session spend budgets you can set or remove.
max_usesmax_tokenscachingmax_list_cost
Use it now · API Docs
What
The bundled tool-use reference now documents max_uses, max_tokens and caching on the advisor tool definition, along with the advisor_tool_result_error content variant and its error codes. The cURL guide gains session budget examples: creating one with max_list_cost in minor currency units, raising or lowering it, or removing it, which is one-way. Agent version is now an integer rather than a string.
Evidence
advisor_tool_result_error
Compact summaries are flagged as synthetic in SDK output #
Compaction summaries are flagged synthetic in SDK and stream-json output so you can filter them.
stream-json
Use it now · SDK Output
What
Messages produced by compaction are now marked synthetic in SDK and stream-json output, so consumers can filter them out alongside meta and transcript-only messages.
Details
The serialiser now calls a shared helper instead of computing the flag inline from meta and transcript-only checks.
A local-command result that trims to an empty string after its stdout and stderr wrappers are stripped now returns nothing instead of emitting an empty assistant message.
Evidence
isCompactSummary
Git identity, commit signing and proxied clones for runner sessions #
Juicy
--configure-git sets a commit identity and installs SSH commit signing backed by a code-sign subcommand.
--configure-git sets a git identity of Claude <noreply@anthropic.com>, installs an SSH commit signing program and Co-authored-by hook stubs under <base-dir>/.runner, and requires git 2.34 or newer. The signing itself is done by a new self-hosted-runner code-sign subcommand, which sends the commit to the session's signing endpoint using the session access token.
Details
--use-anthropic-git-proxy routes clones through Anthropic's git proxy using a repo-local credential helper. It requires --capacity 1 and git 2.32 or newer.
A governed-git configuration delivered by the server can supersede the proxy, mounting repos read-only and resetting remote.origin.url back to the plain upstream address.
Only SSH-style signing is supported by code-sign; anything else is rejected.
Evidence
code-sign: only SSH-style signing (-Y sign) is supported; got:
Marketplaces can offer plugins as zip downloads with an optional sha256 pin that doubles as the version.
archivesha256
Use it now · Plugins
What
A marketplace entry can now point at a plugin as an archive: an HTTPS URL for a zip file, with an optional sha256 digest. The digest is checked on every download and also serves as the plugin's version identity, so a changed archive is a changed version. This source type is always available, not gated.
Details
If the zip contains a single wrapping directory, it is stripped so the plugin's files land at the top level.
Archives must be served over HTTPS.
Evidence
HTTPS URL of a zip archive containing the plugin.
Plugins can be installed from an HTTPS zip archive #
Zip plugin installs strip a single wrapping directory so the plugin lands at top level.
sha256
Use it now · Plugins
What
A marketplace entry can now point at a zip file over HTTPS instead of a git repo or npm package, with an optional sha256 digest that is checked on every download. When no version is declared, that digest is what identifies the version. If the zip contains a single wrapping directory, it is stripped so the plugin lands at the top level.
Details
The URL is checked against a new guard that rejects loopback, link-local, IPv4-mapped IPv6, unique-local and cloud-metadata hosts, so a marketplace entry cannot make Claude Code fetch from inside your network.
Authentication headers are inherited from the enclosing url-sourced marketplace only when the origins match.
The error message for marketplaces configured in settings now lists this type alongside github, git-subdir, npm and url.
Evidence
Archive URLs must use https:// and must not point at a loopback, link-local, or cloud-metadata host
Remote sessions can run on self-hosted runner pools #
Juicy
You can target your organization's own runner machines when starting a remote session.
/remote
Use it now · Self-Hosted Runner
What
Claude Code can now list your organization's self-hosted runner pools (machines your org runs itself rather than Anthropic-hosted ones) and target one for a remote session. Availability is decided by your organization's server-side configuration and first-party login; other auth returns an empty list.
Details
Pools come from /v1/code/runners/self-hosted/pools with the beta header ccr-byoc-2025-07-29, and each entry carries a pool id, name and a count of live runners.
A pool id prefixed ccpool_ is sent as the self-hosted pool target instead of the usual environment id.
A pool default coming from an untrusted source is ignored with a warning pointing at /remote-env, and a public Project rejects pools outright: public Projects run on Anthropic-hosted infrastructure only.
List outcomes are recorded with separate non-200, API-error and unexpected-response variants.
Runner collects metrics from its child sessions and re-exports them #
Juicy
Set OTEL_METRICS_EXPORTER=prometheus and child sessions report through the runner, giving one scrape target per machine.
OTEL_METRICS_EXPORTER
Use it now · Self-Hosted Runner
What
The runner's health server accepts OTLP/JSON metrics on POST /v1/metrics and merges them into its own /metrics output, labelled with session_id and client_platform. When capacity is above 1 and you have set OTEL_METRICS_EXPORTER=prometheus, child sessions are automatically pointed at http://127.0.0.1:<health-port>/v1/metrics instead, so one scrape target covers the whole machine.
Details
Requests from any address other than loopback get 403. Bodies over 1 MiB get 413.
Child metric names that collide with the runner's own claude_code_self_hosted_runner_ prefix are dropped.
A session's series are swept from the output when that session ends.
Sandbox credential masking can fake JWTs, mask single claims, and re-sign AWS requests after swapping keys.
sandbox.credentialsdecodemaskClaimsawsPairssigv4
Use it now · Sandbox
What
Credential entries under sandbox.credentials can now use decode: "jwt" to swap a real token for a structurally valid fake so client-side parsing still works, and maskClaims to mask only named claims and rebuild the token. A new awsPairs setting groups masked environment variables into access-key, secret and session-token trios so the proxy can re-sign AWS SigV4 requests, and a new sigv4 block sets deny or passthrough policy for streaming uploads, presigned URLs and SigV4A.
Details
For environment variables, combining decode with extract, or with a fail-closed onExtractNoMatch, is rejected at validation time.
SigV4A signatures are asymmetric, so there is no shared key to recompute; the sigv4 block decides what happens to them.
awsPairs and sigv4 are only honored from user settings, managed/policy settings, or the CLI --settings flag, and are now forwarded into the proxy's credential block.
At startup, a masked environment variable whose name uses the reserved synthesized-placeholder prefix produces a warning and degrades to deny.
Evidence
Policy for SigV4A (AWS4-ECDSA-P256-SHA256) asymmetric signatures: there is no shared-key HMAC to recompute., awsPairs
Nine operator tools can inspect runners, sessions, secrets, health, metrics and logs, loaded only via --base-tools.
CLAUDE_CODE_REMOTE
Use it now · Self-Hosted Runner
What
Nine new tools let an operator inspect and drive a self-hosted runner fleet: self_hosted_runner_get_pool, _list_runners, _list_sessions, _list_secrets, _spawn_local, _read_health, _read_metrics, _tail_log and _requeue_session. They load only when the CLI's --base-tools names one of them, and never when CLAUDE_CODE_REMOTE is set or the session kind is "bg". Auth reuses the operator's existing OAuth session, and tailed logs are redacted for secrets before reaching model context.
Details
The enabling latch is one-way in production: the internal helper that turns the operator tools back off is documented as test-only.
When a runner spawns a session, any tool name starting with self_hosted_runner_ is stripped from the server-supplied tools list before launch, so a spawned session cannot be handed fleet-operator tools.
If stripping empties the list, the --tools argument is dropped entirely and the default tool pool is used.
Evidence
[runner:session] Stripped self-hosted-runner operator tool names from the server-supplied tools arg, self_hosted_runner_spawn_local
Advisor entry added to Managed Agents multiagent rosters #
Multiagent rosters can include one advisor entry so the main thread consults a stronger model mid-turn.
advisor
You'll notice · Claude API Skill
What
Rosters accept a new {"type": "advisor", "model": ...} entry, at most one per roster, letting the main thread consult a more capable model partway through a turn.
Details
Consultations run as a platform-spawned thread under a reserved name and do not count against the 25-concurrent-thread limit.
Advice arrives as an agent.thread_message_received event, either plaintext or [{"type": "redacted"}] depending on the advisor model.
Fable 5 is documented as temporarily unavailable in the advisor role.
Evidence
anthropic.advisor
Memory documents carry version tokens and report conflicts #
Org memory documents now show version tokens and report conflicts so concurrent edits get retried instead of clobbered.
You'll notice · Memory
What
Reading an org memory document now shows a version token next to the updated date, writes report the version they produced, and a concurrent edit produces a distinct conflict result telling the model to re-read the document and retry with the fresh token. Requires org memory to be enabled for the session.
Details
The conflict message is "The memory store reported a concurrent change to this document."
The conflict result also carries the conflicting path taken from the server response.
The version token is appended to reads in the form [version: ...].
Evidence
The memory store reported a concurrent change to this document.
/ultrareview prompts and free-quota counts, all switched off by default #
Your remaining free cloud reviews can appear in the slash menu and in tips after commits.
/ultrareviewCLAUDE_CODE_ULTRAREVIEW_QUOTA_FIXTURE
Not switched on · Code Review
What
New code fetches your remaining free cloud reviews from /v1/ultrareview/quota (3 second timeout) and can show that count in the slash-command menu, plus two one-off tips: a prose pointer, and a hook that fires after a git commit suggesting /ultrareview before you push. Each of the three surfaces, slash_menu, prose_pointer and post_commit, is keyed separately in the tengu_ultrareview_awareness remote config, so with no server value nothing appears.
Details
CLAUDE_CODE_ULTRAREVIEW_QUOTA_FIXTURE substitutes a fixed quota response instead of calling the API.
Evidence
Tip: Run /ultrareview before you push to catch bugs with a cloud-based multi-agent review
Artifact tool gains a document database, off by default #
Juicy
Published artifacts can gain a document database Claude reads and writes, off unless you set the env var.
CLAUDE_CODE_ARTIFACT_DB
Not switched on · Artifacts
What
The tool that publishes artifacts can now read and write a published artifact's document database, through two new actions read_db and write_db. Reads take a db_op of get, list or query; writes take set, update or delete, addressed by collection and doc_id. The actions only appear in the tool's schema when the tengu_umber_lattice gate is on (source fallback is false, real value from remote config) or the CLAUDE_CODE_ARTIFACT_DB environment variable is set.
Details
A collection is a path of 1 to 31 slash-separated segments (letters, digits, _ - . ~ : @ + per segment), so subcollections nest like boards/b1/columns; doc_id is a single segment. There are byte caps on the composed document path and on serialized data.
Queries support where comparators including the Firestore-style array-contains, plus order_by, limit and cursor; list results page through a cursor.
Rows read back are wrapped in a === BEGIN ARTIFACT DB fence and labelled as collaborator-written data, not instructions, and the read-consent prompt warns that collaborator-written rows will be read into the conversation.
Prompts flag ownership: a suffix of "(someone else's artifact)" or "(ownership unconfirmed)" and a shared-with note, and the consent prompt says the database is written by its collaborators when a share probe fails.
Consent is recorded per artifact for the session, once for reads and once for writes, with separate handling in plan mode and for notification-triggered reads.
Transcript lines render as "read database" and "write database"; verbose mode shows the target document and share status on writes.
Backend errors are normalised to a fixed set (not found, invalid argument, quota or rate, busy, upstream auth, store unavailable, not declared) each with a human remedy.
Read is treated as read-only and safe to run concurrently; write is not.
Evidence
Read a published artifact's database \u2014 collaborator-written rows will be read into the conversation, Database operation: 'get', 'list' or 'query' for read_db; 'set', 'update' or 'delete' for write_db. Required for both database actions; meaningless for every other action., database write committed, CLAUDE_CODE_ARTIFACT_DB, Database collection path: 1-31 "/"-separated segments (letters, digits, _ - . ~ : @ + per segment), so subcollections nest like "boards/b1/columns". Required for read_db and write_db.
Cross-session messaging inbox now actually starts at startup #
Juicy
Startup can now actually open the local socket that lets other sessions message you.
Startup opens a local socket so other Claude Code sessions on the same machine can send this one messages. In the previous build the call site was empty. It is off unless the tengu_harbor_kite gate is on (in-source fallback false) or CLAUDE_CODE_HARBOR_KITE is set, and it never runs on Windows.
Details
Startup clears CLAUDE_CODE_MESSAGING_SOCKET and, unless a socket path was passed explicitly, uses the default path.
Success and failure are reported as agents_cross_session_inbox, with a bind_failed reason; setup time is recorded as setup_uds_messaging_ms.
Skipped with a log line on remote thin clients and when the gate is off.
Evidence
[uds-messaging] Skipped: cross-session messaging gate off
The thinking-effort picker can show what each level costs relative to the default.
Not switched on · Thinking Effort
What
The thinking-effort picker gains a description line under each level: the default level is labelled as the default, and the others show an estimated multiple of the default's cost taken from the model's cost index. When shown it replaces the warning about overthinking at the top level. It is behind the remote flag tengu_marbled_teal, which falls back to off in this build, so whether you see it is decided by server config.
Evidence
The default effort for this model
Fleet view can list sessions it has no record of #
Fleet view can show other running sessions it never tracked, once two gates are on.
Not switched on · Background Tasks
What
The fleet view refresh folds in other concurrent interactive sessions found in the local process registry, so sessions started outside its own bookkeeping appear. Needs both the tengu_fleetview_peers gate (in-source fallback false) and the cross-session messaging gate.
Details
A registry entry qualifies if it is a different pid, has a session id, reports a peer protocol version at or above a minimum, and was seen within the last 24 hours.
Synthesised entries are keyed off the other process's pid; a locally known newer name or intent wins over the registry copy.
Evidence
tengu_fleetview_peers
New ListAgents tool for finding other sessions you can message #
Juicy
A tool that lists other Claude sessions you can message exists but stays off by default.
CLAUDE_CODE_HARBOR_KITE
Not switched on · Cross-Session Messaging
What
A tool that lists the other Claude Code sessions you can send a message to now exists and is registered, under the name ListAgents with the alias ListPeers. It is off unless the tengu_harbor_kite gate is on (source fallback false, real value from remote config) or the CLAUDE_CODE_HARBOR_KITE environment variable is set, and it never runs on Windows.
Details
It is read-only and safe to run concurrently, and returns a single formatted list of reachable agents.
Its channel and q inputs are both documented as "Not available in this build; leave unset."
Previously only the name existed as a constant; the implementation is new here.
The cache key for tool schemas now encodes whether the gate is on, so flipping it does not reuse a stale schema.
Evidence
list agents you can SendMessage to
SendMessage can address other sessions directly and reports delivery timing #
Juicy
Messages can be addressed to a specific session by socket or id, blocked unless peer messaging is enabled.
CLAUDE_CODE_HARBOR_KITE
Not switched on · Cross-Session Messaging
What
SendMessage can now target a peer by local socket (uds:) or by session id (bridge:), with failure advice that distinguishes a stale socket from a busy pipe, and it records a send_message_delivery event with the route taken and the time it took. Both address schemes are refused at validation time unless the peer feature is on, which needs tengu_harbor_kite or CLAUDE_CODE_HARBOR_KITE and a non-Windows machine.
Details
A socket that is gone (connection refused or missing) and a pipe that is busy produce different guidance.
The delivery event also carries how long the send waited when it was blocked.
With isolatePeerMachines on, sending to a cloud session now requires an explicit approval prompt.
Evidence
send_message_delivery
Untracked files can be uploaded to a cloud session's working directory #
Juicy
Cloud sessions can upload untracked files, but only behind an off-by-default gate and a project setting.
remoteFileModecontainer_sync
Not switched on · Cloud Sessions
What
Cloud sessions can now start from more than the git bundle. A new seeding step finds files that are untracked but not gitignored, hashes them and uploads them to the session, with hard ceilings of 192 files, 104857600 bytes (100 MB) and a 60 second deadline. It is off unless the tengu_violin_wood gate is on (it falls back to off, including on any error) and the project setting remoteFileMode is container_sync. Otherwise the session starts from the git bundle alone.
Details
The file list comes from git ls-files --others --exclude-standard -z at the git root, and dependency directories are filtered out: node_modules, venv, .venv, __pycache__, build, dist, target, vendor.
Symlinks, hard links, oversize files and files outside the git root are skipped.
Each file is uploaded to the session's synced_file endpoint along with a manifest listing what was sent.
You see a per-file progress line and a summary. When the feature is unavailable you get "Cloud file sync is unavailable for this session; starting from the git bundle alone".
Telemetry: tengu_dir_sync_inventory carries per-reason skip counts including skipped_too_large, skipped_symlink and skipped_over_budget; upload start/complete and tengu_dir_sync_seed_complete record the outcome.
Decodes a session access token and prints its claims, reading it from an argument, from $CLAUDE_CODE_SESSION_ACCESS_TOKEN, or from stdin up to 16 KiB. Signature verification against the published key set and the expiry/not-before check with 60 seconds of clock skew are both on by default.
Details
--no-verify skips the signature check, --no-check-expiry skips the time check, --header prints the token header instead of the claims.
--verify still parses but does nothing, kept so older wrapper scripts do not break.
The self-hosted runner now writes an executable .runner/code-sign script that invokes self-hosted-runner code-sign. It uses the binary named by CLAUDE_RUNNER_CLAUDE_BIN if set, otherwise a built-in path. Neither the script nor that environment variable existed before.
Evidence
exec "$BIN" self-hosted-runner code-sign "$@"
Inference geography can be pinned on a Managed Agents agent #
The Claude API docs describe pinning inference geography to us or global on an agent's model.
inference_geo
You'll notice · Claude API Skill
What
The skill docs add inference_geo, either "us" or "global", set inside an agent's model object rather than at the top level as on the Messages API. It is checked when the agent is saved, when a session is created, and on every turn, and it cannot change for the life of a session.
Details
Unlike effort, an inference_geo given in a per-session model override is applied.
Omitting it in an override clears the agent's pin.
Every model in a multiagent roster must use the same geography.
Evidence
Pinning inference geography
Workshop document writes counted separately in the activity summary #
Writes to workshop documents are counted separately from scratchpad writes in the activity summary.
You'll notice · Activity Summary
What
The collapsed activity summary now counts writes to workshop documents (files like .workshop.md or .workshop.html outside your working directory) on their own, with lines added and removed, rather than lumping them in with scratchpad writes.
Details
Counts are merged across collapsed groups.
A new pass rolls the counts back when the matching tool result comes back as an error, so failed edits no longer inflate the totals.
Evidence
workshopLinesRemoved
Attention budget: state and telemetry land, nothing can trigger it #
Juicy
A per-session attention budget with up and down shortcuts is built but completely unreachable.
Not switched on · Context Management
What
Groundwork for a per-session attention budget, one of "w25", "w50", "w100", "w200" or "unlimited" and defaulting to "unlimited". A cycle handler emits tengu_attention_budget_cycle, a new attachment type carries the budget into and out of the transcript, and two new key actions "chat:attentionUp" and "chat:attentionDown" exist. None of it is reachable: the chat key bindings and handler map both splice in an empty object where those entries would go.
Details
The attachment renders nothing and its generator returns an empty list, so the budget never reaches the model.
The cycle callback also returns early behind two condition checks that this build does not resolve.
A preserveLiveBudget option is passed into session restore and ignored by the function receiving it.
Evidence
tengu_attention_budget_cycle, chat:attentionUp
Forked sessions are told once that their twin is still running #
A forked session can be told once that its twin is still live and how to reach it.
CLAUDE_CODE_HARBOR_KITE
Not switched on · Cross-Session Messaging
What
When a session is detected as a copy of another that is still live, a one-time note is queued for the model explaining that history up to the fork point is shared, that the two have since diverged, and how to find and message the sibling. Requires the tengu_harbor_kite gate (fallback false) or CLAUDE_CODE_HARBOR_KITE, and is skipped on Windows.
Details
Suppresses itself if the note is already in the conversation or already queued.
Reported as fork_source_note, with a parent_gone reason when the original session cannot be resolved.
Evidence
This session began as a fork (copy) of another session that is still running
Git checkout machinery for self-hosted runners ships in full #
Juicy
Full git checkout machinery for self-hosted runners now ships, but you cannot reach it interactively.
CLAUDE_RUNNER_FETCH_DEPTH
Not switched on · Runners
What
The code that prepares a git working copy for runner and bring-your-own-compute sessions is now in the bundle; the previous release only declared its environment variable. It is not reachable from an interactive session. CLAUDE_RUNNER_FETCH_DEPTH tunes clone depth and accepts full, 0, or a positive integer, with an unparseable value logged and ignored in favour of the default.
Details
Access is validated with exponential backoff, and fetches retry under a cumulative wall-clock cap, degrading to HTTP/1.1 and low-speed timeouts on later attempts.
Git's progress output feeds a stall watchdog that sends SIGTERM then SIGKILL to a hung fetch.
Detects empty remotes and refs that have permanently failed, prefers a delta read-tree reset over reset --hard, and manages detached per-session worktrees.
Command lines, stderr and telemetry are redacted for URLs and credentials: Anthropic keys, GitHub/GitLab/Slack/Square tokens, JWTs, and Bearer and Basic auth headers.
Evidence
[byoc:git] Repository is empty, skipping checkout
Newer cloud session creation endpoint for review and plan sources #
Cloud sessions from review or plan sources can use a newer creation endpoint allowing --project grouping.
--project
Not switched on · Cloud Sessions
What
When a cloud session comes from an ultrareview or ultraplan source and the tengu_woven_harbor server flag is on, creation uses a newer endpoint, and only then are grouping sessions under a --project and dispatching to a Kindling agent accepted instead of refused. The flag falls back to off when the server sends no value, so by default the existing refusals still apply.
Evidence
tengu_woven_harbor
Server can push work hints over SSE so the runner picks up jobs faster #
Juicy
The runner can hold a live server connection and wake instantly on work, but it defaults off.
CCR_SHR_SSE_HINTS
Not switched on · Self-Hosted Runner
What
Set CCR_SHR_SSE_HINTS and the runner holds an event-stream connection to the server and wakes its poll loop as soon as a work_available event arrives, instead of waiting out the full poll interval. It defaults to off, and nothing else in the build turns it on.
Details
Wakes are jittered by up to 200ms to spread out a fleet reacting to the same event, and the wake source is reported back to the server.
The stream times out after 45 seconds without a read and reconnects with exponential backoff capped at 30 seconds.
Wakes are suppressed while the runner is already at capacity.
Evidence
CCR_SHR_SSE_HINTS
Directory sync apply starts with the working-file syncer #
Juicy
Startup also starts a directory sync apply step alongside the working-file syncer in normal local sessions.
Startup now also loads and starts directory sync apply for the current directory, in the same branch that starts the working-file syncer, and logs dir_sync_apply_import_failed if that load fails. The branch runs only when both CLAUDE_CODE_ENVIRONMENT_KIND and CLAUDE_CODE_DISABLE_WORKING_SYNC are unset, which is the normal local case.
Evidence
dir_sync_apply_import_failed
Plan-mode reentry records whether artifacts come first #
Re-entering plan mode records whether the setup calls for artifacts first.
Under the hood · Plan Mode
What
The record written when re-entering plan mode now notes when the configuration calls for artifacts first, alongside the plan file and doc paths it already stored.
Evidence
plan_mode_reentry
Two session-restore options are wired up but do nothing yet #
Session restore passes budget-preserving options that the receiving code currently ignores.
Not switched on · Session Restore
What
Restoring a session after a fork or a pre-clear rewind now passes an option to preserve the live budget, and session restore spreads in an attention budget. Neither takes effect: the receiving function ignores that parameter, and the attention budget variable is initialised to null and never assigned.
Evidence
preserveLiveBudget
Storage backend plumbed through several call sites but not switched on #
Several config and session lookups can accept a new storage backend, but none supply one yet.
Under the hood · Internals
What
Gateway model discovery, the computer-use lock, session-store loading of ~/.claude.json and user settings, the settings-key presence probe and session transcript lookup all gained an optional new storage backend parameter. When none is supplied, the existing filesystem behaviour runs unchanged, and the computer-use lock call sites in this build supply none.
Details
Uses namespaced keys such as a "gateway-models" cache key and a "computer-use-lock" state key.
The lock has distinct error paths: an already-exists result means the lock is held, an invalid-argument result is thrown.
Whether any given call site uses the new backend depends on what the caller passes, which varies across the build.
Evidence
computer-use lock v5 create failed
New memory_write tool for saving documents to a connected memory store #
Juicy
Claude can now save documents into a connected memory store, with secret scanning blocking risky writes.
Memory goes from read-only to read-write. Alongside memory_list and memory_read, Claude can now create or overwrite a whole document in a connected, writable memory store, and is prompted to check each of your replies for corrections and preferences worth keeping. Writes are refused for read-only stores, empty content, content over the byte cap, or anything a secret scan flags. Requires memory stores to be connected via CLAUDE_MEMORY_STORES, the allow_memory_sync permission, and CLAUDE_CODE_DISABLE_ORG_MEMORY unset.
Details
Prompt guidance: one topic per file, frontmatter on each document, and a per-store index document kept current.
Read-only stores refuse with "The memory store ... is read-only in this session; changes will not persist." Store resolution gained a write flag defaulting to false, which drives that refusal.
Secret-detection refusal notes the store "is shared across the organization's connected projects."
Written text is sanitised: control characters become U+FFFD, and line separators including U+2028 and U+2029 become plain newlines.
The whole feature also sits behind the remote-config flag tengu_haze_glass, whose fallback in this build is off, so the real value comes from server config.
In auto mode a write is routed to classifier review ("Saving a shared memory document requires classifier review."); in plan mode it asks.
Evidence
The memory store ${JZo(e)} is read-only in this session; changes will not persist., save a document to a connected project memory store
"pool" renamed to "environment" in runner flags, old names still work #
Juicy
Runner "pool" flags are renamed to "environment"; old names still work but warn.
--pool-secret-file and SELF_HOSTED_RUNNER_POOL_SECRET still work on both the runner and the orchestrator but now print a deprecation warning to stderr. Use --environment-secret-file or SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET instead; the error shown when no secret is supplied at all names only the new spellings.
Evidence
[runner:warn] --pool-secret-file is deprecated; use --environment-secret-file
ANTHROPIC_BEDROCK_REGION_PREFIX pins the Bedrock inference-profile region #
Juicy
Set ANTHROPIC_BEDROCK_REGION_PREFIX to pick which regional inference profile your Bedrock models resolve to.
ANTHROPIC_BEDROCK_REGION_PREFIX
Use it now · Bedrock
What
A new environment variable lets Bedrock users choose which regional inference-profile prefix models resolve to. Accepted values are us, eu, apac, jp, au and global. It is added to the environment passthrough sets used for sandboxed and spawned processes, so child processes inherit it.
Details
An older seven-entry region list including us-gov is kept separately, used for parsing Bedrock hostnames rather than for this variable.
Setting a prefix that cannot be confirmed, or models that resolve to a different prefix, produce warnings (see below).
A whole new claude self-hosted-runner command tree is available to anyone who types it.
claude self-hosted-runnerself-hosted-runner orchestratorself-hosted-runner setupself-hosted-runner doctorself-hosted-runner code-sign
Use it now · Self-Hosted Runner
What
The CLI now ships and dispatches a whole self-hosted-runner subcommand tree: orchestrator, setup, doctor, code-sign, decode-token, plus a bare runner mode. None of this code was in 2.1.223. No flag or remote gate sits in front of the dispatch, so anyone who types the command reaches it.
Details
Each subcommand lazily loads its own module, so startup for everyone else is unaffected.
Comes with its own usage text, an operator setup and doctor guide, and a /healthz probe on the orchestrator.
Entering the path fires a cli_self_hosted_runner_path telemetry event first, then dispatches.
Around 21k lines of runner code are new to the bundle; whether that reflects a new feature or a packaging change is not something the source alone settles.
Usage
claude self-hosted-runner doctor
claude self-hosted-runner orchestrator
Evidence
cli_self_hosted_runner_path, Usage: claude self-hosted-runner [options]
Create a cloud session straight from the command line with --environment and a prompt, optionally as JSON.
--environment
Use it now · Cloud Sessions
What
Running Claude Code non-interactively with --environment now creates a cloud session straight from the command line. It prints the title, session id, view URL and a resume hint, or with --output-format json emits an object with ok, session_id, url and pool_id. A prompt is required, as a positional argument or on stdin, and its absence is a hard error.
Details
previously this path needed an interactive terminal
new counters tengu_remote_create_session, tengu_remote_create_session_success and tengu_remote_create_session_error are tagged with entry_point: pool_headless
Usage
claude --environment my-pool -p "fix the failing test" --output-format json
Evidence
Error: non-interactive --environment requires a prompt (positional or stdin). Run from a TTY for an interactive cloud session.
Cross-session messages from a coordinator are now delivered by default #
Juicy
Task notifications from a coordinator session now arrive automatically unless you set crossSessionInbound to refuse or hold.
crossSessionInboundrefusehold
Use it now · Cross-Session Messaging
What
Messages arriving from another session are now sorted into three classes, and a new "coordinator" class (a task notification that carries a peer send-message) is delivered unless you explicitly set crossSessionInbound. Set it to refuse to reject them or hold to buffer them; with no setting at all, coordinator messages are accepted outright.
Details
The other two classes are peer messages, which follow the existing peer policy, and ungated messages.
hold puts coordinator messages into the same hold queue as peer messages; the queue drops its oldest entry when full.
Only an explicit crossSessionInbound value can hold or refuse this class, so an unset config means accept.
Evidence
Your "crossSessionInbound" setting is "hold".
New environment variable CLAUDE_CODE_MESSAGING_SOCKET#
Juicy
Point CLAUDE_CODE_MESSAGING_SOCKET at a socket path to enable session-to-session messaging and stream-json message replay.
CLAUDE_CODE_MESSAGING_SOCKETstream-json
Use it now · Cross-Session Messaging
What
Set CLAUDE_CODE_MESSAGING_SOCKET to a socket path and Claude Code records it with the session and, when the output format is stream-json, turns on replay of user messages without you asking for it. The variable is also carried through the set of CLAUDE_CODE_* variables Claude Code forwards to what it launches.
Details
The path is stored on the session registration record as messaging_socket_path.
Replay is only auto-enabled when it was not already on and the output format is stream-json; other output formats ignore the socket path for this purpose.
Neither the variable nor the session field existed in the previous build.
dialogExpiry accepts 60s, 5m, 10m or never for how long forwarded dialogs and held messages wait.
dialogExpiry
Use it now · Permissions
What
A new settings key controls how long a permission or question dialog forwarded to a remote client stays parked, and how long a held cross-session message waits for approval, before resolving to its safe no-action default. Accepts "60s", "5m", "10m" or "never", defaults to 5 minutes, and falls back to the default on an invalid value. Purely local prompts are unaffected.
Details
Resolution order: the environment variable CLAUDE_CODE_USER_DIALOG_TIMEOUT_MS, then dialogExpiry, then 300000 ms.
Read from trusted settings sources only, and sits next to the existing askUserQuestionTimeout key with the same enum.
claude --environment <environment_id> starts a cloud session on one of your own self-hosted environments (ids look like ccpool_...). An id that does not parse is rejected with an explicit error. Hidden companions --pool (a deprecated alias), --correlation-id, --ref and --on-branch also exist.
Details
--bg cannot be combined with --environment; the two are separate backends and you get a dedicated message pointing at direct invocation.
The --bg argument filter strips --environment and --pool, including their =value forms, before forwarding the remaining arguments.
Usage
claude -p "fix the flaky test" --environment ccpool_abc123
Evidence
Create a new cloud session that runs on the given self-hosted environment (ccpool_...).
sandbox.ignoreViolations can now be scoped to specific commands #
Juicy
You can silence sandbox violations for one command instead of all of them.
Use it now · Sandbox
What
Violation suppression is no longer all-or-nothing. A "*" key still applies to every command, and other keys are matched against the command text so you can silence violations for one command only.
Details
Recorded violations now carry the command, its encoded form and a timestamp.
The command text is recovered from a bounded cache of encoded commands, falling back to a decode that strips control characters.
Evidence
ignoreViolations
Bridge messages from peers can no longer skip the approval gate #
Text arriving over the editor bridge from peers can no longer run immediately without approval.
You'll notice · Editor Bridge
What
Incoming messages on the repl bridge were always classified as ungated because the classification was hardcoded, so any text arriving could be run immediately as a command. Messages are now classified from their content, platform, origin and receiver grouping, and the run-immediately shortcut is taken only when that classification really is ungated. Peer and coordinator messages go through the normal accept-or-hold policy.
Evidence
[bridge:repl] Ran immediate command without enqueue:
Clearer message when a tool needs approval and no prompt can be shown #
In headless runs, denials now tell the model approval is impossible and not to retry.
You'll notice · Permissions
What
In headless runs and async agents, a denial no longer just echoes the request back. The model is now told the action requires interactive approval, that permission prompts are not available in this session, and explicitly not to claim success or retry, with the original request appended.
Evidence
it requires interactive approval, and permission prompts are not available in this session
Quitting right after a turn no longer loses your last history entry.
You'll notice · Sessions
What
Both the periodic history flush and the flush on exit now wait for every pending write to finish before returning, so quitting immediately after a turn cannot drop the last entry.
Evidence
history_save_exit_flush_failed
Forked skill launches: session cap removed, duplicate race closed #
Juicy
The cap on forked-skill subagents per session is gone, and duplicate launches are blocked.
You'll notice · Subagents
What
The per-session cap on how many forked-skill subagents you can spawn is gone from this build entirely. The rule that only one agent per forked skill runs at a time is now checked both before and after the async write that reserves it, closing a window where two launches could both get through.
Evidence
forked_skill_live_duplicate
Invalid sandbox credential settings now fail closed instead of being ignored #
A malformed sandbox.credentials block now denies everything instead of quietly disabling protection.
sandbox.credentials
You'll notice · Sandbox
What
A malformed sandbox.credentials block used to be dropped entirely, leaving no credential protection in place. It now degrades to a deny-everything skeleton: all sigv4 signing modes deny, and implicit AWS credential pairing is suppressed rather than left open.
Details
Invalid awsPairs entries become non-functional suppressors built from the conventional AWS environment variable names, with a deterministic suffix so the result is stable across runs.
The sigv4 sub-keys streaming, presigned and sigv4a each degrade individually to "deny".
allowPlaintextInject degrades to an explicit false, so a lower-precedence settings file cannot turn it back on.
A single object where a list is expected is accepted as a one-element list with a warning.
A valid credentials block is salvaged out of an otherwise invalid sandbox value, with every other sandbox field ignored.
Evidence
The credentials block was salvaged from the invalid sandbox value and stays enforced; every other sandbox field was ignored.
Login errors for artifacts say which credential is in the way #
Artifact login errors now name which credential is blocking you and how to fix it.
You'll notice · Artifacts
What
The single "needs claude.ai login" message split into three: sign in to a console account, a remote session whose launching machine is not signed in, and a session running on a credential injected by its host environment that takes precedence and cannot be changed from inside the session.
Evidence
but this session authenticates with a credential injected by its host environment, which takes precedence and cannot be changed here
New post-commit review hook fires after git commits #
After a git commit completes, Claude is now nudged to review what it just committed.
You'll notice · Git Integration
What
Startup registers an internal hook that watches Bash tool output and injects a system message when it sees a completed git commit, so the model is prompted to review what was just committed.
Details
Registered as an internal PostToolUse callback hook with a timeout of 1, matching the Bash tool names.
Fires only when the command looks like a git commit and the output matches commit-shaped patterns such as create mode or N files changed.
Skipped in one mode check; registration sits in the same non-plugin-only startup branch as the session file-access hooks.
Evidence
registerUltrareviewPostCommitHook
Prompt history remembers pasted content and how you submitted #
Recalling an old prompt now restores its pasted attachments and remembers how you submitted it.
CLAUDE_CODE_SKIP_PROMPT_HISTORY
You'll notice · Prompt History
What
Recalling an earlier prompt from history now restores its pasted attachments, not just the visible text, and each entry records the submit mode it was sent with, such as bash mode. Setting CLAUDE_CODE_SKIP_PROMPT_HISTORY still turns recording off entirely.
Evidence
submitMode
Runner management tools require a first-party login and say so #
Runner management tools now require `claude login` on Anthropic's API; API keys are rejected.
claude loginANTHROPIC_BASE_URL
You'll notice · Self-Hosted Runners
What
The self-hosted runner tools now check up front that you are on Anthropic's own API and signed in with claude login. An API key is not accepted. Failures carry the HTTP status, and 401 or 403 responses append a hint pointing at claude login and ANTHROPIC_BASE_URL.
Details
The API base is ANTHROPIC_BASE_URL with trailing slashes stripped, falling back to the built-in Anthropic API URL.
These tools are only reachable from the setup and doctor wizards.
Evidence
Self-hosted runner management is only available on the first-party Anthropic API provider.
Sharing a transcript retries with smaller payloads instead of failing #
Sharing an oversized transcript now retries with trimmed versions instead of just failing.
You'll notice · Sessions
What
When a transcript is too large to share, Claude Code now tries progressively stripped versions rather than giving up. It walks a ladder of candidates (full, without the last API request, raw transcript lines only, metadata only), size-checks each before sending, and posts the first that fits.
Details
A successful reduced upload records "payload_stripped" so it's visible that content was trimmed.
Size failures and RangeError during serialisation fall through to the next variant; the precheck reports payload_too_large_precheck.
Blocked outcomes (essential-traffic-only mode, data residency, auth) still fail immediately with their own reason codes and are not retried.
You can spawn as many subagents as you want in one session; the per-session cap is gone.
You'll notice · Subagents
What
There is no longer any cap on how many subagents one session can spawn. The limit, its error message and the counter that tracked spawns have all been removed. Subagents launched from a forked skill still stop at the nesting depth limit and still refuse to start a duplicate of one that is already running.
Details
CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION still appears in a list of recognised environment variable names, but nothing in the build reads or enforces it.
`claude eval --interactive` now appears in help; `--interview` remains a hidden alias.
--interactive--interview
Use it now · Plugin Eval
What
The flag now appears in help output with text explaining that it runs the authoring interview, that this is already the default in a terminal, and that it needs an interactive terminal. --interview stays as a hidden alias.
Evidence
Run the authoring interview (already the default in a terminal); requires an interactive terminal
self-hosted-runner setup and doctor walk you through it in a scoped Claude session #
Juicy
setup and doctor relaunch Claude with a restricted toolset to walk you through runner install and diagnostics.
self-hosted-runner setupself-hosted-runner doctor
Use it now · Self-Hosted Runner
What
Two new subcommands re-launch Claude with a fixed system prompt and a restricted tool allowlist to guide an operator interactively. setup goes from creating an environment in the Admin UI to a live runner and writes ./runner-setup/CHEAT-SHEET.md. doctor works through nine diagnostic categories one step at a time and produces a redacted tarball you can attach to a support escalation.
Details
Both run with --permission-mode default and tools limited to Bash, Read, Write, Todo and Task plus the typed runner admin tools.
doctor additionally gets tools to list sessions and requeue a session; setup gets the tool that spawns a local runner.
Outcomes are recorded under telemetry names cli_self_hosted_setup and cli_self_hosted_doctor, including spawn_failed, child_signal and child_nonzero.
Evidence
Start the self-hosted runner doctor wizard. Greet me, then ask me to describe the symptom or pick from the 8 diagnostic categories. Work through it one step at a time.
Artifact kill switch now applies to more artifact paths #
Juicy
The artifact kill switch now actually disables two more paths that ignored it.
CLAUDE_CODE_DISABLE_ARTIFACTdisableArtifact
Use it now · Artifacts
What
CLAUDE_CODE_DISABLE_ARTIFACT, and the managed disableArtifact setting, are now checked first in two more artifact enablement paths. Previously those paths could still report artifacts as enabled with the kill switch set.
Evidence
CLAUDE_CODE_DISABLE_ARTIFACT
Feedback drafting tool queues a report you review before sending #
Claude can draft a feedback report locally that waits for you to review and send via /feedback.
/feedback
Use it now · Feedback
What
Claude can now prepare a draft feedback report about Claude Code locally. Nothing is sent automatically: the draft waits for you to review and submit it via /feedback, and the model is instructed not to announce it in the middle of a task. Scope covers both product bugs and the model's own behaviour, such as retracting a correct answer, stopping short of finishing, or spawning too many subagents.
Details
The prompt prescribes a fixed bullet structure for the draft, with a failure_mode field filled in only for reports about model behaviour.
Whether this tool is exposed in your session is not something the bundle itself decides.
Evidence
Queue a draft feedback report about Claude Code
Local messaging socket: where it lives, who can read it, and refusing to steal a live one #
Juicy
The messaging socket lives under XDG_RUNTIME_DIR with locked-down permissions and refuses to hijack a live one.
The local socket used for session-to-session messaging binds under $XDG_RUNTIME_DIR/cc-socks/<pid>.sock, with the directory created 0700 and the socket 0600, and its path exported as CLAUDE_CODE_MESSAGING_SOCKET. If you pass --messaging-socket-path pointing at a socket something is already listening on, startup refuses rather than hijacking it.
Details
Falls back to a /tmp path, or $PREFIX/tmp under Termux, when the primary path would exceed the 103 byte limit on socket paths.
Non-local paths are refused outright.
Input is line-delimited JSON; any line over 1 MiB is dropped.
Evidence
--messaging-socket-path points to a live socket:
Plugins can be installed from a zip archive over HTTPS #
Install plugins from an HTTPS zip, with a sha256 pin checked on every download.
archivesha256
Use it now · Plugins
What
Marketplaces can now offer a plugin as a downloadable zip. A new source kind archive takes an HTTPS zip URL plus an optional sha256 pin; when the pin is set every download is checked against it and the install is refused on mismatch, and the digest also stands in as the plugin's version when none is declared.
Details
Downloads are hardened against server-side request forgery: HTTPS only, loopback, link-local and cloud-metadata hosts refused, at most 5 redirects, a 256 MB size cap, a 120 second timeout, and a fixed User-Agent of Claude-Code-Plugin-Manager.
Headers configured on the enclosing marketplace url-source are only reused when the origin matches.
Installed plugin records gained a contentSha256 field, and the temp directory used during install has an "archive" naming case.
Evidence
plugin archive URL policy rejected
Prometheus metrics on the runner and orchestrator health port #
Juicy
The runner and orchestrator serve Prometheus metrics at /metrics on the health port.
--health-port/metrics/healthz
Use it now · Self-Hosted Runner
What
The health listener (--health-port, default 8080, 0 disables) now serves Prometheus metrics at /metrics alongside /healthz. The runner exports claude_code_self_hosted_runner_: capacity, active and initializing sessions, per-platform session counts, init duration, poll errors and per-session idle time. The orchestrator exports claude_code_self_hosted_orchestrator_: queue depth, spawn-hook outcomes, spawn-hook and queue-wait histograms, clock skew and connector state.
Details
Poll-error series are pre-seeded for all five kinds (transport, timeout, 5xx, 429, 4xx) so rate() queries work from the moment the process starts rather than from the first error.
Whether the listener bound successfully is reported through telemetry named self_hosted_healthz_listen.
Evidence
text/plain; version=0.0.4; charset=utf-8
Runner can refuse repo-committed settings that reach outside the workspace #
Juicy
The runner can warn about or block repo-committed settings that grant access outside the workspace.
Before starting a session, the runner inspects the checked-out repo's .claude/settings.json and settings.local.json for grants that would escape the session workspace and reports or blocks them. --confine-repo-settings (or SELF_HOSTED_RUNNER_CONFINE_REPO_SETTINGS) picks enforce, warn or off; the CLI defaults to warn, which logs what it would have refused and starts the session anyway.
Details
What it looks at: permissions.allow paths, sandbox filesystem allowRead/allowWrite, additionalDirectories, bare Edit and Write rules, env set by the repo, and any repo override of the operator's sandbox or hooks posture.
Symlinks and .. are resolved, and a path that cannot be resolved is treated as a violation rather than allowed.
An invalid value for the flag fails at startup rather than silently falling back.
Outcomes are reported through telemetry named self_hosted_confine, with separate reasons for warn and enforce.
The runner gains a set of flags for managing how long it lives. --retire-at (or SELF_HOSTED_RUNNER_RETIRE_AT, an absolute Unix timestamp in seconds) releases active sessions, stops accepting new work and exits 0. --release-idle-session-min and --startup-timeout-min (default 15) are watchdogs, --kill-session-after-min waits for the current turn to finish first, and --drain-wait-sec sets drain time.
Details
--drain-wait-bg-tasks-sec is a deprecated alias for --drain-wait-sec.
--push-outcome-on-release pushes the session's tracked outcome branches to the source remote when a session ends without completing, and fetches them back if that session later resumes on a fresh worker.
Retirement releases sessions through the same path as idle release.
Release outcomes are reported through telemetry named self_hosted_release_session, with reasons including released_false_backstop.
Checkout hooks, post-session hooks and the remote runner environment now export CLAUDE_RUNNER_SESSION_UUID and CLAUDE_CODE_REMOTE_SESSION_UUID, so your scripts can key on the session. Neither existed in 2.1.223.
Details
The value is derived from the session id by decoding its trailing segment into a canonical UUID; if that does not decode, the variables are left unset.
Only set on the self-hosted runner and remote session launch paths.
Evidence
CLAUDE_RUNNER_SESSION_UUID
Tunnel from the orchestrator to a private GitHub Enterprise host #
Juicy
Pass --scm-connector-host to tunnel Anthropic requests into a GitHub Enterprise server only your network can reach.
Passing --scm-connector-host opens a persistent WebSocket to Anthropic and proxies inbound HTTP requests to a GitHub Enterprise server that is only reachable from inside your network. --scm-connector-id is required alongside it, --scm-connector-provider defaults to ghe, and --scm-connector-ca-file supplies a custom CA. The connector is entirely off unless you pass the host flag.
Details
Requests are checked against a method allowlist, hop-by-hop headers are stripped, and paths that would escape the configured origin are refused.
Frames asking to open a raw socket or a PTY (wsOpen, ptyOpen) are rejected.
Close code 4003 means another orchestrator already holds this connector; it retries after 30 seconds.
--scm-connector-host-rewrite is documented as being for end-to-end testing only.
Evidence
/v1/code/scm-connectors/{provider}/{id}/tunnel
Managed Agents sessions can carry a hard dollar spend cap #
The bundled Claude API docs now describe a hard dollar spend cap that pauses a session idle.
budgetmax_list_cost
You'll notice · Claude API Skill
What
The bundled claude-api skill, the documentation Claude Code consults when you ask it to write code against the Claude API, now documents a session budget. It is set at create time only, in minor units and USD only, for example {"type": "limit", "max_list_cost": {"amount": "2500", "currency": "USD"}}. A session that reaches the cap pauses idle instead of terminating, and only resumes if the budget is raised or removed.
Details
A paused session accepts only settle events: user.tool_confirmation, user.tool_result, user.custom_tool_result, user.interrupt.
Removing a budget is one-way; it cannot be added back to that session.
Raising the cap must exceed what the session already spent, otherwise the API rejects it.
Claude Code will generate and explain this shape whenever the skill is in use.
Evidence
budget.max_list_cost must be greater than the session's consumed list cost
Turn summary now counts workshop page edits and hook time #
Turn summaries now count workshop page edits and how long PreToolUse hooks took.
You'll notice · Activity Summary
What
The activity summary after a turn reports workshop writes as their own line, "workshop making/made N page edit(s)" with a diff stat of lines added and removed. If nothing else happened but hooks ran, it adds a line counting how many PreToolUse hooks fired and how long they took in total.
Details
Workshop write counts and line deltas are tracked per tool call.
Claude can auto-generate an index of your memory files and feed it in as a source.
CLAUDE_CODE_REMOTE
Not switched on · Memory
What
Claude Code can build a listing of the memory files under a directory and feed it in as an extra memory source, under a virtual path named <auto-memory-index> rather than a real file. The content begins with a generated line naming the directory and noting that the paths below it are relative. It is off unless a server value enables tengu_stone_shell, whose built-in fallback is false, and it is skipped entirely when CLAUDE_CODE_REMOTE is set.
Evidence
<auto-memory-index>
Artifact tool gains document-store read and write #
Artifacts get document read and write operations with separate remembered consent for each.
Not switched on · Artifacts
What
New read and write operations address documents by page address, collection path and document id, with errors for a bad address, an over-long composed path and a missing document id. Consent is remembered separately for reads and writes, and again separately for approvals given by a person in plan mode.
Details
The stored consent covers write approval, human write approval, and per-address lists for read consent and human read consent.
Whether these operations are offered unconditionally or behind a flag is decided by the tool's schema, which is not resolved in this build.
Effort levels can be labelled with relative cost like ~2x, hidden behind an off gate.
Not switched on · Thinking Effort
What
The effort level slider can label each level with an estimated cost multiplier against the model's default effort, shown as ~2x or ~0.25x, with a distinct note on the default level. It is behind the tengu_marbled_teal gate, which falls back to off, and it also needs per-model cost index data to be present.
Evidence
the estimated cost of
Files received from a peer session are verified before use #
Files another session sends you are size- and hash-checked and confined to a staging folder before use.
Not switched on · Cross-Session Messaging
What
When another session sends file attachments, they are now checked before Claude sees them: the attachment list is schema-parsed and capped in count, each path must sit inside the transfer staging directory, must be a regular file, and must match the declared size and hash. Verified files are copied into an uploads directory with owner-only permissions. This runs only with peer messaging enabled.
Details
A file that fails any check is logged with a [peer-file-transfer] prefix and surfaces as a notice, rather than being attached silently.
Evidence
transfer path is outside the file-transfer spool
Memory writes will require the version token from your last read #
Memory writes will need the version token from your last read, forcing a read before overwriting.
Not switched on · Memory
What
A build-gated change to the memory tools makes every write carry if_version: either the 12-character version token returned by the most recent read or write of that path, or the literal word new for a document that does not exist yet. The model therefore has to read a document before overwriting it. Reads now return the token; listing does not. Off in this build unless the tengu_haze_glass gate is on, which defaults to false.
Details
A stale token, or new against a path that already exists, rejects the write and returns the current content (when it fits within the read size cap) plus its current version, so the model can merge and retry.
Rejections are recorded as tengu_memory_tools_version_conflict with the reason.
Evidence
Every ${lS} needs if_version. Pass the literal word new for a document that does not yet exist.
Artifact database access asks permission first, with reads and writes scoped differently.
CLAUDE_CODE_ARTIFACT_DB
Not switched on · Artifacts
What
The new artifact database actions ask before first use, and the prompt spells out how far approval reaches: approving a write covers database writes to any artifact for the rest of the session, approving a read covers that one artifact for the rest of the conversation. Writes persist and are visible to everyone who can open the artifact. The actions are gated behind CLAUDE_CODE_ARTIFACT_DB and the tengu_umber_lattice gate.
Details
In plan mode the request is always routed to the user rather than the automatic permission classifier.
Evidence
Claude wants to write to this artifact's database \u2014 writes persist and are visible to everyone who can open the artifact; approving covers database writes to any artifact for the rest of this session.
Untracked files can be seeded into a cloud session #
Juicy
Teleporting to a cloud session can upload your untracked files so the remote starts with them.
remoteFileModecontainer_sync
Not switched on · Cloud Sessions
What
Teleporting to a cloud session can now inventory your git root and upload untracked working-tree files so the remote session starts with them, reporting progress as it goes. It needs both the tengu_violin_wood gate, whose fallback is off, and the per-project setting remoteFileMode set to container_sync. If the upload times out or is unavailable, teleport falls back to sending the git bundle alone.
Details
Uploaded files go under a .ccr-seed prefix accompanied by manifest.json and ready.json.
New telemetry events: tengu_dir_sync_inventory and ccr_dir_sync_seed.
Evidence
Cloud file sync timed out after
Teammate messages carry the sender's permission mode #
Messages between agents now carry the sender's permission mode, preserved across relays.
Under the hood · Agents
What
Messages passed between agents now include the sender's permission mode in the message header, drawn from a fixed two-value list, and the parser preserves it when a message is relayed through further hops.
Evidence
from-mode=
Eval-authoring guidance had two wrong field names #
Plugin eval guidance now names the real fields, suite.plugins and costUsd.
suite.pluginscostUsdaggregate-result.json
Use it now · Plugins
What
The guidance for writing plugin evals now names the fields that actually exist: suite.plugins for checking the plugin loaded, and costUsd for the cost figure in aggregate-result.json. It previously said plugins and cost_usd.
Evidence
The pilot's top-level \costUsd\ in \aggregate-result.json\``
Two env vars change how runner git fetches handle retries and stalled delta resolution.
CLAUDE_RUNNER_FAIL_FAST_FETCHCCR_DELTA_RESET
Use it now · Self-Hosted Runner
What
On the runner and bring-your-own-cloud execution path, CLAUDE_RUNNER_FAIL_FAST_FETCH makes a git fetch fail immediately instead of retrying, and CCR_DELTA_RESET makes the fetch record HEAD beforehand and treat the "Resolving deltas" 100% progress line as a point that resets the stall timer. Both are read as plain booleans from the environment.
Evidence
CLAUDE_RUNNER_FAIL_FAST_FETCH
Tighter limits on the first publish of a review page #
First publish of a review page now caps followups, unchanged items and text lengths.
You'll notice · Review Pages
What
Publishing a review page for the first time now rejects more than 3 unchanged-item entries, more than 3 followups, a bottom line longer than 600 characters, or any concern body longer than 300 characters. Pages already published under the older, looser limits can still be republished as they are.
Evidence
bottom_line over the first-publish cap
Artifact database access must be declared when publishing #
An artifact must declare database capability when published, or database calls fail and ask you to republish.
CLAUDE_CODE_ARTIFACT_DB
Not switched on · Artifacts
What
Among the new database errors for artifacts is one for publishing: if the artifact's currently published version does not declare the db capability, the call fails and tells you to republish with it declared. Database access is opt-in per artifact rather than automatically available. Gated by CLAUDE_CODE_ARTIFACT_DB and the tengu_umber_lattice flag.
Evidence
this artifact's current published version does not declare the database capability \u2014 republish it with the db capability declared, then retry
Cloud sessions can be created through a newer request shape #
Cloud session creation can use a newer request shape for review and plan sources.
--project
Not switched on · Cloud Sessions
What
Creating a cloud session can now build a different request body for the newer session-create endpoint, carrying worker, source, outcome, seed bundle and branch-reuse fields in place of the older single session-context blob. It applies only when an account-level check passes and the session comes from ultrareview or ultraplan; nothing in this build sets that check, so what accounts get is decided elsewhere. --project and agent dispatch still refuse outright on accounts still using the old endpoint.
Evidence
v1alpha2
Forked sessions can be told their original is still running #
A forked session can be told its original is still running and how to message it.
CLAUDE_CODE_HARBOR_KITE
Not switched on · Cross-Session Messaging
What
A new note injected into the conversation tells the model that this session is a copy of another session that is still running, when the copy was made, and how to find and message the original. It is off by default: the path is disabled on Windows and otherwise falls back to tengu_harbor_kite being false, so it only runs if remote config or CLAUDE_CODE_HARBOR_KITE turns it on.
Details
The note is wrapped in <fork-source> tags in the prompt.
Queued and pending prompts are checked first so the note is not added twice.
Logs fork_source_note, with a parent_gone outcome when the original session can no longer be found.
Evidence
This session began as a fork (copy) of another session that is still running:
Memory index built by scanning files rather than read from disk #
A memory index can be generated by scanning recent files rather than read from a stored index.
Not switched on · Memory
What
New code builds a memory index at load time by walking the memory directory, taking the most recently modified files and reading each one's name and description header fields, falling back to the filename and first heading. The result is rendered as markdown and truncated at a byte budget. It runs only for stores that ask for a generated index; stores without that keep using an index file on disk.
Details
The walk skips dotfiles and is capped on depth, number of files and per-file size.
Emits tengu_memdir_index_assembled with scan counts, how many files needed the filename fallback, whether output was truncated, and whether a disk index was superseded.
The consolidation prompt has a matching variant that drops the "update the index file" step in favour of keeping each file's header fields accurate.
Evidence
tengu_memdir_index_assembled
PR review artifact publishing, present but hard off #
Juicy
A full pull request review page with diagrams and comparisons is built but never offered.
Not switched on · Artifacts
What
The Artifact tool can expose a pr_review option that publishes a composed pull request review page from a JSON payload you author, rendered through a bundled template. It is backed by a large new review format covering diagrams, flows, before-and-after comparisons, concerns with visuals, and followups. The helper that decides whether the option is offered returns false unconditionally in this build, so the option never appears.
Evidence
Publish a composed PR review page: file_path names the structured payload .json the artifact-pr-review skill had you author, and the page is built from the bundled review template at publish time.
Assistant text is scanned for harness-shaped tags #
Claude's own replies are scanned for text imitating internal control markup, and matches counted only.
Under the hood · Permissions
What
Main-session assistant messages are now checked for text that looks like Claude Code's own internal control markup, including system reminders, harness envelopes and token-count, session-context, wake and role-turn shaped lines. Nothing is rewritten; the matches are only counted and reported.
Details
Runs for main-session, non-error assistant messages only, with no flag involved.
Bundled models carry per-effort cost multipliers, though nothing in this build reads them.
Under the hood · Model Catalog
What
Four entries in the bundled model list now carry a cost multiplier per effort level, for example low: 0.47, medium: 0.74, high: 1, xhigh: 2.41, max: 5.59 on one and a gentler xhigh: 1.6, max: 1.7 on others, alongside the existing default effort of high. The remote config schema was extended to match, each level an optional positive number, so a server can override them. No code in this build reads the values back.
Details
The data is present in every build, which points at cost-aware effort selection landing later.
Evidence
effort_cost_index
Startup remote-control setting now tracks where its value came from #
Remote control startup now records where its on/off value came from, but nothing reads that yet.
remoteControlAtStartup
Under the hood · Remote Control
What
Resolving whether remote control is on at startup now returns the origin of the value as well: managed policy, a command-line flag, user settings, an older global config value, a project or local setting turning it off, or nothing set. The warning that repo-scoped settings are ignored is unchanged. Nothing in the build was found reading the origin.
A session switch for wizard operator tools exists, defaults off, and can never be turned back off.
Not switched on · Tools
What
A session flag for "wizard operator tools" ships defaulting to off, and its setter refuses to be passed false outside tests. Once something enables it during a session, nothing in normal operation turns it back off. No code in this build turns it on.
Evidence
setWizardOperatorToolsEnabled(false) is test-only: the wizard latch is one-way in production
Everything else · 243
Smaller changes and internals, grouped as the pipeline found them. Nothing is dropped, it is only further down.
New Features
24 items
Visible failure state when sharing a transcript doesn't go through #
A failed transcript share now says so in the dialog and points you at /feedback.
A failed transcript share now shows in the dialog rather than only in telemetry. You get the line "Couldn't share the transcript." and, unless DISABLE_FEEDBACK_COMMAND or DISABLE_BUG_COMMAND is set, a dimmed hint "You can share details with /feedback instead." The dialog auto-closes after the usual delay.
Details
Previously a failure produced only a transcript_share_failed telemetry event and no on-screen change.
Implemented as a new share_failed UI state with its own render branch.
Evidence
You can share details with /feedback instead., Couldn't share the transcript.
Cowork warns when your default environment isn't in the org's list #
You get a logged warning if your default self-hosted environment isn't in your org's list.
You'll notice · Cloud Sessions
What
If you have a default self-hosted environment configured and start a session without picking one explicitly, Claude Code fetches your org's environment list in the background and logs a warning if the configured id isn't there. The id is still sent, because the server validates it when the session is created.
Details
Warning text ends with "is not in the org's environment list".
A pool fetch that fails outright is logged separately rather than blocking the session.
Evidence
is not in the org's environment list
Remote-control autostart decision is resolved in one place #
One resolver now decides whether Remote Control starts and in which mode, weighing flags, settings and env vars.
Whether the remote-control bridge starts, and whether it runs full or outbound-only, is now decided by a single resolver that weighs the CLAUDE_CODE_REMOTE environment variable, the --remote-control flag, the explicit setting, a built-in default, and the CLAUDE_BRIDGE_REATTACH_SESSION and CLAUDE_BRIDGE_REATTACH_OUTBOUND_ONLY variables.
Details
The outcome is reported as tengu_rc_autostart_resolved, carrying the explicit setting and where it came from, the default and its source, and the mode that won.
Evidence
tengu_rc_autostart_resolved
Two warnings when a Bedrock region prefix cannot be confirmed #
Bedrock now warns when it can't confirm a region prefix, or when models resolve elsewhere.
ANTHROPIC_BEDROCK_REGION_PREFIX
You'll notice · Bedrock
What
If inference-profile discovery is unavailable, setting a region prefix now warns that it is being applied without an availability check. If discovery works but some models resolve to a different region, a second warning names how many and states that the prefix is a preference, not a residency guarantee.
Details
Warning text is assembled at runtime around the fixed fragment "is being applied without an availability check (inference-profile discovery is unavailable)."
Both warnings only appear when ANTHROPIC_BEDROCK_REGION_PREFIX is set.
The session details list gains a "Peer address" row showing the messaging socket as uds:<path>. It appears only when cross-session messaging is enabled and CLAUDE_CODE_MESSAGING_SOCKET is set; this slot was previously always empty.
Details
Cross-session messaging is gated by tengu_harbor_kite or the CLAUDE_CODE_HARBOR_KITE environment variable.
Evidence
Peer address
Invoking the prototype skill directly starts prototype mode #
Invoking the prototype skill yourself now actually starts prototype mode.
You'll notice · Elsewhere
What
Calling the prototype skill yourself now marks prototype mode as started, as invoking it any other way already did. This does not happen when the skill is only being preloaded or when the model scheduled the invocation itself.
Evidence
prototype_started
Remote Control errors are typed as auth or terminal #
Remote Control failures are labelled auth or terminal, and auth ones point you at /login.
/login
You'll notice · Remote Control
What
Bridge failures now record whether they were an auth problem or a terminal one, and auth failures show the /login hint. The token-refresh failure message changed from "re-authenticate, then re-enable Remote Control" to text ending "run /login to re-authenticate".
Details
App state gains an error-kind field alongside the existing error, set to "auth" or the default "terminal", and cleared wherever the error is cleared.
Evidence
run /login to re-authenticate
MCP OAuth failures name the specific issuer mismatch #
MCP OAuth failures now tell you it was an issuer mismatch instead of a generic error.
You'll notice · MCP
What
When an MCP server's OAuth flow fails because the server echoed back the wrong issuer, the failure is now reported with a specific reason rather than a generic one, making misconfigured servers easier to identify.
Details
Three new failure reasons: issuer_echo_denied, issuer_echo_mismatch and issuer_response_mismatch, each raised from its own error class and checked ahead of the existing reasons.
One authorization-server metadata discovery path now skips the library's built-in issuer check and validates the issuer itself afterwards, throwing the existing "AS metadata discovery failed: issuer mismatch" error.
MCP connect telemetry gains a sibling-probe field, computed only in auto negotiation mode, on both the success event and tengu_mcp_server_connection_failed.
Evidence
issuer_echo_denied
Sandboxed commands are tagged with an attribution id #
Sandboxed commands now carry an id into the sandbox config so activity traces back to its command.
Under the hood · Sandbox
What
Commands run in the sandbox now pass an identifier through to the sandbox wrapper, where it appears as a command id in the macOS and Linux sandbox configuration, so sandbox activity can be traced back to the command that caused it.
Details
A new sandbox attribution id option is threaded through the bash and PowerShell exec path into both sandbox wrapper entry points.
The macOS sandbox log watcher was reworked to decode its command marker through a caller-supplied resolver, defaulting to identity, instead of a pre-built ignore map.
Evidence
sandboxAttributionId
Cloud seeding tells you when there are too many untracked files #
If you have too many untracked files, cloud seeding refuses and tells you which budget you blew.
.gitignore
You'll notice · Cloud Sessions
What
When the untracked files at your git root exceed the seeding budget, the upload is refused and you are told why instead of quietly starting from the git bundle alone. There are two messages: one counting files against the 192-file budget, one counting bytes against the 100 MB transfer budget, and the byte one suggests adding a .gitignore entry.
Details
Same gating as the seeding feature itself: the tengu_violin_wood gate plus remoteFileMode set to container_sync.
The fallback is bundle-only seeding, and the existing seed telemetry records a too_many_untracked outcome.
Evidence
untracked files exceed the v0 seed budget of, of untracked files exceed the v0 seed transfer budget of
Skills can be loaded from a mounted GitHub repository #
Skills can load from a mounted repo's .claude/skills, in cloud sandboxes only.
.claude/skills
You'll notice · Skills
What
A new docs section describes loading skills from a mounted repository's root .claude/skills directory. Skills are discovered once per session from the code as it stood when the session started, and this works in cloud sandboxes only, not self-hosted.
Details
Carries an explicit warning that repository skills are agent instructions running inside your trust boundary, so anyone who can commit to the repo can change agent behaviour.
Evidence
Skills from a GitHub repository
Local runner spawn writes into ./runner-setup and checks 127.0.0.1:8080 #
The setup wizard spawns a detached runner into ./runner-setup and warns it outlives your session.
The setup wizard's spawn tool starts a detached self-hosted runner process, defaulting its working directory to ./runner-setup/workspace, its log to ./runner-setup/runner.log and its pid file to ./runner-setup/runner.pid. Companion tools read http://127.0.0.1:<port>/healthz and /metrics on port 8080 by default (0 disables the listener). The permission prompt warns that the runner will keep running after this session ends.
Details
The spawn passes --environment-secret-file, --capacity, --base-dir, --api-url, --health-port and --log-file.
The metrics tool reads only gauges prefixed claude_code_self_hosted_runner_, skipping histogram buckets, per-session idle seconds and poll error totals.
Tail-log reads the trailing bytes of the log and redacts secrets before showing them.
These tools are only available inside the setup and doctor wizards.
Evidence
claude_code_self_hosted_runner_
Invalid extraKnownMarketplaces entries are dropped with a warning #
Bad marketplace entries in your settings are now removed and reported as warnings instead of silently accepted.
extraKnownMarketplaces
You'll notice · Plugins
What
Bad marketplace entries in your settings are now reported instead of quietly accepted. A non-object extraKnownMarketplaces value is deleted outright, and each entry is validated, with a mismatch between the map key and the marketplace name it declares called out by name. Offending entries are removed and surfaced as warnings against the settings file and path.
Details
The warning text is "Invalid marketplace entry was ignored: " followed by the reason.
Entries with an unrecognised source kind, or that carry plugins, are skipped rather than dropped.
Evidence
Invalid marketplace entry was ignored:
Org-anchored consent for remote managed settings #
Approvals for risky org-managed settings are now remembered per organization, so you get re-prompted far less.
You'll notice · Managed Settings
What
When your organization ships managed settings, consent to the dangerous ones can now be recorded against the org rather than only against the local payload you saw. Consent is stored in a new remote-settings-consent.json, capped at 20 organizations and rewritten at most once a day per org, and you are not re-prompted while the org record's hash of the dangerous settings still matches.
Details
Requests now carry the organization and account ids so the response can identify which org the consent belongs to.
Without an org record, the previous behaviour applies: the locally consented payload is compared directly.
Consent is not recorded if the signed-in identity changed part-way through the fetch.
A login or logout during a fetch discards that fetch's result, reported as reset_during_fetch.
Evidence
Remote settings: Cache was reset (login/logout) during this fetch; discarding its result, remote-settings-consent.json
Sandbox violations record the command that caused the blocked request #
Blocked network requests are now recorded with the command that made them, not just dropped.
You'll notice · Sandbox
What
A network request blocked by the sandbox is now recorded as a violation with its method, sanitized URL, reason and the command that made it, instead of only being dropped. Filesystem violations on Linux and macOS also gained command text.
Details
Applies only while the sandbox proxy and platform monitors are running.
Evidence
deny http-request
Sandbox network denials name the command that caused them #
Blocked outbound connections now name the shell command responsible.
You'll notice · Sandbox
What
When the sandbox blocks an outbound connection, the violation record now includes the shell command responsible, so you can tell which command tried to reach the network rather than only seeing that something did.
Details
The proxy's auth check returns a result object carrying an encoded command instead of a plain yes/no.
The proxy Basic credential username may now be srt or srt.<suffix>; the SOCKS path previously required an exact srt match. The suffix decodes to the command identity, set from SRT_ENCODED_CMD when a command id is supplied.
The decoded command is passed to the allowlist filter and to the denial callback, and violation records carry both the encoded form and a resolved command string.
Requests failing the auth check still get the existing 407 and 403 responses.
Evidence
SRT_ENCODED_CMD, encodedCommand
Published plans are rendered from a plan template and tracked #
Published plans now use their own page template and get their own tracked addresses.
You'll notice · Artifacts
What
Publishing a plan now requests a plan template from the HTML publisher and records the resulting page under a plan storage namespace, in the same registry used for prototypes. Existing plan pages are enumerated so a new plan does not reuse an existing address.
Evidence
namespace: "plan"
Remote Control tells you when a credential expired instead of just dropping #
An expired Remote Control credential now closes with a clear message telling you to run /login.
/login
You'll notice · Remote Control
What
Remote Control now separates auth failures from other disconnects. When the worker token expires or is rejected, the session closes with a dedicated code and the message points you at /login, instead of the previous generic re-authenticate wording.
Details
New close code 4094, "worker credential expired or rejected (code 4094)", used for token_expired and auth_exhausted.
epoch_conflict, epoch_stale and session_not_found keep close code 4090 and recover through the poll loop.
The cause-based mapping applies only when the transport is built with causeTypedCloseCodes; both v2 bridge call sites pass it as true, so it is live.
The 404-exhaustion path now names its cause explicitly as session_not_found.
Evidence
worker credential expired or rejected (code 4094)
Workshop file writes are counted in the turn summary #
Workshop file writes are counted separately per turn and shown in the status display.
You'll notice · Artifacts
What
Writes to workshop files are now tracked separately, with a per-turn count of writes and lines added and removed, and the status display shows the write count.
Details
Tool classification gains a workshop-write flag; the turn summary accumulates write count plus lines added and removed.
Edits are keyed by tool use id so a rewind subtracts exactly the right amounts, and counts merge when summaries are combined.
The status component reads all three values and includes the write count when deciding whether there is anything to display.
Evidence
isWorkshopWrite
Peer messages carry the sender's permission mode #
Messages between sessions now carry whether the sender was bypassing permissions or prompting.
Under the hood · Cross-Session Messaging
What
A message sent between sessions now includes whether the sender was running in bypass or prompting permission mode, so the receiving side can see how permissive the sender was.
Details
Rendered in the message envelope as from-mode="...", limited to the two values bypass and prompting.
Parsed back out on receipt and preserved when a message is re-encoded.
Both the local socket peer client and the bridge sender accept the mode as their final argument.
Evidence
["bypass", "prompting"]
Prototype runs and publishes now report their own telemetry #
Prototype runs and publishes now emit their own telemetry events with the artifact slug.
Under the hood · Elsewhere
What
Claude Code emits two new events around prototype artifacts: one when a prototype run starts, and one when a prototype is published, carrying the artifact's slug and whether it was the first publish.
Details
The publish event records artifact_slug and is_first_publish.
Neither event name exists in the previous build.
The functions that emit these events are new; which artifact flow calls them was not traced, so it is not clear from the build itself which user actions trigger them.
Evidence
prototype_publish
Plugin eval can validate and report its own JSON output #
Plugin eval JSON output is validated before printing, and suppressed with a stderr warning if invalid.
claude plugin eval--json
You'll notice · Plugin Eval
What
claude plugin eval --json now checks its result against the expected shape before printing. If validation fails the JSON is not printed at all and a warning goes to stderr instead; if it merely differs from the expected shape a warning is printed and the result is still emitted.
Details
On drift, a result_schema_drift counter fires and the result is still printed.
On outright validation failure, output is withheld entirely and stderr carries the explanation.
New outcome telemetry records pass and fail counts, how many cases hit run errors, and separates exits caused by a cost ceiling from exits caused by a case that failed to load.
Evidence
warning: --json result withheld because it failed schema validation
Messages relayed between your own sessions are now labelled as such #
Messages relayed from your other sessions are now tagged as peer sends rather than looking like scheduled triggers.
Under the hood · Cross-Session Messaging
What
A message delivered to one session from another of your sessions, sent by the model through a coordinator SendMessage, now carries subkind: "peer-send-message" on its origin instead of being indistinguishable from a scheduled trigger. Anything reading origin.subkind should expect this additional value alongside scheduled-trigger.
Details
These deliveries keep the same prompt authority as task notifications but are now distinguishable on the wire.
The classifier stamps the new value when an inbound message arrives over the coordinator path, so the receive-side crossSessionInbound setting can apply to it.
Evidence
so the receive-side crossSessionInbound setting can apply to it
Consent to dangerous remote settings is remembered per organization #
Approving risky remote settings is now saved to a file so you aren't asked again.
You'll notice · Managed Settings
What
When you approve remote settings that can run shell commands, set environment variables, install hooks or write CLAUDE.md, that approval is now written to a remote-settings-consent.json file so you are not asked again for the same content.
Details
Records are keyed by organization uuid and store the account uuid, a hash of just the dangerous portion of the settings, and a timestamp. If that portion changes, the hash no longer matches and consent is requested again.
The file is written with 0600 permissions and the number of records is capped.
If the file is unreadable or was written by a newer version, it is left alone rather than overwritten.
Publish prompts now say your file becomes a private page on claude.ai instead of an "Artifact".
You'll notice · Artifacts
What
The permission prompt for publishing a file no longer describes it as rendering to an "Artifact". It now says the HTML or Markdown file is published as a page on claude.ai, on Anthropic's servers, private by default, and the prompt says whether it goes to a new page or a named existing one.
Evidence
Publish an HTML or Markdown file as a page on claude.ai (Anthropic's servers), private by default.
Remote transcript upload detects rewritten history and skips suppressed sessions #
Remote transcript uploads track message ids, so compaction no longer loses or duplicates work.
You'll notice · Sessions
What
Uploading a session transcript to the remote side no longer decides what is new by comparing a stored index against the message count, which could miss or duplicate work after a compaction. It now anchors on message ids and tracks which it has already seen, logging when it detects that history was rewritten.
Details
Messages are counted as seen without being uploaded once the session binding has detached.
Uploads of compaction pairs are skipped entirely for sessions carrying history-backfill suppression, with a log line saying so.
Inherited plugins no longer force a lockfile refresh #
Plugins inherited from elsewhere no longer force your plugin lockfile to refresh.
You'll notice · Plugins
What
Claude Code now records, for each enabled plugin, whether it came from this session's own config. Lockfile freshness checks only require a matching lock entry for those plugins, so plugins inherited from elsewhere no longer trigger a relock.
Evidence
fromOwnConfig
Remote bridge retries once after refreshing an expired token #
A remote bridge session that hits an expired token now refreshes and retries once.
You'll notice · Sessions
What
A remote bridge session that gets a 401 during startup now refreshes the OAuth token and tries again, instead of failing. The refresh runs at most once per access token, and if it lands on the final attempt an extra call is made with the fresh token.
Details
Reports bridge_repl_v2_init_401_refresh with a flag saying whether a token was actually refreshed or no refresh was available.
Disconnect reasons "untrusted_device" and "session_stale_relogin" are now classified as auth problems rather than terminal failures, so they take the recoverable path.
Evidence
bridge_repl_v2_init_401_refresh
Session lookup can match a project by the directory recorded in its transcript #
Sessions in truncated or same-named project folders now resolve using the recorded working directory.
You'll notice · Sessions
What
Finding the right project folder for a session no longer depends only on the folder name. Claude Code reads the working directory recorded inside the transcript files and compares it, optionally ignoring case, which disambiguates project folders whose names were truncated.
Details
Reads a relocated path ("relocated" / "relocatedCwd") from the end of the file, falling back to "cwd" via a fast per-line scan of the head.
The recorded path is sanitised the same way project folder names are before comparison.
Transcript lookup by session id now also walks worktrees.
Evidence
relocatedCwd
Clearer error when --bg and --environment are combined #
Combining --bg and --environment now explains they are different backends and shows the right command.
--bg--environment
You'll notice · CLI
What
Passing both now says the two are different backends and shows the direct command to run instead, rather than reusing the older --cloud wording.
Evidence
--bg and --environment are different backends. Use claude -p '<task>' --environment <id> directly to start a session on the environment.
Remote worker conflicts say whether the registration was stale or superseded #
Worker registration conflicts now say whether the registration was stale or superseded.
You'll notice · Sessions
What
When the server rejects a worker registration with HTTP 409, Claude Code reads the reason from the response and reports either a stale registration with no live successor or being superseded by a newer worker, instead of one generic conflict.
Details
The two outcomes log separately as cli_worker_epoch_stale and cli_worker_epoch_mismatch.
Reading the response body is skipped when the client has already closed.
Evidence
cli_worker_epoch_stale
Question prompts are classified using the whole prompt, not just the question text #
Question prompts are classified using labels, descriptions and headers, not just the question text.
You'll notice · Permissions
What
The automatic classification of an AskUserQuestion prompt now sees each option's label, description and preview, the header, and whether multiple selections are allowed, instead of only the joined question texts. Malformed payloads are handled rather than throwing.
Details
A payload that cannot be read is substituted with [malformed AskUserQuestion input] and classification continues.
Evidence
[malformed AskUserQuestion input]
Memory listings point at each store's index document #
Memory listings now show each store's index document path, and reads carry a version.
You'll notice · Memory
What
Listing memory stores now includes an index field giving the path of each store's index document, and reading a memory entry can return a version alongside the content.
Details
The list tool's parameter description was updated to mention the index document path.
version on read output is optional and absent when the store does not supply one.
Saving to a read-only memory store now fails immediately and lists stores you can write to.
You'll notice · Memory
What
Saving to a memory store that is read-only in the current session now fails immediately with the reason read_only and a list of the stores you can write to, instead of appearing to succeed and not persisting.
Details
The system prompt describing the memory index now names the store that owns each entry and marks read-only indexes.
Only reached when connected memory stores are in play; which flag enables those is not settled by anything in this build.
Evidence
is read-only in this session; changes will not persist.
Cross-session sends take plain text without a summary #
Messages to another session accept plain text without a summary; structured objects are rejected.
You'll notice · Cross-Session Messaging
What
Messages addressed to another session skip the usual validation: plain text is accepted without the normally-required summary, and structured object messages are rejected outright with a note that only plain text can cross sessions.
Details
Applies to recipients addressed through the two cross-session transports; ordinary in-session recipients are unaffected.
Requires cross-session messaging to be available in the session.
Evidence
structured messages cannot be sent cross-session — only plain text
Reattaching to a remote session can skip replaying history #
Reattaching to a remote session can skip resending history the client already has.
You'll notice · Sessions
What
A reattaching bridge can now install only the live transcript writer and skip syncing the historical conversation, which avoids re-sending a transcript the remote client already has.
Details
The REPL passes the suppression flag through and marks that suppression was applied; the skip is logged.
Evidence
[bridge:repl] Persistence backfill suppressed — installing live writer only
Forking a session tells the model the fork is separate #
After forking, Claude is told the fork is a separate session reachable by name.
You'll notice · Sessions
What
After forking, Claude is now told that the fork runs as its own session, that its work is invisible to the current conversation, and that it can be reached by name through the session roster. This branch previously attached nothing.
Details
The message is produced only when cross-session messaging applies; otherwise nothing is attached.
Evidence
The fork runs as its own separate session
Peer lookups say when other machines' sessions could not be checked #
If peer listing failed, the not-found message now says other machines could not be checked.
You'll notice · Cross-Session Messaging
What
When you name a peer session that is not found, the refusal now adds a note if the listing of sessions reachable over the remote bridge timed out or failed, explaining those sessions can only be replied to from this machine and cannot be addressed by name.
Details
Backed by a marker recording why the listing failed, with values timeout and fetch_failed.
Evidence
and files can't be sent to it by name from this machine.
Sandbox credential matching ignores ports and schemes in host entries #
Sandbox credential host entries written with a port or scheme now still match.
You'll notice · Sandbox
What
Host entries controlling which credentials get injected into a sandbox are now normalized to a bare host pattern and de-duplicated before matching, so an entry written with a port or scheme still matches, and repeated entries collapse.
Details
Applies to the environment variable, AWS key-pair and masked-file credential resolution paths.
Only affects the sandbox credential configuration path.
Evidence
degradeToUnsetNames
Archive-installed plugins get a real version instead of "unknown" #
Plugins installed from an archive now show a real version instead of "unknown".
You'll notice · Plugins
What
A plugin installed from a downloaded archive with no pinned checksum now gets a 12-character version derived from the hash of the content that was actually downloaded, rather than reporting "unknown". The log line says whether the hash was pinned or downloaded.
Evidence
Using archive sha256 version for
claude plugin eval init no longer suggests a flag that will not help #
The no-terminal message for eval init dropped a flag suggestion that would not have helped.
You'll notice · Plugin Eval
What
The message shown when there is no terminal dropped its "(or pass --interactive)" suggestion, since the interview needs a terminal either way. It now just says to re-run in a terminal.
Evidence
No TTY available \u2014 writing a blank template. Re-run in a terminal for the authoring interview.
Plugin install retries inside a wrapper directory #
Plugin installs now retry inside an archive's wrapper folder when declared paths are missing.
You'll notice · Plugins
What
When a plugin archive's declared entry paths do not exist under the directory install picked, it now retries against the archive's single wrapper subdirectory, and can fall back to the archive root instead, logging which one it used.
Details
Covers the common case of an archive whose contents sit one level down inside a single folder.
Evidence
Plugin archive entry paths resolve at the archive root; using it instead of the promoted subdirectory
Shell commands run from a skill preamble get distinct IDs #
Commands run from a skill preamble get their own IDs, so results no longer collide.
You'll notice · Skills
What
Each command validated from a skill's preamble now gets its own tool-use ID rather than sharing the caller's, so results and permissions no longer collide between them.
Details
IDs take the form parent id + :preamble- + index; the Bash tool finds that marker in the id and recovers the parent id from the text before it.
The separate :inner suffix keeps its existing meaning.
Evidence
:preamble-
A locally configured self-hosted pool always appears as a target #
Your configured self-hosted pool now appears in the picker even if the server omits it.
You'll notice · Self-Hosted Runners
What
The environment picker now shows your configured self-hosted pool even when the server's pool list does not include it, so a freshly configured pool is selectable straight away.
Details
Applies to pool ids beginning ccpool_; the synthesized entry reports zero live runners and no creation date.
Evidence
self_hosted_pool
Git clone errors no longer mangle URLs containing dollar signs #
Clone errors no longer mangle text when the repository URL contains dollar signs.
You'll notice · Elsewhere
What
When a clone fails, the repository URL is redacted out of the error and stderr text. Redacted URLs containing $&-style sequences are now inserted literally instead of being expanded into surrounding text.
Evidence
--filter=blob:none
Failed peer listings are reported rather than looking empty #
A failed peer listing is now reported as a failure rather than an empty roster.
You'll notice · Cross-Session Messaging
What
When Claude Code cannot list the other sessions it can reach, the failure is now recorded as a failure instead of coming back as an empty roster. This matters for the ListAgents tool, which only records what the model saw when the listing actually succeeded.
Details
Failure is set when auth preparation throws, when the list request throws, or when the server returns a non-200 status.
Logs [bridge:peers] auth prep failed:, [bridge:peers] list request failed: and [bridge:peers] list failed.
The population fetch carries the failure flag through and logs a "FAILED, not recordable" marker.
Evidence
[bridge:peers] auth prep failed:
Inline plugin downloads retry the final file move #
Inline plugin downloads retry the final file move, cutting spurious install failures.
You'll notice · Plugins
What
Downloading an inline plugin now uses the shared retrying rename when moving the finished download into place, which should cut spurious failures when the destination is briefly locked.
Details
Replaces a direct rename of the partial download file, immediately before the "Downloaded inline plugin from" log line.
Plugin manifest load failures now report through a helper bound to the span name, taking only the reason (plugin_load_manifest_read_failed, plugin_load_manifest_json_invalid), and reuse the already-resolved manifest lookup.
Evidence
plugin_load_manifest_read_failed
Feedback drafts explicitly cover the model's behaviour, not just the product #
The feedback tool now says it covers Claude's own behaviour, not just product bugs.
You'll notice · Feedback
What
The description of the feedback tool now says it covers Claude Code the product or the model's own behaviour in the current session, so complaints about a bad answer are in scope rather than just product bugs.
Details
New text: "Queue a draft feedback report about Claude Code — the product OR the model's own behavior in this session — for the user to review and send later."
Still controlled by the feedbackDrafts setting: notify (default), quiet, or off, where off disables the tool entirely.
Evidence
Queue a draft feedback report about Claude Code \u2014 the product OR the model's own behavior in this session \u2014 for the user to review and send later.
Compaction boundaries can appear in streamed output #
Compaction boundary markers can now show up in streamed output.
You'll notice · Compaction
What
When a conversation is compacted, the marker for that boundary is now eligible to be emitted in streaming output alongside local command messages.
Details
The filter accepts system messages with subtype compact_boundary; previously only local_command passed.
A predicate can be registered to suppress them; with nothing registered it defaults to allowing them, so in this build they are emitted.
Evidence
compact_boundary
Team memory prompt no longer explains saving when nothing can be saved #
With no writable team memory, Claude is no longer told how to save memories.
You'll notice · Memory
What
When your project has no writable team memory location, the instructions telling the model how to save memories are dropped from its prompt entirely, leaving only a statement that access is read-only.
Details
The removed block is the "## How to save memories" section.
What remains: "You have read-only access to team memory synced from your project. You cannot persist new memories in this session."
A shorter one-step variant of the save instructions is used when no index is required.
Evidence
You have read-only access to team memory synced from your project. You cannot persist new memories in this session.
Expired pastes are dropped from the prompt with an explanation #
Expired pastes are dropped from your prompt with a notice instead of sending a placeholder.
You'll notice · Input
What
If a pasted block is no longer available when you submit, it is now removed from the prompt and you get a notice saying so, instead of a literal placeholder being sent to the model.
Details
The old placeholder text "[Pasted text #N — content no longer available]" has been removed.
Pastes flagged as unavailable are excised from both the shortened and fully expanded prompt.
The notice is built from "is no longer available and was removed from the prompt", with a plural form "are no longer available and were removed from the prompt", and labels the item either "Pasted text" or "Truncated text".
Evidence
is no longer available and was removed from the prompt
Host credentials path normalised like every other sandbox rule #
A trailing slash in your host credentials file path no longer changes whether the rule matches.
CLAUDE_CODE_HOST_CREDS_FILE
You'll notice · Sandbox
What
The file named by CLAUDE_CODE_HOST_CREDS_FILE is now run through the same path normaliser as sandbox allow/deny entries and permission deny rules, so a trailing slash no longer changes whether the rule matches.
Details
Sandbox deny and allow filesystem entries, permission deny rules and the host credentials path all share one trailing-separator-aware normaliser when sandbox rules are built.
Previously each of these handled paths its own way.
Evidence
CLAUDE_CODE_HOST_CREDS_FILE
Sandbox violation text is stripped of angle brackets #
Angle brackets are stripped from sandbox violation text before it is stored.
Under the hood · Sandbox
What
Sandbox violation lines are normalized and have < and > removed before being stored, so violation text cannot smuggle tag-like markup into anything that later displays it.
Evidence
addViolation
Memory tool output no longer shows up in transcript search #
Memory tool contents no longer clutter transcript search results.
You'll notice · Memory
What
The memory read and memory-list tools now report empty search text, so their contents are excluded from transcript search indexing. Read results also carry a version derived from the document's content.
Command helpers can now redirect child output instead of always buffering it in memory.
Under the hood · Elsewhere
What
The shared command-running helpers now pass through stdout and stderr options when a caller supplies them, so child process output can be redirected instead of always being buffered in memory.
Evidence
preserveOutputOnError
Clearer failure when a plugin uses an unsupported source type #
A plugin source this version does not recognise now tells you to update Claude Code.
You'll notice · Plugins
What
Installing a plugin whose marketplace entry has a source kind this version does not recognise now fails with a direct message telling you to update Claude Code, instead of a generic error.
Details
Message: "This plugin uses a source type your Claude Code version does not support. Update Claude Code and try again."
Evidence
This plugin uses a source type your Claude Code version does not support. Update Claude Code and try again.
Messaging another agent skips the auto-mode classifier and no longer counts toward denials.
You'll notice · Cross-Session Messaging
What
Sending a message to another agent no longer goes through the auto-mode permission classifier, so it avoids classifier input parsing and does not count toward denial totals.
Evidence
SendMessage
Artifact publish errors say whether retrying can help #
Artifact publish errors now say whether retrying will help, based on the HTTP status.
You'll notice · Artifacts
What
When Claude Code cannot read back a page to verify a live edit, republish or publish, the message now branches on the HTTP status. Any 4xx other than 408 and 429 is reported as permanent with advice not to retry, 403 adds a note to retry at most once because a concurrent republish can cause it, and reads blocked by the environment's network allowlist say so.
Evidence
An HTTP ${zt.status} failure is not transient, so retrying this live-edit cannot succeed \u2014 WebFetch the page to check its state.
Sandbox proxy only buffers request bodies when there is one #
The sandbox proxy only buffers request bodies when one exists, and tears down bad requests.
You'll notice · Sandbox
What
The sandboxed network proxy now copies a request body only for methods that carry one, or when a content-length or transfer-encoding header is present, and tears down both streams when a request is malformed or denied. Deny messages were reworded and encrypted-tunnel requests are now filtered against a decoded command name.
Evidence
denied by sandbox policy
claude plugin eval init --interactive fails clearly without a terminal #
Asking for the eval interview without a terminal now fails clearly and tells you the alternative.
--interactive
You'll notice · Plugin Eval
What
Asking for the interactive authoring interview when there is no real terminal attached now prints an explanation and exits 1, instead of trying to run the interview. The message tells you to either run it in a terminal or drop --interactive and pass a case name to get a blank template. There are two wordings depending on whether you supplied a case name.
Evidence
The authoring interview requires an interactive terminal (TTY). Run claude plugin eval init in a terminal, or drop --interactive and pass a case name (e.g. claude plugin eval init my-case) to write a blank template instead.
Usage
claude plugin eval init my-case
Bedrock inference profile lookup failures are logged #
Bedrock profile lookup failures are now logged instead of silently falling back to built-in models.
You'll notice · Bedrock
What
When listing Bedrock inference profiles throws, an error-level log now says it is falling back to the built-in model list and includes the underlying error text. Previously the failure was silent and you only saw the fallback models.
Evidence
Failed to list Bedrock inference profiles, falling back to hardcoded models:
Trailing slashes in permission and sandbox path rules #
Permission and sandbox path rules now strip trailing slashes consistently, including UNC paths.
You'll notice · Permissions
What
Path rules for permissions and sandbox filesystem access now strip trailing separators the same way everywhere, with separate handling for Windows paths and for UNC network paths. A new internal option controls whether that cleanup is also applied to the part of a path after a glob.
Evidence
evenAfterGlob
Guidance on when multiagent is worth it, and a corrected docs link #
Multiagent docs gained a staged guide on when extra agents are actually worth it.
You'll notice · Agent SDK Docs
What
The multiagent docs gained a step-by-step section with Python examples: start with a roster of just {"type": "self"}, move reading-heavy sub-tasks to a cheaper worker model, and only then add dedicated specialists. The overview and skill entry point now point fan-out shaped work here.
Details
The URL fetched for live docs was wrong and is corrected from multi-agent.md to multiagent-orchestration.md.
Agent versions are sequential integers, not timestamps #
Agent versions are documented as counting up from 1, not timestamps.
Under the hood · Agent SDK Docs
What
The docs previously said each agent update produced a version numbered with a timestamp, and gave a timestamp example. They now say versions start at 1 and increment by one on each update.
Details
Also tightened: effort is the only field exempt from full replacement when you supply a model object, and supplying model without inference_geo clears any pinned geography.
Evidence
a sequential integer, starting at 1 and incrementing on each update
Proxy tears down both sockets on a rejected request, and chunks bodyless forwards #
The proxy now closes both sockets on a rejected request instead of leaving half-open connections.
You'll notice · Sandbox
What
When a request is denied or AWS SigV4 re-signing fails, the proxy now destroys the client socket and, if the original socket is a different one, fails that too, instead of leaving a half-open connection.
Details
Separately, if an incoming request declared a body but neither content-length nor transfer-encoding survives into the outbound headers, the proxy sets transfer-encoding: chunked.
Evidence
AWS SigV4 re-signing failed:
Clearer answer when a message target is not found #
An unresolved message target now says which of three reasons applied, hedging if listing timed out.
You'll notice · Cross-Session Messaging
What
If you message a session name that does not resolve, Claude now says which of three things happened: the name matches a Remote Control session that can only reply to you from elsewhere, the name genuinely does not exist, or the list of remote sessions did not load in time, in which case it hedges rather than claiming the name is wrong.
Evidence
bridge population not ready within
Sandbox proxy credentials are unique per sandbox instance #
Concurrent sandboxes now get unique proxy usernames instead of sharing one identity.
HTTP_PROXYALL_PROXYCLOUDSDK_PROXY_USERNAME
You'll notice · Sandbox
What
Proxy settings injected into the sandbox (HTTP_PROXY, ALL_PROXY, CLOUDSDK_PROXY_USERNAME, and the socat/ssh ProxyCommand) now use a username with an instance suffix rather than the fixed srt, so concurrent sandboxes no longer share one identity. If the suffixed name would exceed 255 bytes it falls back to plain srt.
Evidence
CLOUDSDK_PROXY_USERNAME=
MCP OAuth discovery cache is re-validated against policy #
Cached MCP OAuth details are rechecked against policy, so moved servers no longer authenticate stale.
You'll notice · MCP
What
Cached OAuth discovery details for MCP servers are now re-checked against policy before reuse and kept only for a fixed window. If the cached authorization server fails the check, stored credentials are invalidated and the cached entry is cleared instead of being reused, so a server that has moved or been disallowed no longer silently authenticates against a stale endpoint.
Evidence
Returning cached discovery state (authServer:
Memory paths capped at 1024 bytes and reserved names refused #
Memory paths over 1024 bytes and reserved names like skills or hooks are now refused.
You'll notice · Memory
What
A memory path longer than 1024 bytes is now rejected, and callers that ask for unsafe segments to be rejected also refuse reserved directory names such as skills, commands, agents and hooks. The refusal message was rewritten and no longer echoes the raw path unescaped.
Evidence
and are not reserved names (skills, commands, agents, hooks, and similar
Plugin marketplace downloads get a size cap and redirect checks #
Marketplace downloads now cap response size and vet redirects before following them.
You'll notice · Plugins
What
Marketplace fetches now enforce a maximum response size and inspect redirects before following them, and errors redact the fetched URL out of the technical details shown to you.
Details
Plugin entries are checked for declared component paths, limited to 32 entries and rejecting URLs and traversal-style segments.
Archive extraction can now descend into a single wrapper directory when that directory contains a .claude-plugin directory.
Evidence
beforeRedirect
Long tool results are clamped in the memory tool output #
Memory tool output is trimmed to 10 lines unless you run in verbose mode.
You'll notice · Memory
What
Memory tool results no longer flood the terminal. At most 10 lines are shown, each line is cut at 200 characters with an ellipsis, and a dimmed "+N more lines" note is appended. Running in verbose mode disables both limits.
Details
Errors are unwrapped from their <tool_use_error> wrapper, with the first line shown in the error colour and the rest clamped the same way.
Wired in for the memory_write tool family.
Evidence
<tool_use_error>
Settings refresh skips notifying when a login or logout races it #
Logging in or out mid-refresh no longer lets stale settings overwrite your new state.
You'll notice · Settings
What
If you log in or out while a remote settings fetch is in flight, the result is discarded instead of being applied over the newer state. The refresh snapshots an auth version before fetching and returns early if it changed.
Details
Logs "Remote settings: Refresh superseded by a login/logout reset; not notifying".
A pending reset callback now also runs on the failure path, and chains onto an in-flight refresh when one exists.
Evidence
Remote settings: Refresh superseded by a login/logout reset; not notifying
Plugin install from a marketplace now honours archive auth on one more path #
Installing from a marketplace entry now forwards archive credentials on one more code path.
You'll notice · Plugins
What
A remaining plugin install call site was brought in line with the others, so installing from a marketplace entry now looks up its source and forwards the archive credentials and the component paths declared in the manifest. Authenticated archive sources work on that path too.
Evidence
entryDeclaresComponents
Self-hosted environments get a labelled section in the picker #
The environment picker now shows a labelled divider above your self-hosted entries.
You'll notice · Self-Hosted Runners
What
The session/environment picker now shows a labelled divider row above your self-hosted entries instead of a blank spacer, so it is clear where that group starts.
Evidence
— Self-hosted environments —
Broken marketplace entries say what is wrong with them #
A broken marketplace entry now tells you what failed validation instead of a generic message.
You'll notice · Plugins
What
A marketplace entry that fails validation is still listed as unsupported, but now carries the validation reason, and an install attempt reports it. Entries that genuinely declare a source type Claude Code does not support keep the old generic message.
Evidence
This plugin's marketplace entry is invalid:
Clearer warning when writing into an unsynced memory-store copy #
Writing into a stale local copy of a memory store now warns that nothing syncs it.
CLAUDE_MEMORY_STORES
You'll notice · Memory
What
Writing into a directory that belongs to a project memory store now gives one of two messages. If memory stores are configured through the CLAUDE_MEMORY_STORES environment variable you get the existing overwrite warning; otherwise you get a new message saying the directory is a leftover local copy that nothing syncs or recalls.
Details
Which message you see is decided entirely by whether CLAUDE_MEMORY_STORES is set.
Evidence
This file's directory is a leftover local copy of a project memory store that is no longer synced.
Sandbox proxy logs blocked requests and repairs lost request framing #
The sandbox proxy now logs each denied request with its method, URL and reason.
You'll notice · Sandbox
What
The sandbox's HTTPS proxy now logs each denied request with its method, URL and the reason it was denied, so a blocked network call is traceable rather than silently failing.
Details
The proxy takes a denial callback; the log message is assembled at the time of the denial.
When an incoming request has a body but the outgoing headers ended up with neither content-length nor transfer-encoding, the proxy sets transfer-encoding: chunked so the body is still framed correctly.
If either side of the connection died while the request filter was running, the proxy now tears the connection down cleanly.
Evidence
onFilterRequestDenied
WSL settings are read without blocking the settings refresh #
On WSL, reading inherited Windows settings no longer blocks the periodic settings refresh.
You'll notice · Elsewhere
What
On WSL, the periodic settings refresh now reads the inherited Windows settings file asynchronously and awaits it, instead of doing a synchronous read on the interval.
Details
Disposal is rechecked after each await so a refresh in flight does not act on a torn-down poller.
Evidence
wslWindowsFile
Clearer refusal when a name matches a device-gated remote session #
Messaging a reply-only remote session now explains why, instead of a generic not-found.
You'll notice · Cross-Session Messaging
What
Sending a message to a name that only matches a reply-only remote session now explains that specifically, rather than returning a generic not-found. The text states that the Claude Code Remote send_message connector cannot reach these sessions and that the "untrusted device" error it produces is misleading.
Details
When the peer list itself fails to load, the fetch is now marked as failed so the caller hedges instead of flatly refusing.
Only reachable when cross-session messaging is active in the session.
Evidence
it cannot reach these device-gated sessions, and its "untrusted device" error is misleading
Rate limit status is pushed to the remote client #
Your rate limit status now reaches a connected remote client right away.
You'll notice · Sessions
What
Rate-limit state now reaches a connected remote client immediately. On bridge connect the current state is written to the peer, and later rate-limit events are written to the bridge channel as well as the local stream. Forwarding failures are logged, not thrown.
Details
The connect-time send is skipped if a rejection window has already elapsed, and is recorded as bridge_rate_limit_forward.
Both paths build the event through one shared helper.
The connect-time send is also guarded by an internal predicate whose source of truth sits outside this code path.
cloud CLI: piped stdin no longer silently overrides a task description #
Piped input no longer silently overrides a task description you passed to --cloud.
--cloud--environment
You'll notice · Cloud Sessions
What
Giving --cloud a task description while also passing --environment and piping stdin is now rejected instead of letting stdin quietly win. When an environment is given, creating the session also prints its id.
Details
The error for public projects now tells you to drop --environment instead of mentioning Anthropic-managed environments.
Evidence
Error: --environment with --cloud <description> cannot also take piped stdin. Pass the task as the description, or drop --cloud.
MCP OAuth issuer mismatches are now recorded separately from other auth errors.
Under the hood · MCP
What
OAuth failures against an MCP server now classify issuer-echo problems separately from generic auth errors, so logs and telemetry can tell them apart from cases like a redirect URI mismatch or a Microsoft Entra specific failure.
Details
The token refresh path can now fail with the distinct reason mcp_oauth_refresh_issuer_echo_denied.
Peer session listings now say when there are more sessions than shown.
You'll notice · Cross-Session Messaging
What
Listing peer sessions used to return a partial list silently once it exhausted its page budget. It now tells the caller and the log line that more sessions exist.
Evidence
pages (more sessions exist)
Reattaching to a vanished bridge session skips history backfill #
Reattaching to a vanished remote session mints a fresh one without backfilling missing history.
You'll notice · Sessions
What
When you reattach to a remote bridge session that no longer exists, Claude Code mints a fresh session instead, and that session is now flagged to skip backfilling history it does not have. The replacement also gets a neutral fallback title rather than inheriting the old one.
Details
The flag is threaded through the transport options, the bridge-session transcript entries, the session-state maps and the clear/save helpers, so it survives save and restore.
Triggered by a reattach-target-gone callback; nothing else in the build sets the flag.
Eval reports now shorten huge evidence blocks and point at the full text on disk.
You'll notice · Plugin Eval
What
Generated evaluation reports now elide the middle of the evidence block shown to the judge above roughly 20000 characters, keeping the first 16000 and last 4000 and leaving a marker that points at the full text in the JSON artifact on disk. The judge prompt uses the same elision.
Details
The aggregate results file is now written with a trailing newline.
Evidence
aggregate-result.json, full text in aggregate-result.json
Bridge disconnects say what kind of failure happened #
Dropped bridge connections now say what kind of failure happened rather than one generic message.
You'll notice · Sessions
What
A dropped repl bridge connection now records an error kind alongside the error message, and close code 4090 distinguishes a session worker registration that has gone stale with no active worker holding it from a session the server does not have, instead of showing one generic message for both.
Evidence
the session worker registration went stale \u2014 no active worker holds it (code 4090)
Malformed JWT masking options in credential rules are now discarded.
You'll notice · Sandbox
What
Deny-mode credential masking rules now discard a decode value that is not "jwt", and discard maskClaims unless it is an array of strings, on top of the existing cleanup of the extract, no-match and duplicate-masking options.
Evidence
maskClaims requires decode \u2014 without a decode format there is no token to read claims from. Set decode, or omit maskClaims.
Teammate message failures are labelled, and inbox write failures reported #
Failed teammate messages now say the recipient was unreachable, including when their inbox write failed.
You'll notice · Cross-Session Messaging
What
When SendMessage cannot find a teammate, the teammate has left, the roster has duplicate or unreadable entries, the failure is now tagged as not reachable. A new case covers the recipient's inbox write returning nothing, and tells you the message was not sent.
Evidence
Failed to write to ${e}'s inbox \u2014 nothing was sent. Try again, or message the lead.
Wayland clipboard copies run one after the other #
On Wayland, clipboard and primary-selection writes now happen in order, not simultaneously.
You'll notice · Elsewhere
What
On Linux under Wayland, copying no longer writes the clipboard and the primary selection at the same time. The clipboard write completes first, and if a newer copy has begun in the meantime the primary-selection write is skipped.
Details
Applies when WAYLAND_DISPLAY is set and wl-copy is on PATH.
Both writes have their output discarded.
Evidence
wl-copy
Pastes that can no longer be loaded are handled explicitly #
Pastes whose data can no longer be read are marked unavailable instead of lingering oddly.
You'll notice · Input
What
Pasted content whose data can no longer be read is now marked unavailable rather than left in an odd state. Text pastes count alongside images and audio when clearing out abandoned pastes, and their placeholders are removed from what you see, shown instead as "Pasted text" or "Truncated text".
The Memory tool's store list now ends each line with the store's index.
You'll notice · Memory
What
The Memory tool's list of connected stores now ends each line with the store's index, after the id, description and writable or read-only marker.
Details
Appears under the existing "Connected memory stores" header; the index is assembled into the line at runtime.
Evidence
Connected memory stores
Blocked-by-proxy responses are detected from a second header #
Proxy-blocked requests are recognised from a second header, so more networks get the proper message.
You'll notice · Internals
What
When a request is refused by a network proxy allowlist, Claude Code now recognises the block from either of two response headers, so more environments get the proper "blocked by egress policy" handling instead of a generic HTTP 403.
Details
An HTTP 403 counts as blocked when x-proxy-error is blocked-by-allowlist or when the new x-deny-reason header is host_not_allowed.
Previously only the first header was checked, and only at the GitHub comments call site; the check is now a shared helper.
Evidence
host_not_allowed
Publicly shared artifacts are labelled correctly #
A publicly shared artifact now correctly reads "anyone with the link".
You'll notice · Artifacts
What
An artifact shared publicly now reports its audience as "anyone with the link" instead of falling through to the unrecognised-sharing fallback.
Details
Share-mode parsing gained an explicit public case that reports the artifact as shared and live.
Previously this mode hit the "others (unrecognized share mode — treating as shared)" branch, which treated it as shared but described it vaguely.
Evidence
anyone with the link
Messages from peer sessions are shown unless suppressed #
Activity messages from a peer session with no named sender are now shown by default.
You'll notice · Cross-Session Messaging
What
Activity messages originating from a peer session with no identified sender are now displayed by default rather than hidden by default.
Details
The display check's boolean argument now falls back to true instead of false, so a caller must explicitly pass false to hide one.
Evidence
observer-activity
Bash tool told that command output may not reach you #
Claude is told you may not see command output, so it should summarise results.
You'll notice · Bash Tool
What
The Bash tool description now states plainly that command output is shown to the model but not reliably to the user, which should push the model to summarise results rather than assume you saw them.
Details
Added line: "- Command output is displayed to you, not reliably to the user."
It replaces one of the fragment lists previously spread into the assembled description.
Evidence
- Command output is displayed to you, not reliably to the user.
Pasted content marked unavailable is skipped when expanding input #
Pastes marked unavailable are skipped when your input is expanded.
You'll notice · Input
What
The two places that substitute pasted text back into your input now skip entries flagged unavailable, so a dropped or expired paste is not inlined.
Details
Previously only non-text entries were skipped.
The input component now receives getPastedContents and getInputMode, image ids are minted through a shared allocator with an onMinted callback, and the command handler surface gains getCurrentInput.
Evidence
getPastedContents
Analytics shutdown waits for queued work before closing sinks #
Analytics now drain queued events before shutting down, so crash-path events have a chance to send.
Under the hood · Telemetry
What
Shutdown now drains a queue of pending analytics tasks, raced against a 200 ms timeout, before the event logging, Datadog and error-tracking sinks are closed. The first user of this is the MCP tripwire event, so an event fired on a crash path now has a chance to be sent instead of being dropped at exit.
Evidence
registerPreFlushTask
Two more MCP connections skip issuer metadata validation #
Two more MCP transports now skip issuer metadata validation, matching the rest.
Under the hood · MCP
What
Two MCP client setup paths now set the same issuer-metadata-validation skip that the other paths already used, so OAuth-backed MCP servers behave consistently across transports.
Evidence
skipIssuerMetadataValidation
Archive-installed plugins are no longer mistaken for ref-tracking ones #
Zip-installed plugins keep their pinned version instead of being re-fetched on every load.
You'll notice · Plugins
What
A plugin whose cache directory is a 12-character hex name used to be treated as tracking a git ref, which meant it was re-fetched on every load. That check now also requires the plugin to come from a git source, so zip-archive plugins, whose cache directory is the first 12 hex characters of the archive digest, keep their pinned version.
Only your main conversation can write memory documents; subagents are blocked from memory_write.
You'll notice · Memory
What
The new memory write tool was added to the list of memory tools blocked for subagents and custom agents, so only the main conversation can save documents to a memory store.
Evidence
["memory_list", "memory_read", "memory_write"]
Remote Control sessions now explain that they are reply-only #
Messaging a Remote Control session now explains it is reply-only until it messages you first.
CLAUDE_CODE_HARBOR_KITE
You'll notice · Cross-Session Messaging
What
Sending a message or file to a name that matches a Remote Control session on your account no longer just fails. The tool now says such sessions are reply-only from here and can be messaged only after they message you first, and that the Remote send_message connector cannot reach these device-gated sessions. A hedged version of the message appears when the list of sessions could not be fetched.
Details
The ListAgents tool now also advertises ListPeers as an alias.
The cross-device recipient schema variant behind this sits on the remote-config flag tengu_harbor_kite, whose fallback here is off, or the CLAUDE_CODE_HARBOR_KITE environment variable.
Published pages now handle an unstamped theme, so they respect your browser's light or dark setting.
You'll notice · Artifacts
What
The publishing prompt and the artifact-design guidance now treat the viewer as having three theme states rather than two: explicitly dark, explicitly light, and an unstamped default where only the browser's prefers-color-scheme decides. Generated pages are told to define a full light palette on :root, guard the dark media block so an explicit light choice wins, add a dark override, and set an explicit background on body so a transparent page does not pick up the host's colour.
Evidence
guarded as \:root:not([data-theme="light"])\``
Allowlist blocks recognised from a second proxy header #
Artifact fetches recognise a second proxy header as a network allowlist block.
You'll notice · Artifacts
What
Artifact fetches now treat a 403 carrying x-deny-reason: host_not_allowed as a network allowlist block, alongside the existing x-proxy-error: blocked-by-allowlist, and other failures append the proxy's deny reason to the error text. The message makes clear the artifact itself is still accessible.
Evidence
not reachable through this environment's network allowlist; your access to the artifact itself is fine (the boot check passed)
Exported Claude archives no longer need every index file #
Importing an exported Claude archive now only requires conversations.json; missing indexes are rebuilt.
You'll notice · Internals
What
Importing an exported .zip only requires conversations.json now. If the combined projects.json is missing, projects are read from the individual projects/*.json files instead, and the archive summary is rebuilt from users.json plus per-conversation message counts rather than being required in the file.
Evidence
export zip missing required entry
Contradictory publish flags are rejected up front #
Passing both --no-publish and --publish-report now errors before the run starts.
--no-publish--publish-report
You'll notice · Plugin Eval
What
Passing both --no-publish and --publish-report now stops the run before it starts with an error, rather than starting and then behaving ambiguously.
Evidence
Error: --no-publish and --publish-report are contradictory
Remote environment picker marks self-hosted entries #
The environment picker labels self-hosted entries and shows a dimmed live runner count.
You'll notice · Self-Hosted Runners
What
After you set a default environment the confirmation says either "remote environment" or "self-hosted environment", and self-hosted entries in the list now show a dimmed count of live runners next to them.
Evidence
alive_runner_count
Drain loops should break on budget_reached, not just terminal stops #
Skill guidance now says polling loops should break on any stop reason except requires_action.
Under the hood · Agent SDK Docs
What
The skill's client-patterns guidance changed its advice for loops that poll a session: break on any stop reason that is not requires_action, rather than only on terminal ones. budget_reached is listed as resumable only by changing the budget.
Details
The sample loop comment moved from // end_turn or retries_exhausted - both terminal to also name budget_reached.
Evidence
break // end_turn, retries_exhausted, or budget_reached \u2014 see list below
vault_ids documented as create-only, and deployments can be updated #
Docs say vault_ids cannot change mid-session, and deployments now have an update endpoint.
You'll notice · Agent SDK Docs
What
Session update docs now state that vault_ids is rejected on update even though the SDK exposes it as a parameter, so only agent.tools, agent.mcp_servers, title, metadata and budget can change mid-session. Deployments gain an UpdateDeployment endpoint and deployments.update SDK method.
Details
A deployment can carry a budget that is copied onto every session it fires; it can be cleared and added back at the deployment level.
Evidence
`vault_ids is create-only (rejected on update) `
Task budgets and session budgets are no longer conflated #
Docs now warn that task_budget is advisory tokens while session budgets are hard dollar caps.
task_budget
You'll notice · Agent SDK Docs
What
The skill's quick reference and its feature-support notes now warn that the Messages API task_budget is advisory and counted in tokens, while a Managed Agents session budget is a hard, dollar-denominated cap enforced by the platform.
Details
The model-tier restriction (Opus 5, Fable 5, Sonnet 5, 4.8, 4.7) applies only to the Messages API form; session budgets have no tier restriction.
Evidence
Not the same thing as Managed Agents session budgets
A plugin entry that fails validation now keeps the reason #
A marketplace entry with bad fields keeps its validation error instead of looking unsupported.
You'll notice · Plugins
What
When a marketplace entry uses a source type Claude Code knows but gets its fields wrong, the entry is kept along with the validation error instead of looking identical to a source type this version simply does not recognize.
Details
The message is compacted before storage: unrecognized field names are listed and sanitized, the text is truncated with an ellipsis, and extra items are rendered as "(+N more)".
Evidence
Placeholder for source types this Claude Code version does not recognize, or a known type whose fields failed validation (then error
Sandbox AWS credential pairs get precedence rules and scope warnings #
Conflicting AWS credential pairs in the sandbox now resolve predictably and warn about risky setups.
credentials.awsPairs
You'll notice · Sandbox
What
The sandbox's forwarding of AWS credentials via credentials.awsPairs now resolves conflicts predictably and warns about risky setups. Later entries override earlier ones with the same target, each environment variable can fill only one slot, and the losing slot is disabled with a placeholder rather than silently taking the wrong value.
Details
Deliberately empty "suppressor" entries are preserved so they keep implicit AWS auto-pairing switched off.
Pairs whose key id or secret are not masked as whole values are either dropped or forwarded with a warning.
New warning when SigV4 re-signing is configured without injectHosts, because the real secret is then in scope at every entry in network.allowedDomains.
New warning when a session token belonging to a forwarded pair is not itself forwarded.
Evidence
SigV4 re-signing with the real secret is in scope at EVERY host in network.allowedDomains
Plugin archive downloads are checked on every redirect hop #
Plugin archive downloads re-check policy at every redirect and strip headers on cross-origin hops.
You'll notice · Plugins
What
Installing a plugin from an archive URL now re-applies the URL policy at each redirect, and refuses the install if any hop fails it. Headers inherited from the marketplace are stripped when a redirect crosses to a different origin, and a sha256 that does not match aborts the install.
Details
Marketplace catalog redirects must stay on the same origin, or be https to a host that is neither loopback nor a cloud metadata address.
An archive that does not actually contain the component paths its marketplace entry declares is rejected, with advice on repackaging.
Evidence
plugin archive redirect policy rejected
Bug Fixes
34 items
Pasted content that has expired is reported instead of silently dropped #
If a pasted attachment has expired, you get told instead of quietly sending a prompt without it.
You'll notice · Paste Handling
What
On submit, pasted entries that are no longer available are removed and you get an immediate notification rather than a prompt that quietly lost its attachment. If nothing is left after stripping, or the input was a bash or slash command, the submit is aborted and your original text is restored.
Details
Editing across multiple inputs also renumbers colliding pasted-text ids, so pastes from different inputs no longer overwrite each other.
Evidence
pasted-text-unavailable
Bridge event checks fail closed when their config is malformed #
If the bridge event rules are unreadable, only fully verified events are accepted.
Under the hood · Editor Bridge
What
If the configuration controlling which bridge events are accepted fails to parse, verification now falls back to the strictest setting (accept only fully verified events, no other statuses allowed) and reports "malformed_config" once, rather than proceeding on a partial config.
Details
Unverified events that are not control requests are dropped with a warning that classifies the payload as control_request_other or other_payload_type.
Drops are reported as bridge_stray_event_attestation, deduplicated to once per class per process so a flood does not spam telemetry.
Direct messages you send with @name now warn you when delivery fails.
You'll notice · Team Messaging
What
Sending a direct message by typing @name in the REPL now shows a 5 second notification when the write to the recipient's mailbox fails, instead of quietly doing nothing. Success shows the same confirmation as before.
Details
Both paths now run through one shared helper, so the success and failure cases cannot drift apart.
Evidence
Couldn't write to @
Conversation resets are never dropped from a full event queue #
A conversation reset can no longer be discarded when the event queue is overloaded.
Under the hood · Editor Bridge
What
When the bounded queue of task events fills up, it no longer evicts a conversation reset. Resets and null-status system frames are skipped as eviction candidates and the next eligible entry is evicted instead, so a reset cannot be lost under load.
Details
Tearing down the remote-control bridge while a reset is still undelivered now reports that fact and resets the bridge's own state.
Evidence
bridge_conversation_reset
MCP OAuth discovery state no longer wiped during a concurrent re-save #
A race no longer wipes working MCP OAuth discovery data during a concurrent save.
You'll notice · MCP
What
Invalidating stored OAuth discovery data now bails out instead of clearing it when the stored entry has no authorization server metadata, which is the signature of another save writing just the URL at the same time. This prevents a race that could throw away working discovery state.
Details
Invalidating discovery no longer clears the step-up scope along with it.
MCPB archive errors truncate the offending file name #
Bad extension archives can no longer flood your terminal with a giant file name.
You'll notice · Plugins
What
Errors from validating an extension archive (unsafe path, oversized file) now show the entry name cut to 120 characters, so a hostile archive cannot flood your terminal with one enormous name.
Evidence
Unsafe file path detected:
Failed team mailbox writes are no longer treated as sent #
Messages to teammates that failed to write now return an error instead of a false success.
You'll notice · Team Messaging
What
Writing to a teammate's mailbox could fail while the caller reported success. Plan rejection now returns failure with a message saying nothing was sent, sending a message to a teammate returns the error write_failed, and permission forwarding emits a mailbox-write-failed degradation instead of an unconditional success event.
Evidence
Failed to write the plan rejection to
Pasted content that can no longer be loaded is kept as a placeholder #
Resuming a session keeps unavailable pastes as placeholders so surrounding text stays aligned.
You'll notice · Paste Handling
What
Resuming a session with pasted text or images no longer drops entries whose content is gone and rewrites the visible text around them. Each missing paste now becomes a placeholder record with empty content, marked unavailable, so the rest of the conversation still lines up.
Details
New paste ids are minted by a session-wide allocator that scans existing text and image paste references, including the stored image paste id list, so a restored session cannot reuse an id that is already taken.
Evidence
pastedContents
Mailbox write failures are reported instead of being assumed to succeed #
Plan submissions and shutdown requests to another agent now fail visibly when delivery fails.
You'll notice · Team Messaging
What
Writes to another agent's inbox can now fail visibly. Submitting a plan for lead approval throws a dedicated error when the write does not land, shutdown requests and shutdown rejections return a failure result naming the target, and the shutdown-approval confirmation is marked degraded. Previously all of these carried on as if the message had been delivered.
Evidence
Failed to write the plan approval request to the lead's inbox \u2014 plan not submitted; try again
The error for a relative memory path now suggests a properly joined path.
You'll notice · Memory
What
The refusal you get for passing a relative memory path now quotes a correctly joined suggested path instead of gluing a prefix onto it.
Details
Memory conflict errors now also carry the conflicting path.
Pre-creating the team-memory directory for team-scope stores was dropped from the load path.
Evidence
Memory paths are absolute and start with "/"
Flag-conflict error names the flag you actually used #
The cloud-session conflict error now blames --environment, the flag you actually typed.
--environment
You'll notice · CLI
What
When a self-hosted pool is selected, the cloud-session flag conflict error now blames --environment rather than --cloud, and drops the claude.ai/code reattach hint that did not apply.
Evidence
--environment
Teammate mailbox failures are reported instead of silently swallowed #
Claude is now told when a message to a teammate did not get delivered.
You'll notice · Team Messaging
What
When a write to a teammate's inbox fails, callers now check the result and tell the model the delivery did not happen, for example that a confirmation could not be written. Previously most of these call sites ignored the failure.
Details
The degraded-outcome path for a failed mailbox write went from one call site to nine.
Lock releases are wrapped so a failed release logs a warning instead of escaping the surrounding cleanup block.
Inbox write errors are now logged at error level and filtered before being surfaced.
Evidence
The confirmation could not be written to team-lead's inbox.
Bash mode no longer swallows pasted non-image content #
A !-prefixed line containing pasted text is no longer misfiled as a shell command.
!
You'll notice · Bash Mode
What
Typing a !-prefixed line that also contains pasted text is no longer recorded as a shell command, and the bash history no longer offers back entries whose pastes were not images. Pasted content that is unavailable is preserved rather than dropped.
Evidence
[Image
Transcript forwarding over the bridge no longer duplicates or stalls #
Forwarding your transcript to a connected editor no longer duplicates messages or stalls.
You'll notice · Editor Bridge
What
Messages forwarded to a connected SDK client are now tracked by message id in a set rather than by position alone, so nothing is sent twice, and a failure in one pass is logged instead of stopping forwarding. A conversation reset rewinds the offset, and reconnects that ask for no history backfill skip the replay.
Evidence
[bridge:sdk] transcript forward failed:
Proxy survives malformed requests and broken sockets #
The sandbox proxy no longer crashes on malformed requests or broken sockets.
You'll notice · Sandbox
What
The local sandbox proxy now attaches error handlers to client requests, responses and upstream responses, so a stream error is logged instead of crashing it. Malformed client requests get 431 Request Header Fields Too Large when headers overflow and 400 Bad Request otherwise, then the socket is destroyed after a one second timer that does not hold the process open.
Evidence
431 Request Header Fields Too Large
Plan temp files left by interrupted writes are now swept #
Leftover temp files from interrupted plan writes are now cleaned up by the retention sweep.
You'll notice · Plan Mode
What
The retention sweep that deletes old plans previously only matched files ending in .md, so a plan write interrupted partway through left a temp file behind forever. When invoked with a store handle it now also matches files containing .md.tmp..
Evidence
tengu_retention_sweep
Undelivered permission requests to a team lead now surface #
A permission request that never reached your team lead now tells you to retry.
You'll notice · Team Messaging
What
When a teammate's permission request cannot be written to the lead's mailbox, the failure was previously ignored and the request appeared to be in flight. The result is now awaited and a message tells you the mailbox write failed and to retry the tool call. Two call sites use slightly different wording, one of which adds "or ask the lead directly".
Evidence
The permission request could not be delivered to the team lead (mailbox write failed). Retry the tool call.
Running /clear no longer disconnects the editor bridge; it follows you onto the new session.
/clear
You'll notice · Editor Bridge
What
Clearing the conversation no longer tears down the REPL bridge. The bridge now repoints onto the new session, carrying its session id, last sequence number, dialog kinds and grouping id, and flags that history should not be backfilled.
Details
It also subscribes to reset, resume and spare-claim transitions.
Archiving the old session changed from an immediate call to a deferred, error-logged one that can be cancelled.
New telemetry records when the bridge disables itself automatically (tengu_bridge_repl_auto_disabled) and when a compaction happens while it is disabled.
Queued SDK events are forwarded with their own error logging rather than being lost silently.
Evidence
tengu_bridge_repl_auto_disabled
MCP stdio connections remember how the last child process ended #
Reconnects to a local MCP server now know whether the previous process exited or was killed.
Under the hood · MCP
What
When an MCP server started over stdio is torn down, Claude Code now records whether its process had already exited or was still running, and the reconnect path reads that back on the next automatic connect. This gives reconnection a view of whether the previous server died or was killed mid-flight.
Details
Keyed by a hash over the command, working directory, sorted environment and arguments, so each distinct server configuration gets its own record.
Recorded only if the transport had finished starting; the outcome is stored as "hard_closed" for an already-exited child or "survived" for a live one.
The entry is deleted once consumed. The map is capped and evicts oldest-first.
Evidence
hard_closed
Sandbox credential restrictions no longer lost when settings are merged #
Managed limits on which AWS credentials the sandbox may use survive settings merges now.
You'll notice · Sandbox
What
Restrictions on which AWS credential forms the sandbox may use now survive merging of managed settings into child settings, instead of being dropped at the merge boundary.
Details
Inheritance now carries the sandbox.credentials.sigv4 deny list, whose values are streaming, presigned and sigv4a.
A normalized awsPairs list of allowed AWS key pairs is carried through the same merge.
Restored input renumbers old paste markers so they can't point at the wrong attachment.
You'll notice · Paste Handling
What
When input is restored from history or a resumed conversation, pasted-content markers whose numbers clash with ones this session already issued are re-numbered, and the visible text is rewritten to match. An old paste marker can no longer point at the wrong attachment.
Details
Each session now tracks which paste ids it minted, which is what makes a collision detectable.
Evidence
allowCurrentEpochSkip
Plan approvals report mailbox write failures instead of claiming success #
Plan approvals sent to a teammate now report failure and retry instead of claiming success.
You'll notice · Team Messaging
What
Sending an approval to a teammate's inbox can fail, and callers now notice. The approve-plan path returns failure with a retry hint saying the teammate is still awaiting approval, the inbox poller logs the error and re-queues the request, and the sandbox permission sync records a mailbox write failure rather than a success.
Details
The write now returns the message id, or nothing on failure, which is what the three callers check.
Evidence
the teammate is still awaiting approval
Trailing slashes no longer change glob-permission warnings on Linux #
Trailing slashes in Read and Edit permission rules no longer change the wildcard warning on Linux.
You'll notice · Permissions
What
The check that warns about wildcard patterns in Read and Edit permission rules now strips trailing slashes from deny rules and absolute paths before looking for wildcards, so /foo/bar/ and /foo/bar behave the same. Allow and deny rules are walked as tagged pairs. Linux and WSL only; other platforms produce no warnings.
Evidence
Failed to get Linux glob pattern warnings:
Replayed sessions no longer show empty command output #
Replaying a stored session no longer shows blank assistant messages for empty command output.
You'll notice · Elsewhere
What
When a stored session is streamed back, a local command whose output is blank once trimmed now produces nothing instead of an empty assistant message. Compact summaries are also now treated as synthetic entries, matching how meta and transcript-only entries are handled.
Evidence
local_command
HTTPS proxy denials report why, and dead sockets are torn down #
Blocked proxy requests now report why, and dead connections are closed rather than written to.
Under the hood · Sandbox
What
When the proxy's request filter blocks a tunnelled request, it now reports the method, url, reason and the encoded command to the denial handler instead of failing quietly. Once the upstream connection resolves, the socket is destroyed if either end has already gone away, rather than continuing to write to a connection that no longer exists.
Evidence
onFilterRequestDeny
Status messages from nested sessions are passed up again #
Compaction status from a nested session is now shown in the session you are watching.
You'll notice · Compaction
What
A status message produced inside a nested session used to be dropped. It is now re-emitted to the outer session along with the permission mode and the result or error from compaction, so a compaction that happened deeper down is visible where you are.
Details
The compaction error is only attached when an internal check allows it, so it can be stripped before the message leaves the session.
Evidence
compact_result
Background settings poll no longer clobbers a login or logout #
Logging in or out mid-refresh no longer gets overwritten by stale background settings.
You'll notice · Settings
What
If you log in or out while a background remote-settings refresh is still running, that stale refresh no longer applies its result.
Evidence
Remote settings: Background poll superseded by a login/logout reset; not notifying
Mailbox write failures are logged instead of thrown away #
Failing to create another session's inbox directory is now logged rather than ignored.
Under the hood · Team Messaging
What
Sending a message to another session's mailbox now catches and logs a failure to create the inbox directory rather than failing silently.
Details
The failure is logged at error level and the write returns without proceeding.
Marking messages as read now releases its lock through a shared helper instead of inline unlock-and-log code.
Evidence
[TeammateMailbox] writeToMailbox: failed to ensure inbox dir:
Generic 5xx text from the peer service is now treated as retryable #
Server errors while listing peer sessions are recognised properly and treated as retryable.
You'll notice · Team Messaging
What
Errors while listing peer sessions were only recognised as server-side when formatted as "HTTP 5xx". Any message containing a 5xx status code now matches too, so these are correctly treated as not your fault and bucketed as a server error rather than surfacing as an actionable failure.
Evidence
bridge_http_5xx
Teammate spawn fails loudly instead of opening an idle pane #
Spawning a teammate now errors out instead of leaving an idle agent with no instructions.
You'll notice · Team Messaging
What
If the initial instructions cannot be written into a new teammate's inbox, the spawn now throws rather than launching an agent that would sit doing nothing, and records an error counter.
Evidence
subagent_teammate_prompt_write_failed
Refused cross-session messages are dropped before attachments are built #
Messages refused from another session are dropped before their attachments are fetched.
Under the hood · Team Messaging
What
Messages arriving from another session are checked against the peer and coordinator policy before their attachments are fetched and before they are queued, so a refused message is logged and skipped instead of being half-processed.
Evidence
bridge:repl: dropped before attachment materialization
Rate-limit headers from before a login change are discarded #
Rate-limit info from before you logged in or out can no longer overwrite fresh state.
You'll notice · Rate Limits
What
Rate-limit tracking now carries a version marker that increments when login state resets, so a response that was already in flight when you logged in or out cannot overwrite the fresh state. The reset also returns status to allowed and clears overage flags.
Evidence
anthropic-ratelimit-unified-grace-status
Editor bridge waits for a pending conversation reset #
The editor bridge pauses writing until a queued conversation reset actually lands.
Under the hood · Editor Bridge
What
When a conversation reset is still queued and undelivered, the bridge now stops writing messages and stops forwarding queued events until it lands, instead of writing into a conversation that is about to be cleared. If the process shuts down with a reset still undelivered, that is logged with an undelivered_at_teardown outcome and bridge state is torn down.
Evidence
undelivered_at_teardown
Pasted images in the question dialog no longer collide with other pastes #
Images pasted into a question prompt no longer collide with pastes made elsewhere.
You'll notice · Paste Handling
What
Images pasted into an AskUserQuestion prompt were numbered from a counter local to that dialog, starting at 1, so their ids could clash with pastes made elsewhere in the same session. They are now allocated from the session-wide paste id pool, seeded with the ids already attached to that question.
Details
Text being typed into the question's inputs is registered as another source of in-use ids while the dialog is open.
Auto-advance when you are away, and skip/accept telemetry, are unchanged.
Evidence
ask-user-question-text-input
In Development
26 items
Memory prompts can describe connected memory stores #
Memory prompts now describe each connected store and its index by name instead of mount paths.
You'll notice · Memory
What
When memory stores are connected, the automatic memory prompt now builds a per-store view describing each index as a memory index inside a named store, including read-only ones, instead of the older team-mount path phrasing. Without connected stores it falls back to the previous prompt.
Details
A separate memory-tools prompt variant exists, reported in telemetry as memory_tools.
Prompt-load telemetry now carries how many stores are connected, whether an index loaded, whether the tools are writable, and which prompt variant was used.
Evidence
memory_tools
Incoming peer messages get their own transcript rendering #
Messages from another session render as an @sender header with indented body instead of raw tags.
CLAUDE_CODE_HARBOR_KITE
Not switched on · Cross-Session Messaging
What
A message sent from another session is displayed as an "@ sender" header with the body indented below, instead of the raw wrapper tag. Only reachable when cross-session messaging is enabled (tengu_harbor_kite gate or CLAUDE_CODE_HARBOR_KITE).
Details
The renderer strips the <cross-session-message ...> wrapper and reads the sender from its from= and from-name= attributes.
Sender addresses are humanised: a uds: address becomes the socket file's basename with .sock removed, a bridge: address becomes "(untitled)", and anything unresolved shows as "peer".
Evidence
</cross-session-message>
MCP OAuth checks the issuer a server echoes back, telemetry only for now #
MCP OAuth now checks a server's echoed issuer, but only records mismatches rather than blocking.
Under the hood · MCP
What
During MCP OAuth discovery Claude Code now validates itself that the issuer a server echoes back matches the URL that was asked for, at three points: the RFC 9728 chain, the legacy path fallback and refresh rediscovery. Controlled by tengu_mcp_issuer_strict_echo, whose in-source fallback is "observe": mismatches are recorded and the connection proceeds. Only a remote config value switches it to enforce, where a cross-origin echo fails the connection.
Details
The SDK's own checks are turned off (skipIssuerMetadataValidation, skipIssuerValidation) in favour of the in-house comparison, on SSE and HTTP transports.
Mismatches emit tengu_mcp_oauth_issuer_echo_mismatch with site, mode, outcome, an origin relation of same_origin, cross_origin or unparseable, the differing parts (scheme, host, port, path, query, fragment, userinfo, normalization_only) and hashed issuers.
In enforce mode the failure raises IssuerEchoCrossOriginError, surfaces as a new issuer_echo_denied outcome for token refresh and revoke, and is excluded from retry.
Automatic memory context can scan a whole memory directory #
Memory context can list every file in your memory directory instead of one file.
CLAUDE_CODE_REMOTE
Not switched on · Memory
What
A new loader builds an automatic memory context block listing every memory file under the user memory directory, with paths relative to it and flagged as differing from disk, alongside the existing single-file version. It returns nothing when CLAUDE_CODE_REMOTE is set or the session is a cowork one; which of the two is used is decided by those same environment checks.
Status text for an oversized workflow exists, pointing at /workflows to stop it.
/workflows
Not switched on · Workflows
What
Status strings for a large workflow are added, built from a prefix constant plus fixed text, with the longer form pointing at /workflows to stop it. Nothing in this group shows when it is displayed.
Evidence
Large workflow
Server-supplied CLI arguments are validated on self-hosted runners #
Self-hosted runners now reject malformed or blocklisted CLI arguments handed down by the server.
Under the hood · Self-Hosted Runners
What
Arguments the server hands to a self-hosted runner session are now checked against a name pattern and a blocklist before becoming CLI flags. Rejected ones are skipped and logged as "malformed" or "blocked", and the count of arguments actually applied is logged.
Details
Values starting with - are passed as --name=value so they are not parsed as a separate flag.
Log lines are assembled from a template beginning "[runner:session] Skipping ".
Evidence
[runner:session] Skipping
MCP servers checked for the issuer they echo back #
Claude checks whether an MCP server points authentication elsewhere, logging mismatches without blocking.
You'll notice · MCP
What
When connecting to an MCP server over OAuth, Claude now compares the authorization-server address it asked about against the issuer value the server returns in its discovery metadata, catching a server that points authentication somewhere else. In this build the check only records telemetry: the gate tengu_mcp_issuer_strict_echo decides the mode and its in-source fallback is false, so absent a remote value the result is observe-only.
Details
In observe mode a mismatch is logged with outcome proceeded and the connection continues.
In enforce mode the connection raises an issuer echo cross-origin error and authentication fails with reason issuer_echo_denied.
Mismatches are classified before reporting, including same_origin and unparseable plus a reason per differing part of the URL.
None of this exists in 2.1.223; the whole check is new.
Evidence
tengu_mcp_oauth_issuer_echo_mismatch
Memory extraction can be told to save only personal memories #
Memory extraction can be told to save only personal memories, with nothing visibly setting that mode.
Not switched on · Memory
What
The memory-extraction prompt has a new mode that tells the model the project-shared memory tools are unavailable and that only personal-directory memories should be saved. It is switched by a flag passed in by the caller, and nothing in this build shows what sets that flag.
Details
Related team-memory prompts dropped the branch saying a private directory would still persist.
The memory upkeep prompt can now skip its "Read the index" step.
Evidence
so skip anything the scope guidance marks as shared with the project
Code review and post-commit tips can point you at a deeper cloud review, off by default.
/ultrareview
Not switched on · Code Review
What
Code review can append a line suggesting /ultrareview for a deeper cloud-based review, with a matching post-commit tip and a count of free reviews in the slash menu. Nothing shows without remote configuration: the tengu_ultrareview_awareness flag defaults to nothing, which is read as no surfaces enabled. It also requires the remote-sessions entitlement.
Details
Skipped for skill preloads and model-scheduled runs, and suppressed once you have run /ultrareview yourself.
Each surface is capped at a few impressions; impressions are reported as tengu_ultrareview_awareness_shown.
Evidence
Tip: For a deeper cloud-based review, try /ultrareview next time
Two shortcut lists have a hole where a conditional keybinding was compiled out.
Under the hood · Terminal UI
What
The chat keybinding map, between the cycle-mode and image-paste bindings, and the confirm-dialog shortcut list each contain an empty placeholder where a conditional entry was removed at build time. Whatever shortcut belongs there does not exist in this build.
Evidence
chat:imagePaste
Two new remote-config gates for bridge event forwarding #
Two new server-controlled switches govern whether reset and rate-limit events get forwarded.
Under the hood · Remote Bridge
What
Two new flags, tengu_luminous_seal and tengu_composed_quail, each falling back to on in this build. The first decides whether conversation reset events are emitted and forwarded and whether they survive the task-event filter; the second decides whether rate limit events are forwarded. Nothing in the build sets either one, so the real values come from server config.
Evidence
tengu_luminous_seal
Progress and failure messages for cloud file seeding #
Cloud file uploads show progress and a clear outcome, falling back to the git bundle on failure.
container_sync
Not switched on · Cloud Sessions
What
While a cloud session uploads the files it starts from, you see a progress line built from how many uploads have settled out of the total. On finish you get one of four outcomes: a summary, a timeout note, an unavailable note, or a could-not-finish note. Each of the failure cases ends by saying the session starts from the git bundle alone. This only appears on the container-sync file path behind tengu_violin_wood.
Evidence
Cloud file sync is unavailable for this session; starting from the git bundle alone
Memory store listing gains each store's index path #
Listing memory stores can also report each store's index document path.
Not switched on · Memory
What
Listing memory stores previously returned each store's id, description and whether it is writable. It now also returns the path of that store's index document, the pointer file the model is asked to keep current with one-line entries. Behind the tengu_haze_glass gate, which is false in this build.
Evidence
whether each is writable or read-only, and the path of each store's index document
SDK and stream-json startup output can report the messaging socket path when the inbox is running.
messaging_socket_path
Not switched on · Cross-Session Messaging
What
The system/init message sent to SDK and stream-json consumers now carries messaging_socket_path, read from the running cross-session messaging module rather than from the environment. It is only set when that messaging inbox started, which is itself gated off by default.
Evidence
messaging_socket_path
Socket peers are identified by pid, start time and ancestor chain on Linux #
On Linux, incoming session messages can be traced to the sending process and its ancestors.
Under the hood · Cross-Session Messaging
What
Incoming connections on the cross-session messaging socket can now be attributed to the process tree that sent them. New helpers read /proc/<pid>/stat for the process start time, used as a liveness token, and walk up to 12 ancestor pids; the pid and chain are captured once per connection and passed into message handling.
Details
The /proc paths are assembled at runtime, so on non-Linux the reads simply fail and the values come back undefined.
Connection handling sits inside the cross-session messaging path, which is off by default.
Evidence
[peer-cred] peer pid unavailable (fd=
Loop file can come from stored state instead of disk #
Your loop.md can come from stored state when a storage handle is available, otherwise from disk.
loop.md
Under the hood · Internals
What
The lookup for loop.md gained an async variant that, after checking .claude/loop.md in the config directory, falls back to a stored loop-file value, trimmed and ignored if empty. The stored path only runs when a storage handle is passed in; otherwise the plain file lookup is used.
Evidence
loop.md
Second LSP tool schema, one strict shape per operation #
The language-server tool gained a per-operation schema, but nothing chooses it over the old one.
Under the hood · LSP Tools
What
A new schema for the language-server tool splits it into a separate strict object per operation (goToDefinition, findReferences, hover, documentSymbol, workspaceSymbol, goToImplementation, prepareCallHierarchy, incomingCalls, outgoingCalls), each with its own field descriptions, so arguments are validated per operation instead of against one flat shape. The old flat schema is still in the build and nothing in this group decides which one the tool presents.
Details
The workspaceSymbol variant drops the "(workspaceSymbol only)" qualifier from its query description, since the field now exists only there.
Evidence
The symbol name or partial name to search for. Most language servers return no results for an empty query.
Scheduled tasks can resolve loop.md defaults asynchronously #
Scheduled tasks resolve loop.md content asynchronously and skip a fire rather than run unresolved.
loop.md
Under the hood · Scheduled Tasks
What
When a storage store is available, the scheduled-task fire path queues fires one after another and awaits an asynchronous resolution of loop.md default content. If that resolution fails, the fire is logged and skipped rather than running with unresolved content. Without a store, the existing synchronous resolution runs.
Details
The skip is logged with the prefix "[ScheduledTasks] loop.md v5 expansion failed; fire skipped: " followed by the error.
Evidence
[ScheduledTasks] loop.md v5 expansion failed; fire skipped:
Remote bridge sessions are described as reply-only and unreachable by name.
CLAUDE_CODE_HARBOR_KITE
Not switched on · Cross-Session Messaging
What
The tool that lists other agent sessions now describes remote bridge sessions as ones you can only reply to, and states that no connector can reach them by name. This wording is only reachable when the cross-session feature is on, via the tengu_harbor_kite server flag or CLAUDE_CODE_HARBOR_KITE.
A startup tip suggests cloud branch review and shows how many free reviews you have left.
/ultrareview
You'll notice · Code Review
What
A new startup tip suggests the cloud multi-agent branch review and appends your remaining free-review count when it is known. It shows at most once every 8 sessions and is skipped once you have run ultrareview.
Details
Requires ultrareview eligibility and the allow_remote_sessions capability.
Per-surface visibility comes from the tengu_ultrareview_awareness gate, whose fallback is empty, leaving the tip off unless a value is supplied remotely.
Evidence
for a cloud-based multi-agent review that finds and verifies bugs in your branch
Cross-session messaging explains why it is unavailable #
Messaging another session now tells you why it failed instead of silently doing nothing.
CLAUDE_CODE_HARBOR_KITE
Not switched on · Cross-Session Messaging
What
Sending a message to another session now returns a specific reason instead of quietly failing: one refusal when the feature is off in this session, another when a cross-machine send would have to route through Anthropic servers. Cross-session messaging is gated on tengu_harbor_kite (off by default) or the CLAUDE_CODE_HARBOR_KITE environment variable, and is off entirely on Windows.
Details
The cross-machine route additionally requires a first-party provider and that nonessential traffic is not disabled; failing either gives the second refusal.
Evidence
Cross-session messaging is not available in this session.
Memory consolidation prompts gained prune-only and tools-unavailable variants for different session types.
CLAUDE_CODE_REMOTE
Under the hood · Memory
What
The prompt used for memory consolidation runs picked up two options. One replaces the index-maintenance step with a pure prune step and drops the instruction to read the index file. The other adds a note that the memory tools are not available during the run, so it should only touch the memory directory. The second is requested only when the session is not running under CLAUDE_CODE_REMOTE.
Details
Which variant is used is decided at runtime by the caller; the underlying feature is otherwise unchanged.
Evidence
# Dream: Memory Consolidation
New artifact login messages are defined but not yet shown #
Three clearer artifact login messages are written but never displayed; you still see the old one.
Not switched on · Artifacts
What
Three replacement messages explaining why artifacts need a claude.ai login are defined, covering the plain case, a remote session authenticating through the machine that launched it, and a credential injected by the host environment that takes precedence and cannot be changed. Only the definitions and the module export table appear in this build, with no call site, so the old single message is still what you see.
Details
A fourth builder interpolates the name of the competing credential source into the message.
Evidence
Artifacts need a claude.ai login, but this session authenticates with a credential injected by its host environment, which takes precedence and cannot be changed here. Start a session that is signed in to claude.ai to publish or read artifacts.
AskUserQuestion dialog fallback cannot fire in this build #
A fallback to the question dialog when auto-classification is unavailable can never fire here.
CLAUDE_CODE_AUTO_MODE_CLASSIFY_ASK_USER_QUESTION
Not switched on · Auto Mode
What
New code lets a question fall back to the interactive dialog when the auto-mode classifier is unavailable or the conversation is too long for it, instead of failing. The condition negates a helper that always returns true here, so the branch is unreachable as shipped.
Details
the separate classifier switch remains, readable from CLAUDE_CODE_AUTO_MODE_CLASSIFY_ASK_USER_QUESTION or the classifyAskUserQuestion field of the auto mode config
Evidence
Auto mode classifier transcript too long for AskUserQuestion, falling back to the question dialog
Remote file store gains create preconditions and cancellation #
Remote file creates can refuse to overwrite an existing file and both calls accept cancellation.
Under the hood · Remote File Store
What
The remote file store's create call takes an options argument that can attach a not_exists precondition, so a create fails rather than overwriting, and both create and update now accept an abort signal. Nothing observed in this build requests the precondition, so whether any caller uses it is not settled here.
Evidence
"not_exists"
Directory sync can apply a file seed and record the result #
A directory can be seeded with a listed set of files, skipping anything already there.
Not switched on · Cloud Sessions
What
New logic waits for a list of files to seed into a directory, creates each one under a destination whose real path is checked, and then records a summary of what happened. It only creates files: anything already present is skipped and anything escaping the destination path is rejected. Nothing in this build was observed turning it on.
Details
Polls for the file list, applies mode bits to each created file, and writes a ready record counting files applied, skipped and missing.
Outcomes are reported as complete, timeout, or bad_manifest when the file list is malformed, each with a matching telemetry event.
Evidence
tengu_dir_sync_apply_start
Internal Changes
66 items
Memory store descriptors gain visibility and prompt-index fields #
Memory store records can now carry a visibility setting and a prompt index path.
Under the hood · Memory
What
The schema describing a memory store now carries a path, a read-write or read-only mode, a kind and a grouping id, plus optional visibility and prompt-index fields bounded to 64 and 512 characters. Both new fields fall back to undefined on bad input, so a malformed value degrades instead of failing the whole parse.
Evidence
grouping_id
PDF page extraction and several caches read through the storage layer #
PDF page images and several caches now read through a shared storage layer instead of raw files.
Under the hood · Internals
What
Extracted PDF page images are now listed and read back through the shared storage abstraction rather than direct filesystem calls, with a guard that fails if the extraction directory sits outside the session's tool-results store. Model-capability caches and the closed-issues cache gained the same storage-backed paths; all of them fall back to the previous filesystem path when no storage handle is supplied.
Evidence
PDF extraction directory is outside the session tool-results store
MCP telemetry identifies servers by a hash, not the base URL #
MCP telemetry identifies servers by a hash rather than their raw URL.
Under the hood · MCP
What
The helper that tagged MCP events with a server's base URL was replaced, in both of its copies, by one that also carries a hashed server key. Server identity in telemetry no longer depends on the raw URL.
Details
The hash is attached to tengu_mcp_listen_reopen events and is the preferred key for per-server rate limiting when forwarding logs, with the base URL used only as a fallback.
Evidence
mcpServerKeyHash
MCP client version mismatch now reports before it throws #
An MCP client version mismatch now reports the two versions before raising its error.
Under the hood · MCP
What
When the MCP runtime resolves to one client generation but the loaded module is from the other, a once-per-process tengu_mcp_tripwire event is emitted, carrying the expected and loaded generations (normalised to v1, v2 or other), immediately before the existing error is raised. The event name was added to the allow-listed list.
The rules that neutralise control tags in subagent output are now shared with a new assistant-output scanner.
Under the hood · Permissions
What
The rules that neutralize control tags and permission-escalation phrasing in subagent output are now one shared list, reused with fresh pattern copies by a new scanner for assistant output. Subagent behaviour is unchanged.
Details
The escalation set covers settings JSON, bypassPermissions, --dangerously-skip-permissions and permission allow/deny phrasing.
Evidence
escalation-pattern
Remote-control registration reports a bridge epoch #
Remote control registration and heartbeats now include an identifier for the current bridge lifetime.
Under the hood · Remote Control
What
Registration and heartbeat payloads sent by the remote-control bridge now include a bridge_epoch value identifying the current bridge lifetime.
Details
The special case that pushed thinking_tokens system messages straight into the bridge SDK stream, along with its dedicated error log, was removed; those messages now go through the normal enqueue path.
Tool schemas were mechanically shortened with no change to descriptions or constraints.
Under the hood · Build
What
Tool input and output schemas across the product were mechanically converted to shorter schema helper calls. Descriptions and constraints are unchanged and no behaviour differs.
Evidence
Processed result from applying the prompt to the content
Bridge close codes distinguish auth failure from recoverable stalls #
Remote bridge disconnects now use distinct close codes for session problems versus expired tokens.
Under the hood · Remote Control
What
When the remote-control connection hits a terminal request-path condition, the close code now reflects the cause: session or epoch problems close with 4090, expired or exhausted tokens with 4094.
Details
Both places that build the client opt into typed close codes, so the mapping is what runs; the untyped path still closes with 4090 for everything.
Dozens of tool schemas were rewritten onto shared helpers purely to shrink the bundle.
Under the hood · Build
What
Dozens of tool input and output schemas were rewritten to use short shared schema helpers. Descriptions and validation look unchanged; this is a size and consistency refactor.
Evidence
project_search: knowledge-base query
Tool-search telemetry records the real mode and a finer skip reason #
Skipped tool-search events now report the real mode in effect and a more precise skip reason.
ENABLE_TOOL_SEARCH
Under the hood · Tool Search
What
When tool search is skipped, the event now reports the mode actually in effect, derived from the ENABLE_TOOL_SEARCH environment variable and one of tst, tst-auto or standard, rather than always reporting standard. It also tells apart a request with no tools from one where the search tool is not registered.
Skill frontmatter and several other schemas now import validation helpers directly; nothing changed.
Under the hood · Build
What
Tool input schemas, skill frontmatter, the Chrome install dialog and GitHub session schemas were rewritten to import validation helpers directly instead of through a namespace. No behaviour or message changed.
Evidence
Unsupported schema:
Workshop document writes counted apart from scratchpad writes #
Session metrics count workshop document edits separately from scratchpad edits.
Under the hood · Artifacts
What
Session metrics now count workshop document writes and their added and removed lines separately, reported only when non-zero.
Details
Plan-mode end-of-turn guidance now takes the publish wording from its caller rather than using a fixed string.
Conflict responses now read their cause from a header, distinguishing a live worker from a stale registration.
Under the hood · Remote Control
What
Conflict responses are now attributed from an x-ccr-conflict-reason header, falling back to parsing the reason out of the JSON body, which separates being superseded by a live worker from a stale registration with no successor.
Plugin manifest loading now reports whether the file was unreadable, invalid JSON or the wrong shape.
Under the hood · Plugins
What
Loading a plugin manifest now reports success, and reports failures separately for an unreadable file, invalid JSON and a manifest that does not match the expected shape. Success is not reported when the caller is only probing for a manifest.
Evidence
plugin_load_manifest_schema_invalid
Settings validation knows which file it is checking #
Settings warnings can now name which settings file caused them.
Under the hood · Settings
What
The settings validator is now given the file path as well as the warning collector, so warnings can name the settings file they came from.
Auto-mode approval events now note whether the tool came from an MCP server.
Under the hood · Permissions
What
Two auto-mode events, subsequent approval and malformed tool input, now record whether the tool came from an MCP server, defaulting to false when the tool does not say. The malformed-input event also runs the tool name through the sanitiser.
Evidence
tengu_auto_mode_malformed_tool_input
All schema definitions rewritten to a smaller builder style #
Every schema in the bundle moved to standalone builder functions to cut size.
Under the hood · Build
What
Every schema in the bundle, covering tool inputs and outputs, plugin manifests, settings, memory and artifacts, was rewritten from the namespaced schema builders to standalone functions. Field names, descriptions and validation behave the same; this is a bundle-size change.
Details
The previous build has 1486 uses of the namespaced string builder and 569 of the namespaced object builder; this build has none of either, with roughly 963 direct object builder call sites.
Example: a hook type that was a namespaced literal with the description "MCP tool hook type" is now a bare literal call, and its server field a bare string call described as the name of an already-configured MCP server to invoke.
The error instance check switched to the corresponding direct class. Several hunks in this group are only the resulting reformatting.
Evidence
w.object(, MCP tool hook type
Tool and config schemas rebuilt on internal builders #
More tool and config schemas moved onto internal builders with identical shapes.
Under the hood · Build
What
Dozens of schema definitions were rewritten from the bundled validation library's object API onto short internal builders. Shapes and descriptions are unchanged, so nothing behaves differently.
Descriptions are byte-identical, for example the MCP refresh tool's field still reads "Optional server name: refresh only this server. Omit to refresh all connected servers."
Evidence
Optional server name: refresh only this server. Omit to refresh all connected servers.
MCP connection failures report a sibling probe result #
Failed MCP connections now report an extra probe result for easier diagnosis.
Under the hood · MCP
What
The telemetry event for a failed MCP server connection carries one more field describing the probe, giving more detail when a server will not connect.
Details
probeSibling joins the existing negotiationMode, probeFellBack, errorCode and errorClassName fields.
The field name does not appear in the previous build.
Evidence
probeSibling
Git credentials are supplied by an inline helper instead of a script #
Remote git operations no longer write a credential helper script to disk, passing an inline function instead.
Under the hood · Git
What
Remote and cloud git operations no longer write a helper script to disk. They pass an inline shell function on the command line that emits a fixed username and reads the password from a named environment variable, after clearing any existing credential helper for the remote.
Evidence
printf 'username=unused
Remote Control startup source labels moved to a lookup table #
Labels for where the remote-control startup setting came from now live in one table.
remoteControlAtStartup
Under the hood · Remote Control
What
The short names reported for where the remoteControlAtStartup setting came from (policy, flag, user) now come from one table instead of scattered strings. The warning that repository-scoped settings cannot enable Remote Control is unchanged.
Evidence
policySettings: "policy"
Schema construction moved off a shared namespace #
All 686 namespaced schema calls became direct helpers, which explains most of this release's diff.
Under the hood · Build
What
All 686 namespaced schema calls were replaced with direct helper functions. Behaviour is unchanged, but it accounts for the very large number of one-line schema diffs in this release.
Evidence
w.custom(
Auto-mode telemetry records whether the tool was MCP #
More auto-mode permission events record whether the tool was from an MCP server.
Under the hood · Permissions
What
Auto-mode decision, fallback-to-ask and denial-limit events now carry a flag saying whether the tool came from an MCP server, defaulting to false, alongside the existing tool name and denial counts.
Runner session tokens are written to per-epoch files instead of one shared file.
Under the hood · Runners
What
The runner now writes its session ingress token to a file named with an epoch suffix instead of one shared file. The write is best effort, and a failure logs that staged-file fetches are degraded.
Evidence
.session_ingress_token.e
Settings presence checks can read through the newer settings store #
Checks for explicitly set settings keys can now read from the newer settings store.
cleanupPeriodDays
Under the hood · Settings
What
The check for whether a key such as cleanupPeriodDays is written explicitly in a settings file is now asynchronous and can be given a reader, in which case user settings come from the newer store instead of the file on disk. A read failure is logged and treated as unknown rather than as absent, and the retention cleanup gate became async to match.
MCP clients now recognise a new denied-issuer-echo error code.
Under the hood · MCP
What
ISSUER_ECHO_DENIED was added to the recognised error codes of both MCP client generations, alongside the existing rejected-auth-header and rejected-bearer codes.
Evidence
ISSUER_ECHO_DENIED
Concurrent-session pid file can go through the v5 store #
Session registration can write its process-id file through the newer store when one is available.
Under the hood · Internals
What
When a storage handle is supplied, session registration writes its process-id file through that store and throws on failure; without one it falls back to writing the file directly to disk as before.
SDK message and control-protocol schemas were restructured with no change to fields or defaults.
Under the hood · Elsewhere
What
The message, hook payload and control protocol schemas are now built from directly bound helpers rather than one shared namespace object. Field names, defaults, optionality and descriptions are unchanged.
Evidence
Controls Claude's thinking/reasoning behavior. When set, takes precedence over the deprecated maxThinkingTokens.
SendMessage records why a message was not delivered #
Undelivered agent messages now record why, such as an unreachable recipient or a failed mailbox write.
Under the hood · Agents
What
The tool that sends messages between agents now reports a delivery outcome to telemetry instead of failing silently, using not_reachable when the recipient is not in the roster or cannot be resolved and mailbox_write_failed when the write itself fails.
The memory prompt no longer asks Claude to narrate a save-or-not verdict before acting.
You'll notice · Memory
What
The prompt behind persistent memory no longer asks the model to state a save or no-save verdict to itself before acting. The requirement to save in the same reply is unchanged.
Evidence
did the user's latest message teach you a durable, applicable lesson?
MCP telemetry is rate limited and tool names bucketed #
MCP telemetry now drops events past a rate limit and reports how many were dropped.
Under the hood · MCP
What
Forwarded events for MCP-style tools now pass through a sliding window per event and server; over the limit, events are dropped and counted, and the next event that gets through reports how many were dropped since the last one.
Details
The window map is size-bounded and evicts its oldest key.
Any tool name beginning skill__ is reported as "skill", and feature names starting tool_skill_ collapse to "tool_skill", except tool_skill_tool.
A denylist of fields is stripped from every payload before it is sent.
Evidence
droppedSinceLastForward
Schemas across the binary rewritten onto internal builders #
Nearly every schema was rewritten onto smaller internal builders with no change in behaviour.
Under the hood · Build
What
Nearly every declared schema in the build, covering tools, hooks, settings, MCP config and message envelopes, plugin manifests, browser listings, LSP operations and sandbox settings, was rewritten from the zod-style object/string/enum/array/union/discriminatedUnion/preprocess/strictObject calls onto compact internal equivalents. Field names, description text and validation messages are unchanged, so validated shapes and error output stay the same.
Details
Some explicit unions became a helper call, and strict objects moved to a strict-object helper.
The MCP v1/v2 module tripwire is untouched by the rewrite.
Evidence
protocol must be an RFC 6455 token, url contains control characters that would be hidden in the approval dialog
MCP events forwarded to Datadog, with identifying fields removed and a per-server cap #
MCP events are forwarded for logging with identifying fields stripped, and skipped entirely if analytics are off.
Under the hood · Telemetry
What
MCP events are now admitted to log forwarding, and every payload has its identifying fields deleted before send. Forwarding is skipped entirely when analytics are disabled.
Stripped fields include the server name, base URL, hashed server key, attribution hashes, hashed error details and a server digest.
Five of the MCP events are capped per event-and-server pair at 10 per 60 seconds, tracked over at most 200 keys; the number of suppressed events rides along on the next one that gets through as droppedSinceLastForward.
Evidence
PEER_RATE_BOUND_EVENTS
Schema definitions rewritten to use direct helper calls #
Schema definitions now call validation helpers directly; nothing behaves differently.
Under the hood · Build
What
Most schema definitions were mechanically switched from a namespaced validation object to directly imported helpers, and several initialiser blocks were relocated intact. Validation messages, limits and defaults are unchanged, so nothing is visible from the outside.
Evidence
segments must match [A-Za-z0-9._-]+ and must not be . or ..
REPL bridge failures record whether they were an auth problem #
Bridge failures are now labelled as authentication or terminal, though nothing reads the label yet.
Under the hood · Remote Control
What
Bridge failures are now tagged as either an authentication problem or a terminal one, alongside the existing error. Missing OAuth token, missing organization and unenrolled trusted device count as auth; everything else defaults to terminal. Nothing user-visible changes yet.
Changelog, model and issue caches now read from a keyed storage backend when one exists.
Under the hood · Internals
What
Caches for the closed-issues list, model capabilities, gateway models and the changelog now look themselves up by a namespaced key and read from a storage backend when one is available, falling back to the previous plain-file reader when it is not.
Details
Whether the backend path or the file path runs is decided by whether a backend is present at runtime.
Failures coming from the backend are now reported distinctly from unexpected errors.
The version is now 2.1.224 everywhere it is printed.
Under the hood · Internals
What
The embedded version is now 2.1.224, with a new build time and git SHA, updated everywhere they are printed: version output, user agents, update messages, feedback bundles, the daemon start log and version warning, and the control-protocol binary version response.
Checking whether a session has history is faster because it scans raw bytes instead of decoding everything.
You'll notice · Sessions
What
Deciding whether a stored session has any history now scans raw record bytes for the user and assistant type markers instead of decoding every record to text, and pages more aggressively: 64KB for the first page, 4MB for later ones.
Details
The filesystem transcript locator gained an optional store backend, so it can also find transcripts held in a session store rather than only on disk.
Remote bridge socket closes now record a cause alongside the numeric code.
Under the hood · Remote Control
What
The close event for the v2 remote bridge transport now carries a cause alongside the numeric close code, and the deferred-close path stores both.
Evidence
tengu_bridge_repl_ws_closed
Remote settings responses carry the identity that fetched them #
Recorded consent is now attributed to the identity that actually fetched the remote settings.
Under the hood · Settings
What
The remote settings fetcher now returns the identity used for the request on every path, including a cached 304, an empty 204 or 404, a parsed settings body and the caught-404 fallback. The caller hands it to the consent-recording step, so a recorded consent is attributed to the identity that actually fetched the settings.
Evidence
consentIdentity
Telemetry for how remote-control autostart was decided #
Whether remote control auto-started, and why, is now recorded.
Under the hood · Remote Control
What
The autostart decision now reports both its value and where the value came from, so the reason a session did or did not start in remote-control mode is recorded.
Details
The event records the explicit setting and its source, the default and its source, plus mirror, reattach and the resolved result of off, mirror or full.
The default still comes from the tengu_cobalt_harbor flag, which is off unless remote config says otherwise.
One of the possible sources, a persistent remote session, cannot be reached: the check that would select it always returns false in this build.
Removing messages from conversation history is now a plain drop-and-append with no boundary trimming.
Under the hood · Compaction
What
The operation that removed messages from conversation history was replaced with one that simply drops the named messages and appends, without the earlier filtering and trim-to-boundary step.
Background worker exits now carry a typed reason such as expired token or epoch conflict.
Under the hood · Remote Control
What
Fatal exits now pass a reason such as session not found, token expired, auth exhausted, or an epoch conflict or stale epoch, instead of terminating with no explanation.
Details
The remote bridge maps auth-related reasons to WebSocket close code 4094 and the rest to 4090, so recovery can pick the right path.
Evidence
causeTypedCloseCodes
Linux sandbox mount computation reworked around symlinks #
Linux sandbox write paths now match both literal and resolved forms, so symlinked directories behave consistently.
You'll notice · Sandbox
What
On Linux, sandbox write paths have trailing slashes stripped before binding, with a bare / preserved, and allowed write paths are matched against both their literal and fully resolved forms so symlinked directories are shadowed consistently.
Details
Applies to the bubblewrap sandbox only.
The path lists, including directories considered for read-denial, are now computed on demand rather than upfront.
Settings warnings now wait for retention config before deciding whether to warn about paused cleanup.
Under the hood · Settings
What
Collecting settings-file warnings now waits for the retention configuration to be determined before deciding whether to show the notice that transcript retention cleanup is paused.
Evidence
Transcript retention cleanup is paused until the settings errors above are fixed
Schema declarations rewritten to shorter helpers #
Schema declarations across the bundle were shortened with no change to accepted values.
Under the hood · Build
What
Schema definitions across the bundle were rewritten from long-form builders to compact helpers, covering tool inputs and outputs, dialog payloads, plugin manifests, scheduled job arguments, todo lists and lock files. Field names, descriptions and accepted values are unchanged.
Evidence
Job ID returned by CronCreate.
SendMessage telemetry marks blocked waits and resumes #
Message delivery telemetry can flag when the sender blocked waiting for completion.
Under the hood · Agents
What
Message delivery telemetry can now flag that the caller waited synchronously for completion, alongside the existing route and duration fields.
Details
Agent-resume branches report on both success and failure under the route resume.
The evicted-agent mailbox path sets the blocked-wait flag.
Evidence
blocked_wait
Plans and session records read through the keyed store #
Plans and session records are now addressable through the keyed storage layer, not just as files.
Under the hood · Internals
What
Plans and session files are now addressable through Claude Code's keyed storage layer rather than only as raw files on disk.
Details
Two namespaces were registered, plan (keyed by name) and session (keyed by file), both classified as plain.
Priming plan slug collisions lists entries from the store, but only when a store handle is passed and the plans directory is the default one; otherwise it still reads the directory directly, and it also falls back to that on a store error logged as "primePlanSlugCollisions: v5 list failed: ".
The old raw-file reader for plan workshop documents was deleted.
Evidence
primePlanSlugCollisions: v5 list failed:
Grading results record whether a criterion was scored #
Evaluation grader output now says explicitly whether each criterion was scored.
Under the hood · Elsewhere
What
Evaluation grader output now carries an explicit flag for whether each criterion was actually scored, derived as the negation of the existing "with only" flag.
Details
The result schema gains an optional boolean scored alongside withOnly, judgeVotes and evidence.
Child processes can have their output redirected, so Wayland clipboard writes stop spewing output.
Under the hood · Elsewhere
What
The shared helper for running child processes now forwards stdout and stderr options, used for example to ignore output from Wayland clipboard writes.
Details
These join the existing maxBuffer and stripFinalNewline passthroughs.
Evidence
stripFinalNewline
Mailbox lock-release failures name the operation #
Failed mailbox lock releases now name which maintenance job failed.
Under the hood · Agents
What
Two mailbox maintenance paths now release their lock through a shared helper that takes an operation name, so a failed release is attributed to the specific job, such as pruning invalid entries or marking messages read.
Startup no longer waits on org memory discovery; the wait depends only on your configured memory stores.
CLAUDE_MEMORY_STORES
You'll notice · Memory
What
The startup wait for a first memory store pull used to also trigger when org-memory discovery marked stores as pending. That latch and its setter were removed, so the wait now depends only on whether CLAUDE_MEMORY_STORES is set.
Pasted image numbering comes from a counter instead of rescanning your whole conversation.
Under the hood · Input
What
The code that worked out the next pasted-image ID by scanning every user message for the highest one is gone; the UI is handed the last issued ID directly, so IDs no longer depend on re-reading conversation history.
Evidence
lastMintedPasteId
Dropped unverified bridge events are now counted #
Unrecognised bridge events rejected by device attestation are now logged and counted instead of vanishing.
Under the hood · Remote Control
What
When device attestation enforcement rejects an event it does not recognise, it is now logged as a warning and counted once per process with a key for the kind of payload, instead of vanishing. Only reached when attestation is configured to enforce.
Evidence
[bridge:attestation] DROPPING unverified
Ultrareview promo surfaces now report impressions #
Each place showing the ultrareview prompt now reports that it appeared; the entitlement gate is unchanged.
Under the hood · Code Review
What
Each place that shows the ultrareview prompt now fires an event naming that surface. The prompts themselves remain behind the existing remote-sessions entitlement check.
The internal metrics forwarder, reached only on first-party accounts, now removes a list of potentially identifying fields before sending, collapses tool and feature names into generic buckets, and limits how often per-server MCP events can be sent.
Details
Deleted fields include the MCP server base URL and name, the MCP tool name, a hashed error message, and two hashed skill names.
Any tool name collapses to mcp when the event is flagged as MCP, where previously only names beginning with mcp__ were collapsed. Names beginning with skill__ become skill, and feature names beginning with tool_skill_ become tool_skill, except tool_skill_tool.
Five MCP events are capped at 10 forwards per 60 second window per server, tracked across at most 200 server keys, and the count suppressed since the last send rides along as droppedSinceLastForward.
Evidence
stripPiiFieldsForDatadog
MCP version mismatch is reported before it throws #
MCP version mismatches are reported to telemetry before the same error is raised.
Under the hood · MCP
What
The check that the loaded MCP client module matches the MCP version Claude Code expects now reports the expected and observed versions to telemetry before raising the same error as before.
Evidence
MCP runtime accessor tripwire: resolved generation is v2 but the loaded client module does not carry MCP_TREE_ID v2
PDF extraction and the retention sweep take a storage handle #
PDF extraction and the retention sweep now receive a storage handle instead of finding one themselves.
Under the hood · Internals
What
Both PDF page-extraction call sites now pass a storage handle through, and the retention sweep and one of its phases take that state as a parameter instead of looking it up themselves.
The plan-exit dialog was rebuilt on plain hooks and its feedback box now gets paste cleanup.
Under the hood · Plan Mode
What
The dialog shown when Claude proposes leaving plan mode was rewritten from heavily memoized generated code into ordinary hooks and inline callbacks. Behaviour and telemetry are unchanged, and its feedback field is now registered for paste cleanup.
PR review skill docs and its HTML template moved location but are byte-identical.
Under the hood · Code Review
What
The PR review skill documents and the bundled HTML template, including the staleness marker, decision pills and the in-page Approve on GitHub control, appear as new symbols but are byte-for-byte the same assets as the previous release. Nothing about generated PR review artifacts changes.
Evidence
prr-stamp
Artifact skill text no longer promises a per-viewer consent prompt #
Artifact docs no longer claim each viewer is asked for consent before a page updates itself.
You'll notice · Artifacts
What
Workshop and whiteboard skill and template text used to say the browser asks each viewer for consent before a page may update itself. That sentence is gone; only the server-side writer gate is described now.
Details
The whiteboard template sends a one-way analytics message when a board is sent to Claude, which the surrounding shell forwards only if the event name is on its allowlist.
Evidence
the shell enforces the writer gate server-side
Schema definitions rewritten with shorter helpers #
Almost every input schema was shortened, which accounts for most of this release's diff size.
Under the hood · Build
What
Almost every input schema in the bundle was rewritten to use short internal helpers instead of long-form calls, including Grep's parameters, the workflow tool, feedback drafts, notebook edits and session records. Field names, descriptions and validation are unchanged. This accounts for most of the diff size in this release.
Evidence
Enable multiline mode where . matches newlines and patterns can span lines (rg -U --multiline-dotall). Default: false.
Removed
4 items
Private memory directory dropped from the prompt #
Claude no longer mentions a private memory folder, and team memory is set up purely through the environment.
You'll notice · Memory
What
Claude no longer describes a separate private memory directory alongside team memory, and the path that discovered and mounted memory stores at runtime is gone. Team memory sync is now configured only through the environment.
Details
All prompt branches mentioning a private memory area were removed; the remaining text states plainly that there is no separate private memory directory in the session.
The store picker and its telemetry went with the discovery path; the team memory sync watcher now always reports its config source as env.
The memory-type descriptions and the instruction to cite memory with tags moved into shared constants.
Evidence
There is no separate private memory directory in this session.
The counter tracking spawned subagents was deleted and nothing replaced it.
Under the hood · Subagents
What
The running count of how many subagents had been spawned is gone; nothing reads or replaces it.
Details
The task registry and its no-op stub both drop incrementTotalAgentSpawns, getTotalAgentSpawns and resetTotalAgentSpawns.
The subagent spawn path no longer increments anything.
Evidence
getTotalAgentSpawns
Bash prompt line about where command output goes #
Claude is no longer told that command output goes to it rather than to you.
You'll notice · Elsewhere
What
The Bash tool prompt no longer tells the model that command output is shown to it rather than reliably to you. The surrounding guidance bullets are unchanged.
Evidence
- Commands are cheap to run and their errors are informative: run the straightforward command rather than perfecting it mentally first, and adjust from what it prints.
conversation_reset events are no longer forwarded #
Conversation reset events no longer turn into outbound messages, so nothing downstream hears about a new conversation id.
Under the hood · Session Events
What
Two query-event handlers dropped the branch that turned a conversation_reset event into an outbound message carrying a new conversation id. Anything downstream that watched for that message will no longer see it; only apply_flag_settings is still translated.