# Claude Code v2.1.277

> Claude Code v2.1.277, released 18 Sep 2026 (2026-09-18). 527 entries read out of the shipped bundle. Unofficial, and not affiliated with Anthropic.

Web version: https://changelogs.core-directive.com/v/2.1.277

This build carries 33 gated additions that stay out of reach. AGENTS.md fallback now becomes the default instruction-file mode when a project has no CLAUDE.md, with the controlling setting renamed. Also present but inert: a per-turn "current time" signal for API requests gated by an env var, a fully-built promo/offer eligibility check with no visible trigger, a SuggestPluginInstall tool for inline plugin-install cards, a repository-trust confirmation flow for cloud sessions, and a usage-limit "wrap up your work" reminder that stays gated off by default.

Of 166 shipped entries, a running tool call can now be detached to the background so a queued message can get through instead of waiting on it to finish. Mermaid diagrams render as ASCII box-drawing art directly in the terminal. Plugins gain a new prompt.attachment hook for rewriting or dropping attachment text before it reaches the model, and plugin fetch can connect over a Unix socket via a new experimental socketPath option. The instructionFiles setting now supersedes projectInstructions, which becomes a deprecated fallback, and remotely served project hook commands now run sandboxed and pinned by checksum before their block/allow decision is trusted.

Among 59 fixes, the TaskOutput tool has been removed, with background task output now read through the Read tool instead. Settings files reached through symlinks to another host or unverifiable routes are now refused rather than followed. Sandboxed shell commands get a fallback $TMPDIR when a command references it but none is set, and PDF page extraction now handles Windows file paths longer than 259 characters. The headless cloud client now validates repository-trust prompts before forwarding them to the host, dropping suspicious ones.

## What probably matters to you

Anything you can use today, anything that visibly changes, and anything worth poking at. One line each, open for detail.

### Long-running tool calls can now detach to the background when a new message arrives

A long-running tool call can now be moved to the background instead of blocking when a new message comes in

**What**

Claude Code can now move a long-running tool call to the background if you send a new message before that call finishes, instead of making the turn wait for it to complete. The model is told the call "was not interrupted" and that its result will arrive later in a separate `tool_result`. When the detached call eventually finishes, fails, times out, or is stopped, its outcome is delivered as a task notification. A detached call is force-stopped if it runs longer than 5 minutes.

**Why**

This keeps a conversation moving instead of blocking on a single slow tool call, while still delivering that call's result once it becomes available.

- Flag `tengu_tool_detach`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Background Tasks
- Tier: You'll notice
- Useful: 5/5
- Signal: 4/5

### Mermaid diagrams render as ASCII/box-drawing art in the terminal

Mermaid flowcharts and sequence diagrams in replies now render as text art in the terminal

**What**

When an assistant reply includes a Mermaid diagram (a way of describing flowcharts and sequence diagrams as text, wrapped in a ```mermaid code block), Claude Code can now detect it and redraw it directly in the terminal using box-drawing characters, in place of the raw Mermaid source. If a diagram can't be laid out or is too large, it's left as plain text instead.

**Why**

This lets you see an actual diagram in the terminal instead of raw Mermaid markup, making flowcharts and sequence diagrams in a response easier to read at a glance. Whether this is active for a given account depends on a setting, `tengu_mermaid_mod`, which nothing has yet been read about.

- Flag `tengu_mermaid_mod`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 5/5
- Signal: 4/5

### Tool calls can now be 'detached' to background mid-flight to let queued messages through

A running tool call can now be detached to the background so a queued message can go through, tracked via telemetry

**What**

A tool call that's taking a long time can now be moved to the background, with its result delivered later through a queued tool result, instead of forcing the current turn to wait for it to finish. This is reported via `tengu_tool_call_detached` telemetry, and a maximum timeout applies to detached calls.

**Why**

This keeps Claude Code responsive by letting new messages go through instead of waiting for a slow tool call to complete, while still tracking and eventually delivering that call's result.

- Flag `tengu_tool_detach`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Background Tasks
- Tier: You'll notice
- Useful: 5/5
- Signal: 4/5

### AGENTS.md fallback is now the default instruction-file mode

AGENTS.md now loads by default when a project has no CLAUDE.md, and the setting controlling it is renamed

**What**

The setting that controls whether `AGENTS.md` files are loaded as project instructions has been renamed from `projectInstructions` to `instructionFiles`, and its default has changed to `"claude-md-or-agents-md"`. In practice:

- A project with no `CLAUDE.md` of its own now gets its `AGENTS.md` files loaded in `CLAUDE.md`'s place automatically, without needing to turn anything on.

- The old setting name, `projectInstructions`, still works as a deprecated alias, but using it now logs a migration notice pointing at the new name.

**Why**

This means projects that use `AGENTS.md` instead of `CLAUDE.md` get their instructions picked up out of the box, instead of requiring users to discover and enable a separate setting first.

- Flag `tengu_agents_md_mod`: Off by default, switched on for this account (read for one account on one subscription tier against v2.1.277; this account: on, anonymous baseline: on, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Settings
- Names: `instructionFiles`, `AGENTS.md`
- Tier: Nothing to try yet
- Useful: 4/5
- Signal: 4/5
- Present in the build but not switched on

### Hosted 'serve' sessions can now surface host-side dialog notices to the cloud session view, behind a gate

Hosted cloud sessions may soon show host-side notices in the cloud session view, gated behind an unread flag

**What**

When a headless "serve" session (a Claude Code session running on your machine but attached to a cloud session) is active, new plumbing can collect notices from the host and surface them through the cloud session view via a new `notices` field and a new `onCloudSessionChanged` hook. Whether this activates depends on a setting called `hostedServeDialogsGateOn`.

**Why**

This would let notices that pop up on the host machine (such as dialogs) become visible from the cloud session view, but whether it's active depends on server-side rollout.

- Area: Cloud Sessions
- Names: `hostedServeDialogsGateOn`
- Tier: Nothing to try yet
- Useful: 4/5
- Signal: 4/5
- Present in the build but not switched on

### New 'alder_ford' model-family override gated to first-party API only

A new 'alder_ford' override can swap in a different model family's display info, but only on first-party API access

**Unclear.** What 'alder_ford' is used for in practice, and what triggers the alias to be configured, isn't stated in the finding.

**What**

Claude Code now has a mechanism, keyed by the internal name "alder_ford", that can substitute one model family's display name and cost information for another's. It checks for a configured alias and an expiry timestamp before applying the substitution, and only does so if the alias resolves to a known model family. This only takes effect when using the first-party Anthropic API, not third-party providers.

**Why**

This looks like infrastructure for temporarily relabeling or rebranding a model family's shown name and pricing, restricted to Anthropic's own API.

- Area: Models
- Tier: Nothing to try yet
- Useful: 4/5
- Signal: 4/5
- Present in the build but not switched on

### New "repository trust" confirmation flow for cloud/remote sessions

Cloud sessions can now ask you to confirm you trust a repository, with device-binding warnings if you're answering from the wrong place

**What**

A new confirmation type, repository trust, has been added for cloud and remote sessions. When a tool call arrives tagged as a repository-trust question, Claude Code shows explanatory text along the lines of "Answering yes marks everything attached to this cloud session as trusted," and it refuses to display the question unless the input matches exactly what the server sent.

- If the terminal you're answering from isn't the device the cloud session is actually bound to, a warning is appended saying the answer can't prove which device it came from, and telling you to answer from claude.ai on web, desktop, or mobile instead.

- If the terminal can't render the question at all, it posts a note that the question can't be shown in full there and leaves it unanswered for other devices to handle.

- Related new messages cover cases where a cloud session can't use a local folder until you answer a trust prompt (required, declined, or unavailable), and refusal messages for when a call can't be vouched for under an organization's trusted-device policy.

**Why**

This closes a gap where a repository-trust decision could be answered from a device other than the one actually bound to the cloud session, which would make the trust confirmation meaningless as proof of who approved it. The new checks and warnings make clear when an answer can't be trusted as authoritative.

- Flag `tengu_violin_bridgepin`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Cloud Sessions
- Tier: Nothing to try yet
- Useful: 4/5
- Signal: 4/5
- Present in the build but not switched on

### New model-alias experiment key 'alder_ford' read from session config

A new experiment key 'alder_ford' can override a model's displayed cost bucket via session config

**Unclear.** What the 'alder_ford' experiment is for, and when it would be set, is not established by the evidence.

**What**

Claude Code can now read a config value keyed `alder_ford` from session config, which must include an alias (`as`) and an expiry timestamp (`ends_at`). When present and not expired, it's substituted for the active model's normal display cost bucket, unless the request is for the fast-speed mode. It's used in cost lookup, in detecting whether a model is managed or from a list, and in the display-name lookup.

**Why**

This looks like infrastructure for an internal experiment that can temporarily change how a model's cost is categorized and displayed, without changing which model actually runs.

- Area: Models
- Names: `alder_ford`
- Tier: Nothing to try yet
- Useful: 4/5
- Signal: 4/5
- Present in the build but not switched on

### New per-turn 'current time' beta signal, gated by an env var

A new per-turn 'current time' signal can be sent with API requests, gated by an env var

**What**

A new field called `perTurnNow` can be added to API requests, sending the current timestamp with each turn (each back-and-forth exchange). It works alongside the existing per-turn-effort mechanism and only takes effect when the beta flag associated with it is included in the request, and when the environment variable `CLAUDE_CODE_PER_TURN_TIMING` is set along with the existing per-turn-effort eligibility conditions.

**Why**

This gives the model visibility into the current time on a per-turn basis, which is opt-in and off unless the `CLAUDE_CODE_PER_TURN_TIMING` environment variable is set.

- Area: API Client
- Tier: Nothing to try yet
- Useful: 4/5
- Signal: 4/5
- Present in the build but not switched on

### New tool: SuggestPluginInstall renders an inline plugin-install card

A new SuggestPluginInstall tool renders an inline card offering to install a plugin found by search

**What**

Claude Code has a new internal tool called `SuggestPluginInstall`. It is meant to be used after a plugin search (`SearchPlugins`) turns up relevant results, and it shows an inline card letting you install one of the suggested plugins directly from the conversation.

Before showing the card, Claude Code checks each suggested plugin against your claude.ai plugin catalog (using a new small cache that holds up to 512 entries). Suggestions that don't resolve to a real plugin, or that turn out to be skills rather than plugins, are dropped. If none of the suggested plugins can be verified, no card is shown at all.

**Why**

This makes it easier to go from "Claude found a plugin that might help" to actually installing it, without you having to run a separate install command yourself. The verification step guards against suggesting a plugin (or skill mistaken for one) that doesn't actually exist in your catalog.

- Flag `tengu_gentle_frost`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Plugin Install
- Names: `SuggestPluginInstall`
- Tier: Nothing to try yet
- Useful: 4/5
- Signal: 4/5
- Present in the build but not switched on

### Promo/offer claim eligibility check is fully built with no visible trigger

Backend support for checking and claiming a promotional offer is fully built but not visibly triggered anywhere yet

**Unclear.** There is no visible trigger showing where or when this offer-claim flow is actually surfaced to users

**What**

A new function checks eligibility and claim status for a promotional offer via an authenticated 'teleport-org' endpoint, complete with a full set of user-facing messages: the offer has expired, it was already claimed (by you or by someone else in another organization), it isn't available, or a generic failure occurred.

**Why**

This looks like preparation for a promo or offer feature, but nothing in this change shows where or how it's actually surfaced to users yet.

- Area: Promotions
- Tier: Nothing to try yet
- Useful: 4/5
- Signal: 4/5
- Present in the build but not switched on

### Gateway egress-boundary mode: outbound traffic can defer address checks to a forward proxy

A new env var lets a gateway proxy handle outbound address safety checks itself instead of Claude Code

**What**

A new environment variable, `CLAUDE_GATEWAY_PROXY_IS_EGRESS_BOUNDARY`, tells Claude Code that all outbound network traffic should be handed directly to an upstream HTTPS or HTTP proxy by hostname, letting that proxy's own allowlist decide what's permitted, instead of Claude Code resolving addresses itself and checking them for unsafe targets (like local/loopback addresses).

This mode refuses to turn on, and logs a warning explaining why, if:

- No usable `HTTPS_PROXY` or `HTTP_PROXY` is configured

- `CLAUDE_GATEWAY_ALLOW_LOOPBACK` is also set

- `NO_PROXY` or `no_proxy` is non-empty

**Why**

This lets a gateway deployment take over responsibility for outbound address safety, which is useful when the proxy already enforces its own allowlist, while the safety checks in Claude Code remain guarded against being disabled by accident or misconfiguration.

- Area: Gateway Proxy
- Names: `CLAUDE_GATEWAY_PROXY_IS_EGRESS_BOUNDARY`
- Tier: Use it now
- Useful: 5/5
- Signal: 3/5

### New 'prompt.attachment' hook type lets plugins rewrite or drop message attachment text

New `prompt.attachment` hook lets plugins rewrite or remove text attached to a message

**What**

A new hook type called `prompt.attachment` runs over the attachments (files or other content attached to a message) on a user's message. A hook that handles this event can rewrite the attached text or remove it entirely before it reaches the model. Claude Code logs what was changed and which plugin and hook made the change.

**Why**

This gives plugins a way to filter or transform attachment content, for example to redact sensitive data or reformat content before it's sent to the model, and the logging makes it clear which plugin is responsible for any change.

- Area: Plugin Hooks
- Names: `prompt.attachment`
- Tier: Use it now
- Useful: 5/5
- Signal: 3/5

### New plugin hook event: prompt.attachment

Plugins can now hook into 'prompt.attachment' to rewrite or drop attachment text before it reaches the model

**Unclear.** Whether `prompt.edit` does anything yet is unclear, since it appears in the event list without any visible dispatch wiring.

**What**

Claude Code adds a new plugin hook event, `prompt.attachment`. A plugin (an add-on that can extend Claude Code's behavior) implementing this hook can now rewrite or remove the text of an attachment (such as a file or image included with a prompt) before it is sent to the model. The system logs whether the attachment's text was passed through unchanged, rewritten, or left out, and records whether that decision came from a plugin, a hook, or the engine itself.

- A new event name, `prompt.attachment`, is added to the list of events plugins/hooks can implement, and is wired up and actively invoked during startup.

- A related event name, `prompt.edit`, is also added to the list of recognized event names, but does not appear to be wired up to run anything yet.

**Why**

This gives plugins a new point of control over what content actually reaches the model when a prompt includes attachments, useful for filtering or transforming attached content before it's processed.

- Area: Plugin Hooks
- Names: `prompt.attachment`
- Tier: Use it now
- Useful: 5/5
- Signal: 3/5

### HIPAA-related failOpenVerdict compliance branch, gate unresolved

A new fail-open exception lets some compliance checks pass when the HIPAA verdict service is unreachable, if HIPAA evidence was loaded

**Unclear.** Which specific compliance keys or actions this exception applies to is not stated

**What**

Organizations using compliance policies now have a new exception path: if the service that returns a compliance verdict is unreachable (a "fail open" condition) and the request matches the identity that was involved when the verdict couldn't be determined, certain otherwise-denied actions become allowed again. This exception does not apply if HIPAA-related evidence hasn't been loaded yet or can't be read.

**Why**

This is meant to prevent an unreachable verdict service from blocking legitimate work outright, while still holding back the exception when the necessary HIPAA compliance evidence isn't actually available to check.

- Area: Compliance
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 4/5
- Present in the build but not switched on

### New tool-host attestation floor check (dark, double-gated)

New tool-host attestation floor check replaces old attestation execution logic, gated behind two flags

**What**

A rewritten internal function now computes a policy verdict for a tool's host-attestation status against an acceptance floor, returning one of "not_policed", "pass", "config_exception", or "below_floor". This replaces an earlier version of the same function that actually executed the tool call directly. The overall attestation mode (whether checks merely observe or actually enforce) depends on the `tengu_vast_tulip` setting, and the whole check only runs at all if a separate condition gated by `tengu_breezy_fairy` returns true.

**Why**

This restructures how Claude Code evaluates whether a tool's host meets an attestation floor, separating the policy decision from tool execution, though whether this behaves as observe-only or enforcing depends on server-controlled settings not disclosed here.

- Flag `tengu_breezy_fairy`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Flag `tengu_vast_tulip`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Tool Attestation
- Names: `tengu_vast_tulip`, `tengu_breezy_fairy`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 4/5
- Present in the build but not switched on

### Usage-limit "wrap-up" reminder injection, gated off by default

A new 'wrap up your work' reminder can be injected near usage limits, currently gated off

**What**

Claude Code has added a system for injecting a hidden reminder to the model when a session is inside a usage-limit grace window (a short period around hitting a usage limit). The reminder tells the model to finish up or checkpoint its work rather than starting new subagents or long-running tasks. The exact wording and mode of the reminder (a 'wrap-up' style, a 'next-steps' style, or a custom message) are configurable, and whether the whole thing fires at all is controlled by the `tengu_lantern_wick_braid` setting.

**Why**

The goal is to help Claude Code avoid starting work it won't be able to finish once a usage limit kicks in. Whether any of this is active for a given account depends on server-side settings that haven't been read for this release.

- Flag `tengu_lantern_wick_mode`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Rate Limits
- Names: `tengu_lantern_wick_braid`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 4/5
- Present in the build but not switched on

### New 'Claude Design' browser sign-in flow for headless/host sessions

A new 'Claude Design' browser-based sign-in flow is being built, with manual-code fallback

**Unclear.** What "Claude Design sync" actually is and when it becomes available is not stated; the finding only shows the flow's plumbing

**What**

New host-side code implements a browser-based sign-in flow called "Claude Design sync," including a fallback to entering a code manually and polling for sign-in pages to complete. It communicates over a session event stream and reports specific failure reasons, such as an incompatible session, a timeout, or a save failure.

**Why**

This appears to be groundwork for a new sign-in method, though it isn't yet configured or available in this build.

- Area: Cloud Sessions
- Tier: Under the hood
- Useful: 3/5
- Signal: 4/5

### CLAUDE.md/AGENTS.md loading mode options renamed and expanded

CLAUDE.md/AGENTS.md loading modes renamed and given a fourth 'managed-only' option

**What**

The recognized modes for how Claude Code loads memory files (`CLAUDE.md` and `AGENTS.md`) changed names and options. The old set was `claude`, `agents-fallback`, `both`, and `none`. The new set is:

- `claude-md`

- `claude-md-or-agents-md`

- `claude-md-and-agents-md`

- `managed-only`

**Why**

The new names describe more explicitly what each mode does (load only `CLAUDE.md`, fall back to `AGENTS.md`, load both, or use only managed/centrally-provided files), and the new `managed-only` option gives a way to load exclusively managed configuration rather than any repository-level memory file.

- Area: CLAUDE.md Rules
- Names: `CLAUDE.md`, `AGENTS.md`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### CLAUDE.md/AGENTS.md mode enum replaced with a differently-shaped option set

The setting controlling how CLAUDE.md and AGENTS.md are used now has four differently-named options

**Unclear.** The finding doesn't say what happens if an old value like "claude" is still set, or how the new values map one-to-one onto the old behavior.

**What**

The list of valid values for the setting controlling how `CLAUDE.md` and `AGENTS.md` files are used has changed. It used to be `"claude"`, `"agents-fallback"`, `"both"`, and `"none"`. It's now `"claude-md"`, `"claude-md-or-agents-md"`, `"claude-md-and-agents-md"`, and `"managed-only"`.

**Why**

If you or your organization set this option explicitly, the old values will need to be updated to the new names to keep working as intended.

- Area: CLAUDE.md Rules
- Names: `claude-md`, `claude-md-or-agents-md`, `claude-md-and-agents-md`, `managed-only`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### New cancel_async_message bridge control request

A new cancel_async_message control request lets a bridge client cancel one queued message by its ID

**What**

A new control request called `cancel_async_message` lets a connected bridge client cancel a message it previously sent and queued for later processing, by specifying that message's `message_uuid`. Claude Code checks that the ID is valid and that a callback is registered for it, then reports back whether the cancellation succeeded or failed.

**Why**

This gives a client a way to withdraw one specific queued message on its own, rather than only being able to cancel everything queued at once. If the message can't be found or was already handled, the request reports failure instead of doing nothing silently.

- Area: Remote Control
- Names: `cancel_async_message`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### Plugin $.fetch gains an experimental Unix-socket transport (socketPath)

Plugin fetch can now connect over a Unix socket instead of a network address, as an experimental option

**What**

The sandboxed `$.fetch` helper available to plugins now accepts a `socketPath` option to connect over a Unix socket (a local, file-based connection) rather than over the network. The path must be absolute, must not contain a NUL byte, and must not resolve to a network location; if the build doesn't support Unix sockets, it throws "no Unix socket transport in this build." When credentials are used with a socket connection, the request forces strict TLS certificate checking and disables connection keep-alive.

**Why**

This lets plugins talk to local services listening on a Unix socket, useful for tools that expose a local API without going through the network, while keeping the same path and security validation Claude Code already applies elsewhere.

- Area: Plugin API
- Names: `socketPath`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### Remote bridge sessions can now cancel an in-flight async message

Remote Control can now cancel a single queued message instead of only interrupting the whole turn

**What**

Remote Control (the bridge that connects Claude Code to claude.ai) can now cancel one specific message that's queued up ('async') rather than only interrupting the entire turn. This adds a new `onCancelAsyncMessage` handler alongside the existing handlers for interrupting, stopping a task, and managing background tasks, and adds a new `cancel_async_message` control request type that a remote or SDK client can send.

**Why**

This gives remote clients finer control: they can withdraw a specific pending message instead of having to interrupt everything that's running.

- Area: Remote Control
- Names: `onCancelAsyncMessage`, `cancel_async_message`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### SetMaxThinkingTokens gains a 'highlights' thinking-display mode

New 'highlights' thinking-display mode added to set_max_thinking_tokens, for Anthropic-hosted sessions only

**What**

The `set_max_thinking_tokens` tool's `thinking_display` setting now accepts a new value, `highlights`, alongside the existing `summarized` and `omitted` options. Instead of a prose summary of Claude's thinking, `highlights` returns one short title per stretch of thinking. This value is only accepted for Claude Code sessions that Anthropic itself hosts; for any other client, requesting it still succeeds but silently falls back to `omitted` once the API rejects the value.

**Why**

This gives Anthropic-hosted sessions a more compact way to show what Claude was thinking about, without a full prose summary, while other clients continue behaving as before.

- Area: Thinking Display
- Names: `set_max_thinking_tokens`, `highlights`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### instructionFiles setting supersedes projectInstructions

New instructionFiles setting replaces projectInstructions, which is now a deprecated fallback

**What**

Claude Code's logic for loading instruction files like `CLAUDE.md` and `AGENTS.md` now reads a new setting called `instructionFiles`. The older `projectInstructions` setting still works, but only as a fallback, and is now considered deprecated. If both settings are missing or conflict with each other, Claude Code logs a one-time warning telling the user to migrate to `instructionFiles`.

**Why**

This gives the `instructionFiles` setting priority going forward while still honoring existing `projectInstructions` configuration for now, with a warning nudging users to switch over before the old setting goes away.

- Area: Settings
- Names: `instructionFiles`, `projectInstructions`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### New sandbox gate for running project command checks (hooks) read-only on this machine for remote/cloud sessions

New sandbox and approval flow for project hooks run read-only during cloud/remote sessions

**What**

Claude Code has added a set of confirmation messages and sandbox logic for "project command checks" (project hooks) that run on a machine serving a cloud or remote session. Specifically:

- Checks that have changed or don't match expectations now ask for approval, either per-session or accepted going forward.

- Checks that try to rewrite the command they're checking are rejected outright for cloud sessions.

- Three approvals in a row suppress further prompting.

- These checks run inside a read-only sandbox.

**Why**

This limits what project hooks can do when a session is being driven remotely or from the cloud, so a hook can't silently rewrite commands or make unreviewed changes on a machine it's attached to.

- Flag `tengu_violin_peg`: Off by default, switched on for this account (read for one account on one subscription tier against v2.1.277; this account: on, anonymous baseline: on, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Sandbox
- Tier: You'll notice
- Useful: 4/5
- Signal: 3/5

### Sandboxed execution added for project-defined hook commands (remote tool serving)

Project hook scripts served remotely are now pinned by checksum and run in a sandbox before their block/allow decision is trusted

**Unclear.** Whether this sandboxing is active for a given user depends on rollout gates the finding doesn't resolve, so it's unclear how widely it applies yet.

**What**

Claude Code can now pin a project's hook scripts by their sha256 checksum, verify they haven't changed since being "served" remotely, and run them in a sandbox with a private temporary directory before trusting their `PreToolUse` decision (the point where a hook can block a tool call before it runs). Outcomes such as the script having changed since it was attached or last served, timing out, or producing malformed output are all tracked and can be surfaced back to you as extra context text, alongside telemetry.

**Why**

This adds a safety check so a project's hook scripts can't silently change and run with a different effect than what was originally verified, and it runs them in a more contained way.

- Flag `tengu_violin_peg`: Off by default, switched on for this account (read for one account on one subscription tier against v2.1.277; this account: on, anonymous baseline: on, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Sandbox
- Tier: You'll notice
- Useful: 4/5
- Signal: 3/5

### /cd (directory-move) gains a 'fresh session' reset path for remote set_cwd

/cd can now fully reset session state when changing directory on a still-fresh session

**Unclear.** The gate `tengu_cd_command` has not been read for this release, so nothing can be said about whether this path is switched on for any account.

**What**

The `/cd` command, which moves a session to a new working directory, now has a "fresh session" reset path used for remote directory changes. If a session hasn't run any turns yet and the reset is confirmed, `/cd` now fully re-derives the start-of-session state, including `session_start` hooks (scripts that run at the start of a session), memory, and hook/skill caches, rather than just adding a "directory changed" note to the conversation. A new `fresh_session` field is also recorded in telemetry for this command.

**Why**

This makes changing directory on a session that hasn't started yet behave as if the session had started fresh in the new directory, rather than leaving it with state loaded from the original directory.

- Area: Directory Change
- Names: `/cd`
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### AGENTS.md / CLAUDE.md instruction-loading modes formalized with telemetry

AGENTS.md/CLAUDE.md loading now has four named modes, tracked with new telemetry

**What**

Claude Code formalizes how it decides whether to load `AGENTS.md` and/or `CLAUDE.md` files as project instructions, with four named modes:

- `managed-only`

- `claude-md`

- `claude-md-or-agents-md` (the default fallback; by default `AGENTS.md` is loaded as project instructions where the project has no `CLAUDE.md`)

- `claude-md-and-agents-md`

Two new telemetry events, `agents_md_load` and `agents_md_nested`, report the number of files found, the number of imports, the total content length, and whether the file-discovery walk succeeded or failed, all keyed by which of the four modes was resolved.

**Why**

Naming these modes explicitly and tracking their use with telemetry makes it possible to understand and troubleshoot how projects choose between `AGENTS.md` and `CLAUDE.md` for their instructions.

- Area: CLAUDE.md Rules
- Names: `AGENTS.md`, `CLAUDE.md`
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### Artifact creation supports an idempotency key and reports in-flight duplicate creates

Creating an artifact can now use an idempotency key to avoid duplicate creates in flight

**What**

When Claude Code creates an artifact from a type, it can now be given an idempotency key (a value used to detect and prevent duplicate operations). If a create request with the same key is already in progress, the new attempt is rejected with a `create_in_flight` error instead of creating a second copy. The response can also indicate `alreadyCreated: true` when a repeated request was replayed rather than acted on again.

**Why**

This prevents duplicate artifacts from being created when the same creation request gets sent more than once, such as from a retry.

- Area: Artifact Publish
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### Composer edits can be relayed through a 'prompt.edit' hook chain

Edits typed in the prompt box can now be routed through a 'prompt.edit' hook chain

**What**

A new recording/replay pipeline captures edits made to the text in the prompt input box (the composer). If a `prompt.edit` hook is registered, these edits are now routed through that hook chain before being applied to the input box. If no such hook is registered, the edits are applied directly and Claude Code logs that they went through unhooked.

**Why**

This lets a hook intercept and potentially modify what you type into the prompt box before it takes effect, opening the door to custom processing of composer edits.

- Area: Prompt Input
- Names: `prompt.edit`
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### New "act" driver API added for scripted interaction with plugin UI mounts

A new internal "act" API can programmatically drive Claude Code's plugin UI components for testing

**What**

A new `act` interface, with actions like `find`, `findAll`, `press`, `input`, `select`, `key`, `pointer`, `post`, `advance`, `resize`, `redraw`, and `unmount`, plus supporting functions (`mount`, `act`, `refresh`, `releaseAll`), can now drive Claude Code's terminal-rendered plugin UI components (Button, Link, Markdown, Code, Input, Select, Client) programmatically: clicking buttons, typing into inputs, selecting values, sending key or pointer events, advancing a virtual clock, and resizing, redrawing, or unmounting a mounted UI.

**Why**

This is a testing/automation tool for exercising plugin UI components without a person at the keyboard, useful for scripted checks of how plugin interfaces behave.

- Area: Testing Tools
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### New CLAUDE_CODE_WORKFLOW_PROMPT_PROVENANCE env var replaces CLAUDE_CODE_DAPPER_LAGOON, backed by tengu_bubbly_harbor and made synchronous

Workflow prompt provenance now read from CLAUDE_CODE_WORKFLOW_PROMPT_PROVENANCE and made synchronous

**What**

The function that used to read the `CLAUDE_CODE_DAPPER_LAGOON` environment variable (falling back to a gate called `MOo`) now reads a new environment variable, `CLAUDE_CODE_WORKFLOW_PROMPT_PROVENANCE`, falling back to a gate called `tengu_bubbly_harbor`, which defaults to true. Two places in the workflow engine that used to `await` this check now call it directly, since it no longer needs to run asynchronously.

**Why**

The flag server is currently returning this gate as on for both this site's account and the anonymous baseline, though no reading has been taken specifically under this release yet. Renaming the environment variable and making the check synchronous suggests this first-party detection logic was reworked and simplified.

- Flag `tengu_bubbly_harbor`: On for this account, and not off by default (read for one account on one subscription tier against v2.1.277; this account: on, anonymous baseline: on, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Workflows
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### New env var CLAUDE_CODE_PARSED_WILLOW overrides tengu_parsed_willow (marks turns as human-authored)

A new CLAUDE_CODE_PARSED_WILLOW environment variable can override marking queued commands as human-authored

**What**

A new function marks certain queued-command turns with `humanTurn: true`. This behavior is controlled by the `tengu_parsed_willow` setting, whose code fallback now defaults to true, and it can now be overridden directly with a new `CLAUDE_CODE_PARSED_WILLOW` environment variable.

**Why**

Marking a turn as human-authored likely affects how it's treated downstream (for example, in provenance or trust checks). The new environment variable gives a direct way to control this without waiting on server-side settings, which haven't been read for this release.

- Flag `tengu_parsed_willow`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Turn Handling
- Names: `CLAUDE_CODE_PARSED_WILLOW`
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### Plugin/MCP reconcile can run concurrently with CLI startup under a time budget

Plugin and MCP server syncing can now run alongside CLI startup under a time budget

**What**

At startup, Claude Code can now begin syncing plugins and MCP servers (external tool connections) at the same time as it starts the main message loop, rather than waiting for one before the other. This sync is tracked against a time budget, `remainingSyncBudgetMs`, derived from the environment variable `CLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS`, and Claude Code flags it if the sync runs longer than that budget allows.

**Why**

Running plugin/MCP sync in parallel with startup should make Claude Code ready to use sooner, while the time budget keeps a slow sync from delaying startup indefinitely.

- Area: Plugin Install
- Names: `CLAUDE_CODE_SYNC_PLUGIN_INSTALL_TIMEOUT_MS`
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### Rules/CLAUDE.md directory walk gains an exclude matcher

CLAUDE.md/rules directory scan can now skip paths matched by an exclude pattern

**Unclear.** The finding does not say what supplies the exclude matcher or how a user configures it.

**What**

When Claude Code walks a directory looking for `CLAUDE.md` files and other rules files, the walker and its helper functions now accept an exclude matcher: a pattern that marks certain paths as ones to skip. This is checked alongside the existing checks that already skip symlinks, binary files, and similar cases.

**Why**

This gives Claude Code a way to leave out specific paths when scanning for rules files, on top of the checks it already applies.

- Area: CLAUDE.md Rules
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### Pane Escape now dismisses background panes from chat, not just the focused one

Pressing the chat cancel key can now close a background chat pane, not only the one you're focused on

**What**

Claude Code's interface can show multiple "Panes" (separate work areas), including chat panes. A new keybinding named `chat:cancel` now lets pressing the chat-level cancel/escape key close a pane even when it isn't the one you're focused on, as long as its chat input is empty, no footer selection or queue edit is in progress, it isn't already in the middle of closing, and it doesn't have its own escape handling or an agent-selection view active.

**Why**

Previously this kind of dismissal likely only worked on the pane you had focused. Now background chat panes that meet those conditions can be closed the same way, making it easier to clear idle panes without switching focus to each one first.

- Area: Terminal UI
- Names: `chat:cancel`
- Tier: Use it now
- Useful: 4/5
- Signal: 2/5

### Plugin API doc points to new `claude plugin validate` command

Plugin type-generation help now points authors to a new claude plugin validate command

**What**

The help text shown by the plugin type-generation tooling now tells plugin authors about `claude plugin validate <dir>`, a command that reads a plugin the same way Claude Code's engine would and reports what it hooks into, what it calls, and what it would refuse to do.

**Why**

This gives plugin authors a way to check how their plugin will actually be interpreted before shipping it, catching issues earlier.

- Area: Plugin Install
- Names: `claude plugin validate`
- Tier: Use it now
- Useful: 4/5
- Signal: 2/5

### Usage-limit display can show a per-model breakdown

Usage/limit displays can now show a separate line per model instead of one combined limit

**What**

The usage and rate-limit summary shown to users, for example via `/usage` (also aliased as `/cost` and `/stats`), can now display a separate line for each model, each labeled "Current week ()" with its own utilization and reset time, instead of always showing one combined limits line.

**Why**

On plans where usage is broken down per model, this lets users see exactly how much of each model's limit they've used rather than only a single aggregated figure.

- Area: Usage & Limits
- Names: `/usage`, `/cost`, `/stats`
- Tier: Use it now
- Useful: 4/5
- Signal: 2/5

### "Wrap-up" usage-limit grace period links to clau.de/wrap-up

New 'wrap-up' grace period lets users finish work after hitting a usage limit, linking to clau.de/wrap-up

**Unclear.** The exact conditions that trigger the grace period and how long it lasts are not stated in the evidence.

**What**

Claude Code adds a support link (`https://clau.de/wrap-up`) and internal logic that checks whether a "wrap-up" grace zone is active and whether a usage-limit grace period is currently set. This points to a feature that gives users a window of time to finish their current work after hitting a usage limit, rather than being cut off immediately.

**Why**

A grace period after hitting a usage limit would let users wrap up what they're doing instead of losing work mid-task, with a documentation link available for more detail.

- Area: Rate Limits
- Names: `clau.de/wrap-up`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### Gateway upstream providers can now set custom headers

Gateway upstream provider configs can now include custom headers

**What**

The gateway's configuration schema for upstream providers (Bedrock, AnthropicAws, Vertex, and Foundry) now supports a `headers` field, letting an administrator attach custom HTTP headers to a specific upstream provider's requests alongside its existing authentication settings.

**Why**

This gives self-hosted gateway operators more control over outgoing requests to each provider, for example to satisfy provider- or network-specific header requirements.

- Area: Gateway Proxy
- Names: `headers`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### New 'Local tools' row in cloud session sync status

Cloud session sync status now tracks a fourth category: 'Local tools'

**What**

The cloud-session sync status display, which already tracked `projectFiles`, `settings`, and `plugins`, now includes a fourth category called `localTools` (shown as "Local tools"). It gets its own synced/pending/not-synced state and change detection, just like the existing categories.

**Why**

This lets users see whether their local tools are in sync with a cloud session, alongside the project files, settings, and plugins that were already being tracked.

- Area: Cloud Sessions
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### New 'localTools' settings panel row

The settings/status panel can now show a localTools row

**Unclear.** The finding doesn't say what data populates the localTools row or what counts as a local tool here.

**What**

The panel that displays status rows such as project files, settings, and plugins now also has a `localTools` row, shown only when there's data for it to display, following the same conditional pattern already used for the panel's trailing notes row.

**Why**

This lets the status panel surface information about local tools when relevant, without cluttering the display when there's nothing to show.

- Area: Settings UI
- Names: `localTools`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### New hidden CLI command: claude design-login --json

New hidden command claude design-login --json backs the /design-login sign-in flow for the VS Code extension

**What**

A new hidden command, `claude design-login --json`, runs the Claude Design sign-in flow and prints its progress as JSON lines. Adding `--status` reports the current sign-in state the same way. This command is meant to be run by the VS Code extension, not typed by hand; if you're working in a Claude Code session, use `/design-login` instead, which authorizes design-system access for `/design-sync` using your claude.ai account.

**Why**

Giving the VS Code extension a machine-readable, non-interactive way to trigger and check sign-in lets it integrate with Claude Design without needing an interactive terminal session.

- Area: Design Sync
- Names: `claude design-login --json`, `/design-login`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### Plugin $.fs.read can now request raw bytes (base64) instead of forcing utf8

Plugin file reads can now request raw bytes as base64 instead of always decoding as text

**What**

The plugin file-system read function used by `$.fs.read` now checks a new `as` option. When a plugin passes `as: 'bytes'`, it gets the file's contents back as base64-encoded raw bytes instead of having them decoded as UTF-8 text. The read-only file-system handler was also updated to pass this `as` option through.

**Why**

This lets plugins read binary files (images, archives, and other non-text data) correctly, since forcing everything through UTF-8 text decoding would corrupt binary content.

- Area: Plugin API
- Names: `as: 'bytes'`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### Session-start announcements can be forced before the closing line, gated by a new env var

A new env var lets session-start announcements be placed before the closing line in headless runs

**What**

A new environment variable, `CLAUDE_CODE_SESSION_START_ANNOUNCEMENTS_BEFORE_PROMPT`, controls where session-start announcements appear in headless (print/non-interactive) sessions. When set, Claude Code examines the last assistant message and, if conditions allow, repositions the announcement to appear before the closing line instead of its usual spot. Telemetry is recorded either way, including cases where the reposition can't happen (for example, if the model doesn't support system messages, there's no user message yet, or there's nothing to announce).

**Why**

This gives headless integrations a way to control the visual placement of session-start announcements relative to the rest of the output.

- Area: Headless Mode
- Names: `CLAUDE_CODE_SESSION_START_ANNOUNCEMENTS_BEFORE_PROMPT`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### fs.stat now reports isLink and can resolve a symlink's real path

Plugin fs.stat and list now report whether an entry is a symlink and can resolve its real path

**What**

The plugin file-system `stat` response now includes `isLink`, telling a plugin whether the entry is a symbolic link (a pointer to another file location). If a plugin requests `resolve` and the link's target stays within the paths the plugin is allowed to access, the response also includes a `realPath` showing where the link actually points. The `list` response now includes `isLink` for each entry it returns as well.

**Why**

This lets plugins detect and safely follow symbolic links within their allowed file access, rather than treating every entry as a plain file or folder.

- Area: Plugin API
- Names: `fs.stat`, `isLink`, `realPath`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### New sandbox-escape detection heuristics for `sandbox.excludedCommands`

New heuristics detect commands trying to escape the sandbox via the excludedCommands allowlist

**What**

`sandbox.excludedCommands` lets you name commands that always run outside the sandbox. Claude Code now parses the actual command line more carefully to catch cases where a command, or a wrapper around it, technically matches an allowlisted entry but is actually being used to slip past the sandbox. It recognizes things like:

- Trusted versus untrusted uses of `env`

- Dangerous interpreter or shell flags, such as `-c`, `--eval`, `-e`, or PowerShell's `-command`/`-encodedcommand`, across dozens of tools including bash, python, perl, ruby, php, node, git, docker, kubectl, aws, and pwsh

- Tricks involving `IFS` or positional parameters

- Risky glob expansion

- Git subcommands that can read or write outside the repository, such as `clone`, `worktree add`, `bundle create`, and `config` changes to dangerous keys like `core.sshcommand` or `core.hookspath`

**Why**

This closes off ways a command could use an excludedCommands entry as a loophole to run unsandboxed code that reaches beyond what was intended, building on earlier work that tied the exclusion list to whether unsandboxed commands are allowed at all.

- Area: Sandbox
- Names: `sandbox.excludedCommands`
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Gateway self-host config: per-upstream custom headers, and a new loopback guard on telemetry forwarding

Gateway config adds per-upstream custom headers and blocks loopback telemetry URLs unless explicitly allowed

**What**

Self-hosted gateway configuration now lets each upstream provider block (Bedrock, AnthropicAws, Vertex, Foundry) specify custom `headers` to send with its requests.

Separately, the gateway's telemetry forwarding setting (`telemetry.forward_to.url`) now rejects loopback addresses (URLs pointing back at the same machine, such as `localhost`) by default. To forward telemetry to a local sidecar collector, an operator must set the environment variable `CLAUDE_GATEWAY_ALLOW_LOOPBACK`.

**Why**

Custom headers give gateway operators finer control over requests to each upstream provider. The loopback guard prevents telemetry from being silently misconfigured to point at the gateway's own machine, while still allowing it deliberately via the new environment variable for legitimate local-collector setups.

- Area: Gateway Proxy
- Names: `headers`
- Tier: Use it now
- Useful: 2/5
- Signal: 2/5

### New disableSideloadFlags settings key hardened against malformed values

A malformed disableSideloadFlags setting now blocks sideload flags by default instead of being ignored

**What**

`disableSideloadFlags` is a managed setting that blocks CLI flags used to sideload extra content, such as `--plugin-dir`/`--plugin-url`, and MCP configuration loaded from outside approved sources. If this setting is present in configuration but its value doesn't parse correctly, Claude Code now treats it as `true` (blocking those flags) rather than falling back to a default that might allow them.

**Why**

This makes a broken `disableSideloadFlags` value fail closed: a configuration mistake results in sideloading being blocked until it's fixed, not silently permitted.

- Area: Settings
- Names: `disableSideloadFlags`
- Tier: Use it now
- Useful: 2/5
- Signal: 2/5

### New git-branch-guard telemetry/env override for cloud session on-branch checkout

Cloud on-branch checkout guard can now be forced on via a CCR_ON_BRANCH_DEFAULT_GUARD environment variable

**Unclear.** Nothing has been read yet about the `tengu_on_branch_default_guard_observe` gate for this site's account, so what "observe" mode does in practice versus "enforce" isn't confirmed here.

**What**

A guard around `--on-branch` cloud checkouts can now be forced into "enforce" mode using the environment variable `CCR_ON_BRANCH_DEFAULT_GUARD`. If that environment variable isn't set, Claude Code falls back to checking a remote configuration value, `tengu_on_branch_default_guard_observe`, to decide the guard's behavior.

**Why**

This gives operators a direct, local way to force strict enforcement of the on-branch checkout guard for cloud sessions, without waiting on remote configuration.

- Area: Git Internals
- Names: `CCR_ON_BRANCH_DEFAULT_GUARD`
- Tier: Use it now
- Useful: 2/5
- Signal: 2/5

### Plugin install errors now marked as "ours" for downstream handling

Design login now accepts a manually pasted authorization code more flexibly, with clearer failure reasons

**What**

The sign-in flow behind `/design-login` (which connects your claude.ai account so `/design-sync` can read and write design-system projects) has been reworked. It now supports pasting in an authorization code manually even in situations where it previously wasn't offered, since Claude Code can no longer always assume whether a browser can reach the local sign-in listener.

When the login fails, it now returns one of several specific reason codes: `interrupted`, `unconfigured`, `remote`, `invalid`, `save_failed`, `timed_out`, or `failed`, instead of just a generic message. A new check can also abort the flow partway through, after a login slot is validated.

**Why**

The more flexible manual-code path means you're less likely to get stuck when Claude Code can't tell whether a browser-based login will work, particularly on remote sessions. The structured failure reasons make it clearer why a login attempt didn't succeed.

- Area: Elsewhere
- Names: `/design-login`
- Tier: Use it now
- Useful: 2/5
- Signal: 2/5

### Usage-limit banner text can be overridden from remote config

Usage-limit banner wording can now be overridden remotely instead of being fixed text

**What

- Flag `tengu_lantern_sconce_copy`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Rate Limits
- Tier: Use it now
- Useful: 2/5
- Signal: 2/5

## New Features

### Dir-sync worker gains an 'attachOffer' path to resume from existing git history

Directory sync can now resume from existing git history instead of only starting fresh

**What**

The directory-sync worker, which uses git to sync a local directory with a cloud session, gains a new `attachOffer` capability. When sync is listening but not yet actively syncing, it can now inspect the local repository's current branch and recent history and offer to attach to that existing history, provided the branch is resolvable, nothing is mid-operation, and consent checks pass.

**Why**

This lets directory sync pick up from a repository's existing git history rather than always starting sync from scratch.

- Area: Directory Sync
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5

### New `notices` field added to cloud-session SDK stream schema for served-tool consent/status messages

Cloud session streams gain a 'notices' field for MCP consent, hook status, and tool mute/unmute messages

**What**

The `cloud_session` startup schema, used by the headless stream-json client for cloud-hosted sessions, now includes a `notices` array. This carries messages the user should see about device-serving events: MCP (Model Context Protocol) consent, reconsent, or drop; hook run status; bash commands run from the home directory; and muting or unmuting of served tools.

**Why**

This gives cloud sessions a structured way to surface important status messages, like when a tool needs your consent or gets muted, rather than these events going unreported to the client.

- Area: Cloud Sessions
- Names: `notices`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5

### Fine-pointer (trackpad-precision) mouse events added to terminal UI

Terminal UI now distinguishes fine (trackpad) pointer input from regular mouse clicks

**Unclear.** What behavior actually differs between fine and coarse pointer input is not stated in the finding.

**What**

Pointer handling throughout the terminal interface, covering press, drag, release, and hover events, now carries a 'fine' true/false flag alongside the existing button, column, and row information. The app also starts and cancels a "fine pointer settle" timer when a component is removed from view.

**Why**

This suggests Claude Code can now tell precise trackpad input apart from coarser mouse clicks, which could allow more accurate handling of pointer gestures in the terminal.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Terminal now probes and can negotiate pixel-precision mouse reporting (SGR 1016)

Terminal mouse input can now report positions in pixels instead of only character cells

**What**

Claude Code's terminal now probes for support of SGR pixel mouse mode (mode 1016), a terminal feature that reports mouse coordinates in pixels rather than character cells, along with a query for the terminal's cell size. Support for this has been built into the terminal rendering layer:

- a `mousePixels` mode that can be turned on and off, alongside existing modes like `focusEvents` and `altScreen`

- a new `fine` property on key and mouse events

- a hook, `retainFinePointer`, that lets interactive elements opt into pixel-precision mouse tracking, along with related helpers to manage that tracking

**Why**

This lets terminal-based interactive elements receive more precise mouse coordinates (in pixels rather than whole character cells), which is useful for finer-grained interactions like drawing or pixel-accurate image display, on terminals that support it.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Mouse events gain sub-cell pixel precision reporting

Mouse input now supports sub-cell pixel precision on terminals that report pixel coordinates

**What**

Claude Code's terminal interface can now translate mouse clicks and movements into pixel-precise coordinates, rather than just the terminal's character grid (column/row), on terminals that support pixel-based mouse reporting. A new terminal mode called `mousePixels` is turned on alongside the existing `extendedKeys` and `mouse` modes each time the screen redraws.

**Why**

On terminals that support it, this allows more precise mouse interaction than the coarser cell-based coordinates previously used.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Invisible/hidden characters stripped from pasted or typed prompt text

Claude Code now strips invisible characters like zero-width marks from pasted or typed text before sending it

**Unclear.** Whether this behaves differently from the related prompt-submission stripping described elsewhere is not established by the finding.

**What**

Before a prompt is sent, Claude Code now scans the text for invisible characters, such as bidirectional marks, zero-width characters, hidden tags, and selectors, and removes them. This applies to text you type as well as text you paste in. When anything is removed, you see a notice like "Removed N invisible characters" before the message goes out.

**Why**

Invisible characters can be used to hide instructions or content inside text that looks empty or normal, so removing them before sending reduces the chance of hidden content reaching the model unnoticed.

- Flag `tengu_tranquil_cloud`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Prompt Input
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Prompt submission now strips invisible/control characters before sending

Submitting a prompt now blocks and warns you if it contains invisible or control characters

**What**

When you submit text in the prompt input, Claude Code now runs it through a pass that removes invisible and control characters first. If any characters were stripped, the submission is stopped rather than sent, and you instead see a toast message such as "Removed N invisible character(s) · review and press Enter to send," or, if nothing printable remains, a message saying there's nothing left to send.

**Why**

This stops prompts containing hidden or control characters from being sent silently, giving you a chance to review the cleaned-up text and confirm before it actually goes out.

- Area: Prompt Input
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

## Improvements

### Dir-sync now tracks whether the cloud side has actually picked up synced files, with new warning copy

Directory sync now tracks whether the cloud side has actually consumed synced files, with a new warning

**What**

Directory sync uploads your local files to the cloud side of a session using git. Claude Code now tracks whether the cloud side has actually picked up ('vouched for') what was uploaded, computing state such as when it was last confirmed and how long it's been settled. If the cloud session hasn't consumed anything synced from a directory yet, Claude Code now shows a warning that changes made locally and on the cloud side may not be reaching each other.

**Why**

This surfaces a case where directory sync looks like it's working locally but isn't actually reaching the cloud side, so you know to check rather than assuming your changes are in sync.

- Area: Directory Sync
- Tier: You'll notice
- Useful: 3/5
- Signal: 3/5

### Plugin-dir file watcher with adaptive polling and ConfigChange hook gate

Plugin skill directories now get watched for changes, with adaptive polling and a ConfigChange hook gate

**What**

Claude Code now watches plugin skill directories (both whole folders and individual files) for changes, polling more often when there has been recent interaction and less often when idle. Before hot-reloading a plugin that uses 'files' scope, it asks a `ConfigChange` hook (a hook that runs when a configuration file changes during a session) whether the reload should proceed. If the hook blocks the reload, the currently loaded version of the plugin stays in place.

**Why**

This lets plugin changes on disk be picked up automatically while giving hooks a way to veto a reload, for example to avoid reloading a plugin mid-edit or in an inconsistent state.

- Area: Plugin Install
- Tier: You'll notice
- Useful: 3/5
- Signal: 3/5

### Plugin install can now verify declared binary hashes

Plugin installs can now verify declared binary file hashes before republishing

**What**

When installing a plugin whose manifest declares binaries, and a feature check passes, the installer now passes along a `binariesHook` containing the declared SHA-256 hashes for those binaries into the staging and publish step. If the hashes already match, the install can report the result as 'kept' and skip republishing the plugin.

**Why**

This avoids unnecessarily re-publishing plugin binaries that haven't actually changed, and lets the install process verify binary integrity against the values declared in the plugin's manifest.

- Area: Plugin Install
- Tier: You'll notice
- Useful: 3/5
- Signal: 3/5

### New 'attached' (fast-sync) relation mode for directory sync, distinct from the legacy merge path

A faster sync path for 'attached' sessions handles directory sync separately from the older full merge logic

**What**

For sessions where a laptop's state is "attached" to a live machine, Claude Code now uses a lighter fast-forward or no-op check to keep directories in sync, instead of the older full three-way merge logic. This path can report that a session is "unready" (the machine has a detached HEAD) or "left" with a reason such as the branch being switched or having diverged. A companion function now also explains a new "switched off" case, meaning the sync feature is switched off for that session.

**Why**

This gives attached sessions a cheaper, quicker sync check instead of always running the heavier merge process, while still surfacing clear reasons like a diverged branch or the feature being disabled when syncing isn't possible.

- Area: Directory Sync
- Tier: You'll notice
- Useful: 3/5
- Signal: 3/5

### Paste/type-out expansion now dedupes repeated pasted text and flags 'ultraplan' mentions

Pasted/typed text expansion now avoids re-expanding duplicate spans and holds back 'ultraplan' matches

**Unclear.** What triggers expansion here and what 'ultraplan' expands to isn't stated in the finding.

**What**

When Claude Code expands typed or pasted text, it now looks at all the text fragments together first. If the same content appears more than once, it avoids expanding overlapping duplicate spans a second time.

There's also a special case: if any of the matched fragments contains the word "ultraplan" (case-insensitive) and that exact text isn't already present verbatim elsewhere, the whole set of matches is suppressed and nothing gets expanded.

**Why**

The deduplication prevents the same pasted text from being expanded multiple times when it appears more than once. The "ultraplan" carve-out stops that specific expansion from firing in situations where it would likely be wrong.

- Area: Prompt Queue
- Tier: You'll notice
- Useful: 2/5
- Signal: 3/5

### /ultrareview can now review a first commit whole, with confirmation

/ultrareview (now /code-review ultra) can review a repo's very first commit in full, with confirmation

**What**

When your current branch has only one commit and it's the very first commit in the repository, `/ultrareview` (also invokable as `/code-review ultra`) no longer silently falls back to diffing against an empty tree. It can instead offer to review every file in that first commit, but only after you confirm, or after a person (not an automated caller) ran the command directly.

**Why**

Previously a first commit on a fresh repo would get a thin or empty review. Now it can be reviewed properly, while still asking before doing a larger-than-usual review.

- Area: Slash Commands
- Names: `/ultrareview`, `/code-review ultra`
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### New shell-command danger-pattern detector

A new detector flags shell commands containing risky constructs like command substitution before auto-approving them

**What**

Claude Code now parses a shell command's structure (using a tree-sitter-based parser) to detect constructs considered unsafe to auto-approve without asking the user, including:

- brace and parameter expansions

- `$'...'`/`$"..."` style quoting

- command substitution (`$(...)`) and backticks

- process substitution (`<(...)` and `>(...)`)

- arithmetic expansion (`$[...]`)

- malformed or incomplete redirects

If any of these appear in a command, it's flagged as unsafe to auto-approve.

**Why**

These shell constructs can let a command do something other than what it appears to do at a glance, such as running hidden commands or reading unexpected input. Flagging them prevents Claude Code from auto-approving a command that looks safe but isn't.

- Area: Bash Safety
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### File tool can now fall back to a single unsynced remote machine when reading files

File tool can now fall back to a single unsynced remote machine, with a warning it may be at a different commit

**What**

When Claude Code's file tool (used for Read, Bash, and similar operations) needs to pick which attached machine to run a command on, it can now fall back to a single remote machine even if that machine isn't set up for two-way or upload-only project sync. In that case, the tool warns that the remote machine holds its own separate copy of the project, that nothing is synced between it and the current session's checkout, and that it may be at a different commit.

**Why**

This lets a command still run on the only available remote machine instead of failing outright, while making clear the files there might not match what the current session sees.

- Area: Remote Machines
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Directory sync extended to mid-session machine attachment

Directory sync now also covers a machine attached mid-session, not just one present from the start

**What**

When one of your machines gets attached to a Claude Code session partway through, rather than being there from the start, the working directory on that machine is now kept in sync with the session's own checkout of the same repository, on the same branch. A new prompt explains this case specifically.

- The session's own HEAD, branch, and commits stay authoritative and don't change to match the attached machine.

- File changes flow between the two checkouts at points like when a command runs or a turn ends.

- If the two checkouts drift apart (diverge), the prompt describes what happens in that situation.

**Why**

This lets a machine joining a session later behave consistently with one that was synced from the start, so attaching a machine mid-session doesn't leave its files silently out of step with what the session is working on.

- Area: Directory Sync
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Kitty graphics protocol gains file-based image transfer and a cell-size query

Terminal image display can now send images by file reference and query the terminal's cell size

**What**

For terminals that support the kitty graphics protocol (a way for terminal programs to display images inline), Claude Code can now send an image by referencing a file path or shared-memory name, instead of only sending the image data inline as base64 text. It can also now ask the terminal how big a single character cell is, measured in pixels.

**Why**

Sending images by reference rather than embedding them as text can be more efficient for compatible terminals, and knowing the terminal's cell size in pixels helps size or position images correctly when they're displayed inline.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Permission-mode changes now wait for server confirmation before taking effect

Switching permission mode now waits for the server to confirm the change before applying it

**What**

When Claude Code changes its permission mode (the setting controlling what actions it can take without asking), it now first sends that change to the server and waits for confirmation. If the server doesn't accept the change within a time window, the permission-mode change is blocked and an explicit reason is shown, instead of the change silently taking effect anyway.

**Why**

This prevents a session's permission mode from getting out of sync between the local client and the server, so a change that failed to save doesn't get applied locally without the user knowing.

- Area: Permissions
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### MCP tools can now background early when a new message arrives

Long-running MCP tool calls can now background early to let a new message through

**Unclear.** Nothing has been read yet about the `tengu_mcp_tool_auto_backgrounded` gate for this site's account.

**What**

Previously, a long-running MCP (Model Context Protocol, a way for Claude Code to connect to external tools) tool call was only moved to the background after a fixed auto-background timeout elapsed. Now, it can also be moved to the background as soon as a new message needs to reach the session while the tool is still running, whichever happens first. The notification shown to the user now explains this: the task was moved to the background "so that a message that arrived while it was running can reach you; it was not interrupted and keeps running." The `tengu_mcp_tool_auto_backgrounded` telemetry event now records a `trigger` property distinguishing whether backgrounding happened because of a message delivery or a timeout.

**Why**

This keeps a slow MCP tool call running in the background instead of blocking new messages from getting through, while making clear to the user that their tool call wasn't interrupted, just moved aside.

- Area: Background Tasks
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### New robustness pass for improved terminal text-wrapping that is ANSI/control-sequence aware

Terminal text-wrapping rewritten to correctly handle ANSI codes, with a verified fallback

**What**

Claude Code's terminal text-wrapping logic (which decides how to break long lines of text to fit the terminal width) has been rewritten to properly account for ANSI escape and control sequences, the invisible codes terminals use for things like color and cursor movement. The new approach temporarily replaces these sequences with a placeholder character while wrapping, then verifies that the wrapped result still reconstructs the original text correctly. If that verification fails, it falls back to a simpler, character-based wrapping method and marks the result as "degraded." This replaces the previous text-measurement approach entirely.

**Why**

This reduces the chance that colored or otherwise styled terminal output gets wrapped incorrectly, while the verification-and-fallback approach means a wrapping bug degrades gracefully to a simpler method instead of producing broken output.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Ultrareview (`/review`-style remote precondition) now accepts a base commit, not just a branch name

Remote ultra-review (/code-review ultra) now accepts a base commit, not just a branch name

**Unclear.** Whether this applies to /review as well as /code-review ultra, and what exactly the first-commit-only mode changes about the review, is not stated.

**What**

The precondition check that runs before a remote deep review (invoked via `/code-review ultra`, sometimes called ultrareview) now accepts a commit as the target, not just a branch name. Previously, if you passed something that wasn't a branch in the current repo, the check would fail; now it also accepts a commit reference. A related bundling step also gained an optional "first commit only" mode, tracked in a new `first_commit` telemetry field recorded when a diff is too large to review.

**Why**

This gives you more flexibility in what you can point a remote deep review at, letting you target a specific commit instead of requiring a named branch.

- Area: Code Review
- Names: `/code-review ultra`
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Precise pointer / SGR-Pixels mouse mode built out, including a fine-pointer hold/retain mechanism

Claude Code adds support for xterm's precise pixel-coordinate mouse mode (SGR-Pixels)

**What**

Claude Code's terminal handling now supports xterm's SGR-Pixels mouse reporting mode (mode 1016), which reports mouse position in exact pixel coordinates rather than character cells. This includes new parsing for the pixel-coordinate escape sequences, the sequences to turn the mode on and off, a coordinate normalizer, a new `fine` field on mouse events, and a hold mechanism (`retainFinePointer`) that keeps fine-pointer tracking active across parts of the render pipeline.

**Why**

This is groundwork for more precise mouse interaction in the terminal, such as accurately targeting small UI elements or fine-grained drag gestures, in terminals that support this xterm mode.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Gateway proxy can become the sole egress-boundary/SSRF check

OIDC sign-in requests now also route through the proxy when the gateway proxy is set as the sole egress boundary

**What**

When a gateway deployment declares its outbound proxy as the sole boundary for outbound network safety checks (via `CLAUDE_GATEWAY_PROXY_IS_EGRESS_BOUNDARY`), Claude Code stops doing its own hostname-resolution and loopback checks and simply hands hostnames to the proxy. As part of this, OIDC identity-provider sign-in requests now also check this new state as a fallback for whether to use the proxy, when that isn't explicitly set elsewhere, and the log message shown when proxying is used is worded slightly differently depending on whether proxy use was explicitly configured.

**Why**

This keeps sign-in traffic consistent with the rest of outbound traffic when a gateway has taken over egress safety checks, instead of leaving OIDC requests on the old behavior.

- Area: Gateway Proxy
- Names: `CLAUDE_GATEWAY_PROXY_IS_EGRESS_BOUNDARY`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Artifact publish: new 429 rate-limit and 'contract rollout' error classification

Artifact publishing now recognizes generic 429 rate limits and a new 'contract rollout' error for outdated contracts

**What**

When publishing an artifact fails, Claude Code now recognizes more error cases:

- A generic 429 (too many requests) response is now classified as `rate_limited` and comes with a retry-after message, in addition to the existing capacity-cap 429 case

- A new `contract_rollout` error code is added for 422 responses that match wording indicating a contract "is newer than the preferred" one, when a `latestContract` flag is set

**Why**

This gives clearer, more specific error messages when artifact publishing is blocked by rate limits or by a contract version mismatch, rather than a generic failure.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Rate-limit usage response strips 'limits' when status is 'seeded'

Rate-limit usage responses no longer include per-limit detail when status is 'seeded'

**Unclear.** What the 'seeded' status specifically represents, and why per-limit detail is excluded for it, is not stated

**What**

When the rate-limit status returned is `seeded`, Claude Code now removes the `limits` field before building the rate-limit usage object it returns, so a seeded response no longer includes the detailed per-limit breakdown.

**Why**

This changes what information is available when rate-limit usage is in the 'seeded' state; per-limit detail won't show up for that case anymore.

- Area: Rate Limits
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Model 'fable' family label simplified to just a name

The 'fable' model family's picker entry lost its description text, now shows just a name

**What**

The code that builds a model picker entry for the "fable" model family used to return a rich object including a label and description text ("most capable for your hardest and longest-running tasks"). It now just returns the model's display name, or nothing if there isn't one.

**Why**

This means the picker no longer shows explanatory description text for the fable family in this particular code path, just its plain name.

- Area: Models
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Artifact publishing gets dedicated rate-limit error messages and retry-after handling

Artifact publishing gets specific error messages for rate limits and version conflicts

**What**

When publishing an artifact fails, Claude Code now shows more specific messages instead of a generic failure. This covers:

- Being rate-limited, with a message that nothing was published and to try again

- A version conflict where the server's contract is newer than the one being published against, surfaced as a distinct handshake error

- Retry-after guidance, telling the user how long to wait, including a callout about the reserved slug involved

**Why**

This makes it clearer to users why an artifact publish failed and what to do about it, rather than a vague error.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Artifact publish preflight/upload now detects and reacts to 429s mid-flow

Artifact publish now detects mid-flow rate limiting and reports which step was refused

**What**

The artifact publishing process now checks each step of its preflight and upload sequence for rate-limit (429) responses. When one is hit, Claude Code reports the reserved slug involved and specifically which step was refused, such as staging the files being copied for the publish.

**Why**

This gives a more precise error when a publish is rate-limited partway through, rather than failing without indicating what stage it happened at.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Skill/tool file-path arguments now reject network locations, and gain a 'below' parameter

Skill/tool file-path arguments now reject paths pointing to unreachable network locations, and gain a new 'below' path check

**What**

Validation of file-path arguments for skills and tools now checks a new `below` path parameter in addition to the existing one. Either path is rejected if it points to what Claude Code determines is a network location not reachable from the current setup, such as a different git remote or host than the current worktree.

**Why**

This prevents skill or tool file-path arguments from pointing at git locations that Claude Code can't actually reach, catching a class of invalid paths earlier.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Tool-execution error/telemetry logs now redact tool names and truncate error content by structure, not raw text

Tool error and permission-denial debug logs now report structured metadata instead of raw tool names and text snippets

**What**

Local debug log lines for tool input validation errors, validate-input rejections, permission denials, and runtime tool errors no longer include a raw slice of the offending input, message, or error text. Instead they report structured details: issue codes, byte/character counts, and error codes. These log lines also now use a new classifier that labels skill tools, MCP tools, and dynamically-named tools with a generic label like `skill_tool`, `mcp_tool`, or `dynamic_tool` instead of printing the tool's literal name.

**Why**

This keeps potentially sensitive tool names and raw error content out of debug logs while still giving useful, structured information for diagnosing tool failures.

- Area: Tool Validation
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Cloud/remote hook execution now inspects a script's shebang line, not just its declared interpreter

Cloud/remote hook execution now reads a script's actual shebang line, not just its declared interpreter

**What**

When deciding whether a hook script is safe to run in a cloud or remote session, if the script doesn't declare an interpreter, Claude Code now reads the file's own shebang line (the `#!` line at the top of a script that names its interpreter). It withholds the hook if that interpreter is 'unjudgeable', or if it isn't a plain absolute path or a recognized `env`-based form. Acceptable examples include an interpreter found on your `PATH` via `#!/usr/bin/env python3`, or one named by a full path outside what the session can write, with no options or only simple, recognized switches like `bash -eu` or `python3 -I`.

**Why**

This closes a gap where a hook script without a declared interpreter could otherwise bypass the safety checks that govern what's allowed to run in cloud or remote sessions.

- Area: Sandbox
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Code-attribution report can be computed against a different repo root than the current session

Fixes the claude/human code-attribution report to use the right repo root when computing contribution splits

**What**

The code-attribution report, which totals up how much of your code came from Claude versus a human, could get confused about which repository it was reporting on. It now separately resolves the repo root that was actually requested and the repo root the current session is really using, and only re-fetches ignored-file information for each root when they differ. Each file's Human/Claude split is now looked up using a key that includes which root it belongs to, with a fallback if the root doesn't match.

**Why**

This prevents the report from mixing up contribution data across different repository roots, so the numbers you see for a given repo actually reflect that repo.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Device hooks now hold back if the sender is unattested

Device hooks now refuse to act when the sender's attestation can't be verified

**What**

Device hooks are checks that run against actions coming from another device. The dispatcher that runs these hooks now first checks whether the sender is "attested" (verified as legitimate). If the sender is held back because it isn't attested, the hook logs a message saying it was held back and gives no opinion, instead of continuing on to its usual muted-check and dispatch logic.

**Why**

This stops device hooks from acting on input from a sender whose identity or trustworthiness can't be confirmed, reducing the risk of unverified devices influencing a session.

- Area: Sandbox
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### New atomic plugin-version directory swap with byte/entry-budgeted tree comparison

Plugin version installs now swap in atomically after comparing the new and old file trees under a size budget

**What**

Installing a new version of a plugin now goes through a new subsystem that first compares the newly staged version's files against the currently installed copy, checking permissions, ownership, hardlinks, binary hook files, and `node_modules`, within a limited comparison budget. If the two are identical, the existing install is kept as-is. Otherwise, the old copy is atomically moved aside, the new version is published in its place, and the old copy is restored automatically if the swap fails partway through. On Windows, where directories can be temporarily locked, the swap retries with backoff, and it also guards against races when two installs happen at once.

**Why**

This makes plugin version upgrades safer: an interrupted or failed update no longer risks leaving a plugin half-installed, and identical reinstalls are skipped rather than redone unnecessarily.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Artifact publish now handles server rate limiting explicitly during upload/copy

Artifact publish now handles server rate-limit responses explicitly during upload and copy, showing a retry-after time

**What**

When publishing an artifact, the file-upload and cross-artifact-copy steps now specifically detect a rate-limited response from the server and call a dedicated handler for it, instead of treating it as a generic 'upload unavailable' error. The final error message shown for a failed deploy now includes a `retryAfter` value read from the server's response headers.

**Why**

This means that if artifact publishing is rate-limited by the server, you now get a clearer error that tells you when to retry, rather than a generic failure message.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Attribute-aware snapshot staging now detects and reports writes racing the read pass

Git snapshotting now detects and reports files edited right as the snapshot pass begins, not just mid-read

**What**

When Claude Code takes a snapshot of your git working tree, it now tracks when the snapshot pass started and flags files with a new `sincePassStart` marker if they were modified right at that moment, producing a distinct error message for that case instead of lumping it in with files changed mid-read. The diff comparison also now passes `--ignore-submodules=dirty`, and previously-verified files that turn out unstable are re-applied via `update-index`.

**Why**

This makes race-condition errors during snapshotting more precise, so if a file changes right as Claude Code starts reading your working tree, you get a clearer explanation of what happened instead of a generic error.

- Area: Git Internals
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Plugin install/publish path reworked with a non-strict-cache fast path

Installing plugins without strict caching now uses a faster path that replaces any existing copy directly

**What**

When publishing or moving a plugin during install, plugins that don't use `strictCache` now take a new fast path: Claude Code drops the `.git` folder from the staged clone and installs it directly, replacing any already-installed copy, instead of going through the version-cache rename process used for `strictCache` plugins. The publish step now also returns an explicit 'published' status.

**Why**

This speeds up and simplifies plugin installation for plugins that don't need strict caching, at the cost of always overwriting the existing installed copy rather than preserving it.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Clearer error message when a plugin can't load because its marketplace isn't registered

Plugins that fail to load from an unregistered marketplace now get a specific explanatory error

**What**

When a plugin can't load because its marketplace source isn't known during this session (it's not in `known_marketplaces.json`, or it's listed under `extraKnownMarketplaces` but unusable), Claude Code now shows a specific diagnostic explaining why, and tells you to run `claude plugin marketplace add <path-or-repo>` to fix it. Previously this failed silently or with a generic marketplace-not-found error.

**Why**

This saves you from guessing why a plugin silently didn't load, and points directly at the fix.

- Area: Plugin Install
- Names: `claude plugin marketplace add`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Directory-sync uploads now request-signed via client_request_signer

Directory-sync file uploads and downloads are now cryptographically signed before being sent

**What**

The directory-sync client used for uploading and downloading session files now signs each upload's content, path, and `ifMatchSha256` value using a request-signer before sending it. If signing fails, Claude Code logs a warning once and records a telemetry event.

**Why**

Signing requests helps verify that directory-sync uploads haven't been tampered with in transit. The one-time warning and telemetry event mean a signing failure won't go unnoticed while also not spamming logs.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Session resume now restores accumulated cost from history file

Resuming a session now restores its accumulated cost from the saved history instead of resetting to zero

**What**

When you resume a previous session using a `history_file`, Claude Code now reads a saved `restoredCostUsd` value from that file and carries it forward into the resumed session.

**Why**

Previously, resuming a session likely lost track of how much the earlier part of the conversation had already cost. Now the cost total picks up where it left off, keeping cost tracking accurate across a resumed session.

- Area: Sessions
- Names: `restoredCostUsd`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Git snapshot/sync pass gains richer refusal reasons and pacing controls

Claude Code's git snapshot process now gives more specific refusal reasons and can pace itself with new timing controls

**What**

The internal process that builds a snapshot of your git working tree now accepts new timing controls (`stageHooks`, `budgetMs`, `lastDescribed`, `passStartedAtMs`) to control its pacing. When it refuses to include something in a snapshot, it now reports a structured reason: `rules_unreadable` (ignore rules couldn't be read), `staged_protected` (protected files are staged), `credential_named` (a file looks like it holds credentials), or `committed_protected` (protected files are already committed). Snapshot output also now separately reports files withheld for being unspellable, alongside other withheld categories.

**Why**

More specific refusal reasons make it clearer why certain files were left out of a git snapshot, and the new pacing controls let the process run without blocking for too long at once.

- Area: Git Internals
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Artifacts publish confirmation now cites sources and marks scratchpad files

The Artifact publish confirmation prompt now names the source artifacts being copied and flags files that live in the scratchpad

**What**

The confirmation prompt shown before publishing an Artifact was reworked to explicitly list the source artifacts, by title, when files are being copied server-side from more than one source. It also now marks file paths that live "in scratchpad" (a working/temporary area) in that confirmation message.

**Why**

This gives more detail in the publish confirmation prompt, making it clearer where the content being published is actually coming from before you approve it.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Multi-store-sync's empty-receipt handling loses its tengu_typed_koala gate and moves inline

Clearing a stale empty store receipt before syncing no longer depends on the tengu_typed_koala flag

**What**

Claude Code keeps local "receipts" on disk to track whether a data store has been synced. Previously, clearing out a stale or empty receipt before a sync required a feature flag called `tengu_typed_koala` to be turned on, in addition to two other conditions. That flag check is now gone: the logic runs unconditionally, and the two other conditions (whether the on-disk receipt is empty, and whether a pull has already happened) have moved into the function that does the actual work.

**Why**

This behavior no longer depends on a feature flag, so it applies the same way everywhere rather than only when that flag was enabled for a given account.

- Flag `tengu_typed_koala`: On for this account, and not off by default (read for one account on one subscription tier against v2.1.277; this account: on, anonymous baseline: on, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Team Memory
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Terminal image (kitty graphics) file-backed transmission gets an active capability probe

Claude Code now actively tests whether the terminal can read image files before sending screenshots that way

**What**

For terminals that support the kitty graphics protocol (a way of showing images in a terminal), Claude Code used to just assume the terminal could read image files it wrote to disk. It now actively tests this: it writes a small temporary image file, asks the terminal to display it, and checks the terminal's reply. It logs "Terminal image files: yes/no" along with the reason, and falls back to sending image data directly (inline) if the test fails or gives no clear answer.

**Why**

This avoids broken or missing images in terminals that claim kitty graphics support but can't actually read locally-written image files, by verifying support before relying on it.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### File reads hardened against symlink/TOCTOU races (boundRead)

File reads are now hardened against symlink-swap race conditions

**What**

A new internal function, `boundRead`, is used for file reads. It resolves a file's real path first, then opens it using flags that refuse to follow symlinks (`O_NOFOLLOW` on Linux, `F_NOFOLLOW_ANY` on macOS), and on Linux also double-checks `/proc/self/fd` to confirm the opened file matches the expected path. If a symlink (a file that points to another location) is found along the way, or the opened file doesn't match what was expected, the read is refused and a warning is shown.

**Why**

This protects against a class of security bug sometimes called TOCTOU (time-of-check-to-time-of-use), where a file is swapped for a symlink to a different, unintended file between the moment Claude Code checks it and the moment it actually reads it.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Plugin onboarding flow adds a fallback productivity-plugin search when no role was picked

Onboarding now searches for a productivity plugin when no role is picked, and hides the recommendation if none is found

**What**

During plugin onboarding, if a user skips or dismisses the role picker, Claude Code now runs a `SearchPlugins` search for a productivity plugin (after first checking `ListPlugins`) instead of always suggesting one. If that search comes back empty, the recommendation widget is skipped entirely rather than shown unconditionally.

**Why**

This stops the onboarding flow from recommending a plugin that doesn't actually exist for the user, since the recommendation now only appears when a real match is found.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Coordinator sessions blocked from reading worker transcripts/task outputs via shell tricks

Coordinator agents are now blocked from reading worker transcripts or task outputs via shell workarounds

**What**

When an agent acting as a 'coordinator' (an agent that manages other worker agents) tries to run a shell command, Claude Code now rejects commands that attempt to read a worker's transcript file or task output directory indirectly, including via:

- command substitution (`$(...)`)

- a variable

- a `~name` shorthand path

- a `..` path segment

- an overly broad wildcard pattern

**Why**

A worker's result is meant to be read through the proper channel, the task notification or an explicit request to the worker, not by having the coordinator shell directly into the worker's transcript files. This closes off ways that check could previously be bypassed.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### New shebang-interpreter vouching check for cloud/teleported script execution

Scripts run from a cloud session now get their interpreter line checked before being trusted to execute

**What**

Before running a script that came from a cloud or "teleported" session, Claude Code now parses its shebang line (the `#!` line naming the interpreter) and classifies it as: an absolute path, a program resolved via the environment, a path relative to the current directory, or "unjudgeable" (for example, a relative interpreter, an environment call with extra options, or an interpreter that itself takes a file argument).

**Why**

If the interpreter can't be confidently identified and vouched for, execution is held back with an explanation instead of running blind. This guards against a script from a cloud session quietly loading settings or code from the checkout in a way that couldn't be verified, such as via `bun`, `tsx`, `lua`, or `Rscript` without `--vanilla`.

- Area: Sandbox
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### New slash-command relay refusal path for unverified Slack turns

Slash commands from unverified Slack messages can now be blocked before relaying

**What**

When a message coming through Slack looks like a slash command but didn't go through the existing bridge-slash-override handling and isn't confirmed to be from a verified human Slack user, a new check called `resolveRelaySlashRefusal` now runs and can block the message from being relayed.

**Why**

This closes a gap where an unverified Slack message could otherwise trigger a slash command, adding a safeguard against unauthorized or spoofed command execution through Slack integrations.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### New in-session permission check before forwarding a tool call to a bound/remote host

Subagent tool calls to a remote or bound machine now get an in-session permission check first

**What**

Before a subagent's tool call is forwarded to a remote or bound machine (another device linked to the session), Claude Code now runs an in-session permission check first. If that check denies the call, it is refused immediately with the outcome `rejected_in_session` and never actually reaches the remote machine.

**Why**

This adds a permission checkpoint on the originating session's side before a tool call ever leaves for another machine, rather than relying solely on whatever permission handling exists on the remote end.

- Area: Remote Machines
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Pasted content is now screened and can be stripped from the fleet dispatch and fleet reply composers

Fleet dispatch and reply composers now screen pasted content and can block sending until it's cleaned up

**What**

Before a fleet command is dispatched or a fleet reply is sent, any pasted text or content is now run through a filter that can remove parts of it. If anything gets removed, the send is stopped, the message is rewritten to the cleaned version, and the user sees a hint, either "empty" or "review", instead of the message going out as originally pasted.

**Why**

This catches problematic pasted content before it's sent as part of a fleet command or reply, giving the user a chance to review what was removed rather than sending it unchecked.

- Area: Fleet
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Directory-sync bookkeeping now distinguishes real agent commits from sync's own snapshot commits

Directory sync now tells you when a branch was pointed at its own internal snapshot commits, not your real work

**What**

Directory sync (the feature that keeps a local folder in step with a remote work branch) now keeps a separate count of "bookkeeping" commits that directory sync created internally for its own snapshots, as opposed to commits that represent actual work. If a work branch ends up pointed at one of these internal snapshot commits, the message shown to the user now says so explicitly, rather than telling the user to re-commit or cherry-pick commits that were never really theirs.

**Why**

Before this change, users could be told their commits were "kept" or need re-applying when in fact those commits were only directory sync's own internal bookkeeping, which was confusing and could send people looking for work that never existed. The clearer message avoids that confusion.

- Area: Directory Sync
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Sandboxed-bash auto-allow now excludes commands matching rz()

Sandboxed auto-allow for Bash commands now excludes commands matching an additional check

**Unclear.** The finding does not say what kinds of commands the new exclusion check matches.

**What**

When sandboxing and "auto-allow if sandboxed" are both enabled, Claude Code could previously let a Bash command run without asking for approval. Now that auto-allow also requires that the command does not match a new exclusion check, meaning some commands that would have been auto-allowed before will now still require approval.

**Why**

This tightens the conditions under which sandboxed Bash commands skip approval, reducing the chance that a command that shouldn't be auto-approved slips through.

- Area: Bash Safety
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Slash-command remote-control gating extended to a second 'relay' surface

Slash-command blocking over Remote Control now also covers a second 'relay' connection surface

**Unclear.** Nothing has been read yet about whether the `tengu_slash_command_unavailable` gate is on or off for this site's account.

**What**

Claude Code can block slash commands that aren't available when used over Remote Control (controlling Claude Code from another device). This blocking logic previously only applied to the "bridge" surface; it now also applies to a second surface called "relay". The shared telemetry and messages for blocked commands now record which of the two surfaces triggered the block.

This behavior is controlled by a gate named `tengu_slash_command_unavailable`.

**Why**

This closes a gap where slash commands unavailable over Remote Control could previously go unblocked when accessed through the relay surface instead of the bridge surface.

- Area: Remote Control
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Multi-machine sessions now distinguish a separate synced checkout from the primary one

Multi-machine session messages now distinguish a synced mirror from a separate, unsynced copy

**What**

When a session shows which machines are attached to it, Claude Code now handles a new case: the current session's checkout being the primary copy of the project, while a named machine holds the user's own separate copy with nothing synced between the two. This gets its own explanatory text, distinct from the existing case where a machine holds a synced mirror of the project.

**Why**

This makes it clearer when working across multiple machines whether changes on one machine will show up on another, avoiding confusion about whether two checkouts are actually kept in sync.

- Area: Remote Machines
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Projects tool's org-policy-disabled message is now dynamic, and Projects context is retried after a policy cache miss

Projects-disabled-by-policy message is now dynamic, and access retries after policy resolves

**What**

The fixed message telling you "Projects is disabled by your organization's policy" has been replaced with dynamic wording driven by the `allow_projects_tool` policy check, so the text now matches whatever the actual policy decision says. Separately, if the policy check for `allow_projects_tool` was previously unresolved (a cache miss) and later resolves to allowed, Claude Code now automatically re-subscribes and rebuilds your project context instead of requiring a restart.

**Why**

This means the message you see about Projects being disabled will more accurately reflect your organization's actual policy, and access to Projects can recover on its own once the policy check catches up, without you needing to do anything.

- Area: Elsewhere
- Names: `allow_projects_tool`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Proxy request forwarding gains an explicit header allow/deny list

Proxy request forwarding now strips sensitive headers and keeps only an allowed set of prefixes

**What**

When Claude Code forwards requests through a proxy, it now applies explicit rules about which HTTP headers (the metadata sent alongside a request) are allowed through. Headers considered sensitive or connection-specific, such as `authorization`, `x-api-key`, `host`, and `content-length`, are stripped out. Headers whose names start with certain prefixes, including `anthropic-`, `x-stainless-`, `x-claude-gateway-`, `x-goog-`, `x-amz-`, and `x-amzn-`, are kept. New validity checks also confirm header names and values are well-formed.

**Why**

This reduces the risk of sensitive credentials or connection-specific headers leaking through a proxied request, while still allowing the specific headers that upstream services need to function correctly.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Reminders about kept/discarded output now default to full scope

Reminders about kept-or-discarded output now default to reaching the whole conversation instead of being off

**What**

The `tengu_sleepy_snowflake` setting controls how widely Claude Code delivers a reminder about content it produced that was later "kept" or discarded from the visible conversation. When no explicit value is set remotely, this setting now falls back to `"all"` scope instead of `"off"`. It still only takes effect when using a first-party Anthropic model, with a master toggle and per-conversation state also required.

**Why**

With the fallback changed from off to all, this type of reminder reaches the full conversation by default rather than not appearing at all, when no other configuration overrides it.

- Flag `tengu_sleepy_snowflake`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Elsewhere
- Names: `tengu_sleepy_snowflake`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Handback provenance flag now defaults on

The setting controlling subagent report anti-injection wrapping now defaults to on

**What**

When a subagent (a delegated helper instance of Claude) finishes a task, its report can be wrapped with a preamble marking it as model output with no user authority, so instructions embedded in it can't be mistaken for the user's own commands. This is controlled by the `tengu_melodic_wolf` setting (overridable with the `CLAUDE_CODE_HANDBACK_PROVENANCE` environment variable), which now falls back to true instead of false when no other value is set.

**Why**

With the fallback now true instead of false, this protection is positioned to apply more broadly by default, guarding against text inside a subagent's report being misread as a direct command.

- Flag `tengu_melodic_wolf`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Subagents
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Reminder scope defaults from off to all

Reminder-scope setting now defaults to 'all' instead of 'off' when unset

**What**

The control that decides whether a category of injected reminders (contextual notes Claude Code adds to a conversation) applies to just the current thread, all threads, or none now defaults to "all" when no server or client value is set for it, instead of defaulting to "off" as before.

**Why**

With this fallback changed, conversations that don't have an explicit setting will now receive these reminders across all threads by default rather than none, which can mean more reminder-related content showing up unless configured otherwise.

- Flag `tengu_sleepy_snowflake`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Elsewhere
- Names: `tengu_sleepy_snowflake`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### tengu_melodic_wolf fallback flips true

The tengu_melodic_wolf gate behind subagent report provenance now defaults to on if unset

**What**

A setting called `tengu_melodic_wolf`, which controls whether subagent reports get an anti-injection wrapper (checked via the `CLAUDE_CODE_HANDBACK_PROVENANCE` environment variable), now falls back to true by default when nothing else decides it. Previously it defaulted to false.

**Why**

This changes what happens when no environment variable or remote flag overrides the setting, but nothing has been read yet about how this particular gate is currently configured for this build, so it's not yet known whether the protective wrapping is actually active.

- Flag `tengu_melodic_wolf`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Subagents
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### HIPAA/ZDR compliance gates tighten cache-miss defaults

HIPAA/ZDR compliance checks now default to blocking, not allowing, when the compliance cache is empty

**What**

Three compliance-gated capabilities change their behavior for when compliance status hasn't been cached yet (a cache miss):

- `Projects` tool access now defaults to holding (pausing pending confirmation) instead of allowing

- `Team onboarding` now defaults to holding instead of allowing

- `Peer messaging` now defaults to denying outright instead of allowing

**Why**

This makes these compliance-sensitive features fail closed rather than open when the system doesn't yet know an organization's HIPAA or zero-data-retention (ZDR) compliance status, reducing the risk of allowing something that should have been blocked while status is still unknown.

- Area: Compliance
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Fine-grained (pixel) mouse tracking support added

Terminal mouse tracking gains pixel-precision (SGR-pixels) support

**What**

Claude Code's terminal handling now supports a finer-grained mouse tracking mode (SGR-pixels, mode 1016) in addition to existing mouse tracking. Mouse events now carry a `.fine` field with the raw fractional pixel position, and a new helper converts pixel offsets into row/column coordinates plus this fine-grained payload.

**Why**

This allows terminal interactions that need more precise pointer positioning than whole character cells to work correctly, for terminals that support pixel-level mouse reporting.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### File-sync staging now uses an ownership/permission-checked private folder, with the old auto-cleanup keyed differently

File sync now stages files in a private, permission-checked folder and skips it during cleanup

**What**

When Claude Code syncs files, it now moves them through a dedicated staging folder that is locked down to the current user only (permission mode 0700, meaning only the owner can read, write or enter it). Before using this folder, Claude Code checks that it and its parent folder are genuinely owned by the current user with no group or other access. If the check fails, it deletes the folder and refuses to use it, reporting one of several specific reasons: it could not be created, it is not owned solely by the current user (which can happen on drives that don't preserve file permissions), or it turned out to be a symbolic link or another user's folder.

The existing cleanup routine that removes old staging folders has also been updated to skip the one that is currently in active use.

**Why**

This prevents another user on a shared machine from tampering with or reading files while they're being staged for sync, and stops the cleanup process from accidentally deleting a staging folder that a sync is actively using.

- Area: File Sync
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Usage-limit warning message reworked with remote-configurable copy and added link

Usage-limit warning now uses remote-managed text and links to clau.de/wrap-up

**Unclear.** Whether the new wording, link, and remote-config behavior are active for any given user depends on the `tengu_lantern_sconce_copy` and `tengu_lantern_sconce` gates, which haven't been read for this site's account.

**What**

The "Usage limit reached" notification that appears while a grace period is active (a temporary window after hitting a usage limit) now pulls its headline wording from a remote-configurable source instead of fixed text baked into the app, and its wording changes from "resets ..." to "limit resets ...". The notification also now includes a new, dimly styled clickable link to `clau.de/wrap-up` in addition to its existing rate-limit-type text.

**Why**

Pulling the message text from a remote source lets Claude Code update the wording of this notification without shipping a new release, and the added link gives users a direct place to go for more information when they hit a usage limit.

- Flag `tengu_lantern_sconce_copy`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Flag `tengu_lantern_sconce`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Rate Limits
- Names: `clau.de/wrap-up`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Session-inbox relayed messages can now carry attachments

Relayed session-inbox messages can now include attachments

**What**

Messages relayed through the session inbox (used for things like Slack messages reaching a session) can now carry attachments. The message event builder accepts an optional attachments argument and includes it in the message data sent to the session. The `attachments` field has also been added to the list of fields treated as untrusted, alongside the existing `body`, `sender_display`, and `slack_permalink` fields.

**Why**

This lets relayed messages carry file or media attachments rather than just text, while still treating that attachment data as untrusted input like the rest of the relayed message.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Artifact tool guidance expanded to cover creating and reading design systems

Artifact tool instructions now explicitly cover creating and reading design systems

**What**

The internal instructions that tell the model how to find and use artifact types now explicitly mention design systems, including ones built from your own codebase, as something the quickstart and list-types steps should handle. A new rule classifies design-system requests under an `intent: "other"` category, and a new instruction tells the model to look up and read an existing design-system artifact when answering questions about it, falling back to searching your files if no such artifact is listed.

**Why**

This makes Claude Code better able to recognize design-system-related requests and answer questions about an existing design system using the artifact itself, rather than treating it like an unrecognized artifact type.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Bash auto-allow-when-sandboxed gets an extra command-content block

Bash's auto-allow-when-sandboxed path now also checks command content before skipping confirmation

**Unclear.** What specifically the new command-content check looks for is not stated in the finding.

**What**

The fast path that lets Bash commands run automatically when they're sandboxed now also checks the command's content via a new check, in addition to the existing checks for sandboxing and reading outside the current directory. If that new check flags the command, auto-allow is skipped.

**Why**

This adds another condition that can prevent a sandboxed command from being auto-approved, tightening the criteria for when Claude Code will run a Bash command without asking first.

- Area: Bash Safety
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Plugin extraction now detects tampering while a plugin loads

Plugin loading now detects if a plugin's files are removed or replaced while it's being loaded

**What**

When Claude Code extracts a plugin's files to disk to load it, it now records identifying details of that directory (its device, inode, and creation time) beforehand and checks them again afterward. If the directory was removed or replaced with something else during loading, Claude Code now throws an error saying the plugin directory "was removed before it could be loaded" or "was replaced while it was being loaded," instead of silently continuing.

**Why**

This guards against a plugin's files being tampered with or swapped out during the brief window while it's being loaded, so Claude Code doesn't end up loading unexpected content without noticing.

- Area: Plugin Install
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Marketplaces declared only in settings are now reconciled and logged

Plugin marketplaces listed only in settings are now validated and reconciled automatically

**What**

If a plugin marketplace is referenced in your settings but hasn't yet been recorded in the internal `known_marketplaces.json` tracking file, Claude Code now checks it: it validates the declared source and path, and either admits it (letting plugins load from it right away, with a note that it will be formally recorded once a background reconcile step runs) or records why it was skipped, such as an invalid source type, an unanchored path, a manifest not found under `.claude-plugin`, or a rejection by the registry's admission rule.

**Why**

This closes a gap where a marketplace only declared in settings might not actually get recognized or used, and gives a clear reason when one is rejected instead of it silently failing to load.

- Area: Plugin Install
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Task-management reminders suppressed when the Brief tool has been used

Task-management reminders are now skipped in conversations that used the Brief tool

**Unclear.** The `tengu_humble_zephyr` gate controlling an alternate code path (deferring to `fUo.isBriefEnabled()`) hasn't been read, so it's unclear whether that alternate behavior is active for any account.

**What**

When the internal task-reminder check runs, it now looks for whether the conversation has used the Brief tool. If it has, task reminders are skipped for that turn, at least by default.

**Why**

This avoids nagging you with task-management reminders when you're already working through a Brief-tool workflow, which presumably handles task tracking on its own.

- Flag `tengu_humble_zephyr`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Bridge-relayed messages can now carry pasted content

Messages relayed through the bridge can now carry pasted content, like the SDK already does

**What**

When an inbound message arrives through the bridge (and isn't a peer message or a Slack ping), Claude Code now merges in any attached pasted-content blocks and appends them to the message body, the same way the SDK already handles pasted content. This also triggers the existing `sdk_pasted_content` telemetry event.

**Why**

This lets pasted text reach the model correctly when a message comes in through the bridge, matching behavior that already worked for SDK-originated messages.

- Area: Remote Control
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Fleet command bar and fleet reply composer now strip invisible/injected characters before dispatch

Fleet's command bar and reply composer now strip invisible characters and block sending if any are found

**What**

In FleetView (the interface for managing multiple agent sessions), the slash-command bar and the reply composer now run any pasted or typed text through the same invisible-character stripper used elsewhere in Claude Code. If invisible or injected characters are found and removed, sending is blocked, a hint is shown, and the event is logged under `tengu_prompt_invisible_strip` with a new `surface` value identifying fleet dispatch.

**Why**

This closes a gap where hidden or injected characters could be typed or pasted into fleet commands and replies without the same protection applied elsewhere in the app, guarding against prompt-injection tricks that rely on invisible text.

- Area: Fleet
- Names: `tengu_prompt_invisible_strip`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### CLAUDE_CODE_HANDBACK_PROVENANCE now defaults to enabled (tengu_melodic_wolf flipped to true)

The anti-injection wrapper for subagent reports (CLAUDE_CODE_HANDBACK_PROVENANCE) now defaults to on via the tengu_melodic_wolf gate

**What**

When a subagent (a delegated helper task) finishes and hands its report back, Claude Code can wrap that report with a preamble marking it as model output with no user authority, so instructions embedded in the report can't be mistaken for your own commands. Whether this wrapping happens is controlled by the `CLAUDE_CODE_HANDBACK_PROVENANCE` environment variable, which falls back to the `tengu_melodic_wolf` setting if unset. That fallback's built-in default has now been changed from `false` to `true`.

**Why**

This is the code-level default flip for this protection: instead of assuming the wrapper is off unless explicitly turned on, the code now assumes it should be on unless something says otherwise. Whether it's actually active for any given account still depends on the server-side `tengu_melodic_wolf` setting, which hasn't been read for this release.

- Flag `tengu_melodic_wolf`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Subagents
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### New ripgrep spawn-failure diagnostics with cause-specific advice

Ripgrep search failures now explain the specific cause and give targeted advice

**What**

When Claude Code's search tool (which uses ripgrep under the hood) fails to even start a search, it now explains why in more specific terms, rather than just reporting that the search failed. Recognized causes include the process or thread limit being reached, the system running out of memory, Claude Code itself having too many files open, or the whole system having too many files open. Each cause comes with targeted advice, for example telling the user that Claude Code needs a restart when the problem is too many files open by Claude Code (an "EMFILE" error).

**Why**

This helps users understand and fix search failures instead of just seeing a generic error, and makes clear that when ripgrep can't start, nothing was searched and matching results may still exist.

- Area: Search Tools
- Tier: You'll notice
- Useful: 3/5
- Signal: 1/5

### Credential-scrubbing patterns expanded to include Stripe-style and additional secret formats

Secret-scrubbing now also catches Stripe-style API keys and other additional key formats

**What**

Claude Code scrubs secrets like API keys out of output before displaying or storing it. The list of patterns it checks against has been expanded to include Stripe-style keys, such as those starting with `sk_live_`, `sk_test_`, `sk_prod_`, or `rk_`, along with other additional secret formats.

**Why**

This reduces the chance that a Stripe API key or similar secret accidentally leaks into logs, terminal output, or saved transcripts.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### --tools flag now warns about removed built-in tools

--tools now shows a specific warning when you exclude a built-in tool that's been removed

**What**

When using the `--tools` flag to exclude a tool by name, if that name used to refer to a built-in tool that Claude Code has since removed, the CLI now shows a distinct message explaining that, instead of treating it as if you'd simply mistyped an unknown tool name.

**Why**

This makes it clearer when a `--tools` exclusion refers to a tool that no longer exists, rather than leaving the user to guess whether they made a typo.

- Area: Elsewhere
- Names: `--tools`
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### MCP server management messages now branch on a command-menu surface

MCP server management messages can now point to a command-menu UI instead of the terminal

**Unclear.** Which surface presents the command menu, and when each wording is shown, is not stated in the finding.

**What**

Most response messages for `/mcp enable`, `/mcp disable`, and `/mcp reconnect` now choose between two wordings: the old "Run `/mcp` in the terminal..." text, or a new "Open MCP servers from the command menu." text.

**Why**

This suggests MCP servers (external tool connections) can now be managed from a command-menu surface outside the terminal, not just by running `/mcp` at the command line.

- Area: MCP
- Names: `/mcp`
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Tool result card truncation now groups by identical line value before cutting

Tool output truncation now avoids cutting in the middle of a run of identical lines

**What**

When a large tool-output card is truncated and shown as "N more lines," the logic now scans for consecutive rows that share the same value and only cuts at the boundary between groups, rather than always truncating at a fixed row count as before.

**Why**

This avoids splitting a block of identical or repeated output lines awkwardly across the truncation point, making truncated tool output easier to read.

- Area: Tool Results
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Cloud-session permission prompt for unrecognized hooks reworded

The permission prompt for untrusted hooks in cloud sessions was reworded to be shorter and more actionable

**What**

When a cloud session hits a command check or hook that isn't defined in the user's own settings, and so can't be run automatically for that session, Claude Code shows a permission prompt asking for approval. That prompt's text has been rewritten to be shorter, and now tells the user how to make the check trusted going forward: by reviewing it and copying it into `~/.claude/settings.json`.

**Why**

The clearer wording makes it easier to understand why the prompt is appearing and gives a concrete path to stop seeing it for that same check in the future.

- Area: Cloud Sessions
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Artifact publish rejects remote {artifact,path} file references, requires local copies

Artifact publish now rejects file references into other artifacts, requiring a local copy instead

**What**

When publishing an artifact, the `files` parameter no longer accepts entries shaped like `{artifact, path}` — a reference pointing into another artifact. Such entries now produce a validation error telling the caller to publish from a local copy instead, either a source path inside the artifact's root or an entry shaped like `{from, contentType}`.

**Why**

This closes off publishing files by reference to another artifact, requiring an actual local copy of the content instead, which avoids depending on another artifact's contents at publish time.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### New secret-redaction patterns: Google API keys, Google OAuth client secrets, Stripe-style keys

Secret-redaction now catches Google API keys, Google OAuth secrets, and Stripe-style keys

**What**

Claude Code automatically scrubs sensitive tokens (like personal access tokens) from tool output and logs before they're shown or stored. The pattern matching for this has been expanded to also catch:

- Google API keys (starting with `AIza`)

- Google OAuth client secrets (starting with `GOCSPX-`)

- Stripe-style secret keys (such as `sk_live_` and `rk_test_` prefixes)

All of these are now replaced with `[REDACTED-PAT]` wherever they appear, and a second related redaction table was updated to match them too.

**Why**

This reduces the chance that these kinds of credentials leak into logs or conversation output when Claude Code runs commands or reads files that happen to contain them.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Skill/command permission lock now recognizes reserved settings names

Permissions UI now flags skill/command names that collide with reserved settings keys

**What**

The permissions screen now shows a new state, "reserved-name", when a skill or command's configured name can't be saved into settings because it clashes with a name Claude Code has reserved for its own use. It also shows guidance telling you to rename the skill's folder or the command's file to fix it.

**Why**

Previously this kind of naming collision could silently fail to save; now it's surfaced clearly with a concrete fix.

- Area: Permissions
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Artifact copy/create/publish confirmation dialogs now show artifact/type titles instead of just URLs

Artifact copy/create/publish confirmation prompts now show the artifact's title, not just its raw URL

**What**

When Claude Code asks for permission before copying, creating, or publishing an artifact, the confirmation message now shows the human-readable title of the source or destination artifact (or its type), falling back to "an untitled artifact" or "an artifact type" if no title exists. The raw URL is now shown on its own separate line instead of being woven into the sentence.

**Why**

This makes permission prompts easier to read and understand at a glance, since a title is more meaningful to a user than a bare URL.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Plugin install/update messages now show version-to-version detail

Plugin install messages now show current vs. available version details

**What**

When installing a plugin or when a plugin is already installed, the command-line message now includes more detail comparing the installed version to the available one. If the plugin loads in place from a local or linked source, it notes that it "re-records its version" rather than being reinstalled. If a newer version exists in the marketplace, it says so and hints at the command to update.

**Why**

This gives users clearer visibility into which version of a plugin they have and whether an update is available, instead of a generic install confirmation.

- Area: Plugin Install
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Write tool gives specific errors for directories and special files

The Write tool now gives clear errors instead of failing vaguely when the target is a directory or a device/socket

**What**

The Write tool, which creates or overwrites files, used to only check whether the target path was a symlink before writing. It now also checks for two more cases:

- the target path is a directory, in which case it reports that it's a directory and suggests including a file name in `file_path` to create a file inside it

- the target path is a non-regular file, such as a device, FIFO, or socket, which it now refuses to overwrite, noting that Write only creates or overwrites regular files

Each case gets its own distinct error rather than a generic failure.

**Why**

This gives clearer feedback when Write is pointed at something other than a plain file, instead of a confusing or misleading error.

- Area: File Tools
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Background-task banner shown while a remote-session panel holds a message queue

A new banner tells users when background tasks are queued behind an open side panel during a remote session

**What**

During a remote session (one running on another machine), when a side panel is holding a queue of messages, the chat view now shows a footer line reading something like "a background task update / N background task updates waiting while this panel is open."

**Why**

This lets users know that background task updates are being held back because a panel is open, so they're not surprised by updates arriving all at once once it closes.

- Area: Remote Control
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Device binding now reports a distinct "revoked" failure reason

Device registration failures now report a distinct 'removed from claude.ai devices' reason

**What**

When Claude Code fails to bind (register) this machine as a device, the internal failure report can now include a `revoked` flag, set when the account's registration for this device was specifically removed. This adds a new failure case, shown to users as "removed from claude.ai devices," alongside the existing reasons: hitting the device limit, registration being unavailable, or no keychain being present.

**Why**

This lets you tell apart a device that was actively removed from your account's device list from other, unrelated causes of a failed device binding, making the error message you see more accurate.

- Area: Device Binding
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Device revocation gets its own explanation across binding and file-sync UI

Devices removed from a Claude.ai account now get a specific explanation instead of a generic sync error

**What**

When device binding fails because a machine was removed (revoked) from a user's account on claude.ai, Claude Code now recognizes this as its own distinct reason, `device_revoked`, with a dedicated message explaining that the machine was removed from the account's devices and cannot register again yet. The local-tools and file-sync unbound-session messages now show this specific explanation instead of the generic sync-error text.

**Why**

This gives a clearer explanation when a device stops working because it was deliberately removed from the account, rather than showing a generic error that could be mistaken for a temporary sync problem.

- Area: Device Binding
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Artifact type-listing narrowing switches from substring match to fuzzy best-match

Artifact type filtering switches from plain substring search to fuzzy best-match ranking

**What**

When listing Artifact types (categories used for shared Artifacts), the `type_query` parameter used to work as a simple case-insensitive substring filter. It now ranks results by how well they match and drops weaker matches instead of just checking for a substring. Claude is now instructed to only use this parameter when a previous listing without it indicated more types exist than were shown.

**Why**

A fuzzy best-match search can find relevant types even when the query doesn't exactly appear as a substring, though it also means a narrowed listing might not show the entire catalog of types, since weaker matches are deliberately left out.

- Area: Artifact Publish
- Names: `type_query`
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Review scope adds a 'first commit' case

Code review now explains clearly when a repo's only commit is its first one

**What**

When running a code review on a repository whose entire history is just its first commit, Claude Code now shows a dedicated message explaining that every file in that first commit is being reviewed because there's nothing earlier to compare against. Previously this situation fell through to a generic "no merge base" message. A companion error message also explains that a brand-new repository needs at least one commit before review can work.

**Why**

This gives a clearer, more accurate explanation for a very new repository, instead of a generic message about a missing comparison point that wouldn't clearly explain what's actually going on.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Artifact publish preserves reservedSlug on failure (except for PR-review pages)

Failed artifact publishes now keep their reserved slug so a retry can reuse it, except for PR-review pages

**What**

When publishing an artifact fails, Claude Code now carries the `reservedSlug` (the reserved address for the artifact) forward in the failure result, so that a retry can reuse the same slug instead of getting a new one. This applies unless the artifact's slug is stranded, conflicting, or gone, and unless the artifact is a `pr_review` page.

**Why**

This avoids unnecessarily losing a reserved slug when a publish attempt fails, making retries more consistent, while excluding PR-review pages and problem-slug cases where reuse wouldn't make sense.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### New project-sync status: user's disconnected separate copy

A new status message distinguishes your own disconnected project copy from a generically unsynced one

**What**

When Claude Code shows the sync status of a session's project directory, there's now a distinct message for the case where the directory is your own separate copy with sync turned off: "project at ... (the user's own separate copy, not synced with this session)". Previously this situation would have shown the same generic "not synced" wording as any other unsynced project.

**Why**

This makes it clearer, when reviewing a session, whether a project directory was never synced at all versus deliberately disconnected as your own separate copy.

- Area: Remote Machines
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### New user-facing message: cloud session hooks skipped under trusted-device policy

New message explains cloud session hooks are skipped when trusted-device policy blocks verification

**What**

When Claude Code runs as a cloud session and its hooks (custom scripts that run automatically at certain points) can't be verified as coming from a trusted sender, a new message now explains this to the user: hooks are skipped because the service could not vouch for the sender under the organization's trusted-device policy, and the session continues without running them.

**Why**

This gives users a clear explanation instead of silent or confusing behavior when hooks don't run in a cloud session due to an organization's trusted-device security policy, so they know why their hooks didn't fire.

- Area: Cloud Sessions
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### 'Login expired' message and dedicated /login re-auth copy

New 'Login expired' message distinct from the existing Anthropic profile expiry message

**Unclear.** The exact condition that selects this message over the existing Anthropic-profile message is not detailed beyond being a specific check.

**What**

A new error message was added for invalid-request authentication errors: "Login expired · Run /login to sign in again, or re-authenticate your Anthropic profile." This is shown under certain conditions as a separate message from the existing "Anthropic profile login expired" message.

**Why**

This gives users more specific guidance when their login (rather than specifically their Anthropic profile) has expired, pointing them to the `/login` command to sign back in.

- Area: Auth
- Names: `/login`
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### New client-side settings validation flags dead entries in policy-array settings

Claude Code now flags invalid entries in the strictKnownMarketplaces and blockedMarketplaces settings

**What**

Claude Code now checks the `strictKnownMarketplaces` and `blockedMarketplaces` settings arrays (which allowlist or block [marketplace](/docs/en/plugin-marketplaces) sources for plugins) for entries that can't be parsed or are otherwise invalid, and reports each one it finds.

What happens to an invalid entry depends on where the setting comes from:

- On managed-settings tiers, an invalid `blockedMarketplaces` entry is kept but flagged with a warning; since it can never actually match anything, it ends up blocking nothing

- On managed-settings tiers, other invalid entries may instead be silently stripped out

- In user, project, or local settings files, the whole key is simply treated as inert

**Why**

This surfaces misconfigured marketplace policies instead of letting them fail silently, which matters especially for `blockedMarketplaces` since an invalid entry there looks like it's blocking something when it actually isn't.

- Area: Settings
- Names: `strictKnownMarketplaces`, `blockedMarketplaces`
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Artifact DB requests gain gateway-busy retry and relay-unavailable handling

Artifact database requests now retry on gateway-busy and handle relay-unavailable errors more clearly

**What**

Requests to the artifact database now retry automatically in a few situations:

- When the gateway reports it is busy, the request waits up to a capped delay and retries once, reporting whether the retry succeeded (`relay_busy_recovered`) or was needed at all (`relay_busy_retried`)

- When the server rejects "session hints" sent with the request, it retries once (`session_hints_rejected`)

Separately, failures where the relay is unavailable or not served are now recognized as distinct cases and surfaced with a dedicated error message instead of a generic failure.

**Why**

This makes artifact database requests more resilient to temporary gateway congestion and gives clearer error messages when the underlying relay simply isn't available, instead of failing outright or with an unhelpful message.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 2/5
- Signal: 1/5

### Slash-command dispatch now splits multi-block input before running policy checks

Slash commands now split multi-block pasted input before running permission checks

**What**

When you run a slash command, Claude Code now first splits the raw argument text into pieces, checking whether any of them are a distinct "block" (such as a pasted chunk of content). If so, the text and body pieces are rejoined, separated by blank lines and trimmed, and that rejoined text replaces the original argument string before the command's permission checks and the rest of dispatch proceed.

**Why**

This changes how multi-part or pasted input is normalized before a slash command's policy checks run, which can affect how such input is interpreted when a command's arguments include pasted content blocks.

- Area: Slash Commands
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Pasted large-text blocks can now stay inline instead of always becoming a placeholder

Small pasted text blocks can now stay inline in your message instead of always turning into a placeholder

**What**

When you paste a mix of content into Claude Code, text blocks that are short enough, under a certain character length and at most two lines, are now kept inline in your message text as-is. Previously, any such block would always be replaced with a placeholder reference to the pasted content. A line break is inserted after an inlined block if it's followed by another block or by more non-blank text.

**Why**

This avoids turning small, easily readable snippets into opaque placeholders, keeping short pasted text visible and readable directly in your message rather than hidden behind a reference.

- Area: Prompt Input
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Tool-call UI now reflects running/failed/stopped status of an associated background task

Tool-call cards in the UI now reflect the running, failed, or stopped state of a linked background task

**What**

When a tool call in the conversation is linked to a background task or process, its card in the interface now watches that background task's own status. Whether the card animates (shows as running) or displays an error now takes into account whether the linked background task is running, failed, or has been stopped, not just whether the tool call itself has resolved or errored.

**Why**

This keeps the tool-call display accurate when the underlying work continues in the background: a tool card can now show as still active or as failed based on what's actually happening with its background task, instead of only reflecting the tool call's own immediate result.

- Area: Background Tasks
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Command-output error message classifier expanded from 3 to 5 pattern checks

Command output errors now get checked against five specific message patterns instead of three before falling back to generic text

**Unclear.** Which two new patterns were added and what specific errors they cover is not stated.

**What**

When a command's tool output needs to be turned into a special, more specific error message (used in non-verbose mode), Claude Code now checks it against five distinct pattern-matching functions in sequence, up from three, before falling back to its generic write or delete failure messages.

**Why**

This means more kinds of command failures can now get a tailored, more informative error message instead of a generic fallback one.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### New UI for tool results that arrive after the turn has moved on

New UI shows when a tool's result arrives late, including how long the wait took

**What**

Claude Code has new on-screen messages for when a tool call's result comes back after the conversation has already moved on. If a result shows up late, you'll see a placeholder line noting that an earlier tool's result has arrived. If the assistant paused to handle a new message from you while a tool was still running, a line now reports how long that tool took to finish.

**Why**

This makes it clearer when results are arriving out of order, so you're not confused about why a tool's output appears after the conversation has already continued.

- Area: Background Tasks
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Directory sync's git-config safety limits tightened and made more specific

Directory sync's git-config safety checks now also refuse configs with too many hooks/filters or oversized files

**What**

Directory sync already refused to proceed when a repository's git configuration was unreadable or exceeded limits on include-chain depth or file count. It now also refuses when:

- the configuration defines more hooks and filter drivers than directory sync is able to switch off

- a config file is larger than 1 MiB

- a config file is a pipe or device rather than a regular file

**Why**

These additions close gaps where a git configuration could reference more hooks and filters than directory sync could safely disable, or use unusual file types/sizes, reducing the risk of directory sync running with configuration it can't fully control.

- Area: Directory Sync
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Failed plugin installs show more of the real error

Failed plugin installs now show more of the actual error, with a hint on how to see the rest

**What**

When a plugin fails to install, Claude Code used to just print the plugin's name and a reason, cut off to 2 items. Now it tells apart internal errors from external ones, shows more of a long or multi-line external error (trimmed to a fixed length with "..." if needed), and adds a hint: pressing Enter on a plugin's details in `/plugin` shows its full error.

**Why**

This makes it easier to actually diagnose why a plugin install failed, instead of getting a truncated, uninformative summary, and points you to where you can read the complete error message.

- Area: Plugin Install
- Names: `/plugin`
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Permission rules naming a removed tool are now flagged and skipped

Saved permission rules for tools that no longer exist are now flagged and skipped

**What**

When Claude Code checks your saved permission rules (allow/deny settings for tools) against the tools it currently knows about, a rule that names a tool which has since been removed from Claude Code is now specifically detected. Instead of being treated as an unrecognized or possibly-typo'd tool name, it logs a warning saying the rule "names a removed tool" and is skipped.

**Why**

This keeps old permission rules for tools that no longer exist from being confused with genuine typos, and surfaces a clearer warning so you know why such a rule isn't taking effect.

- Area: Permissions
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### New "background task update(s) waiting" notice while a panel is open

Claude Code now shows a notice when background task updates are waiting while a panel like the model picker is open

**What**

When a full-screen panel is open (such as the model picker or the IDE panel) and no background task is currently running its own update, Claude Code now shows a small notice saying "Background task update" or "N background task updates waiting while this panel is open".

**Why**

This lets you know that something finished or changed in the background while your attention was on a panel, so you don't miss updates that were queued up out of view.

- Area: Background Tasks
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Plugin update messaging: version diff and in-place reload note

Plugin update messages now show version changes and, for linked plugins, remind you to reload before edits take effect

**What**

Claude Code can now tell you, when a plugin has an update, both the version you have installed and the version available. For plugins that are loaded 'in place' from a linked local path (rather than a fetched copy), it now adds a note that any edits to the plugin only take effect the next time you start a session, or when you run `/reload-plugins`, along with a hint for the command to re-record the version.

**Why**

This makes it clearer when a plugin update is actually available and prevents confusion for people developing plugins locally, who might otherwise wonder why their edits don't seem to be showing up until they restart or reload.

- Area: Plugin Install
- Names: `/reload-plugins`
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Custom LLM gateway provider headers validated for safety

Custom LLM gateway header settings are now validated for valid names, no duplicates, and no collisions with reserved headers

**What**

If you configure a custom `anthropic` provider (an LLM gateway) with custom HTTP headers in settings, Claude Code now checks that configuration more strictly:

- Header names must be valid HTTP header names

- The same header name can't appear twice, even with different capitalization

- Header names can't collide with reserved headers that the gateway or the provider's own SDK already sets or signs

- Header values must be non-empty, printable ASCII text with surrounding whitespace trimmed

**Why**

This catches misconfigured or conflicting custom headers before they cause confusing request failures, and prevents a user-supplied header from accidentally overriding one the gateway relies on for authentication or signing.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Artifact publish/share tool descriptions reworded into full sentences, with richer 'replacing' text

Artifact publish/share prompts now read as full sentences and name the specific page being replaced

**What**

Claude Code shows description text explaining what will happen when you publish or share an Artifact (a generated document or page). This text was rewritten from short, comma-joined fragments into standalone sentences, including clauses about sharing status. When an action would replace an existing page, the text now looks up and names that page, saying "replacing its current page" or "replacing the page ''" instead of just showing a URL.

**Why**

This makes the permission prompts for Artifact actions clearer to read, and naming the specific page being replaced makes it easier to tell what you're about to overwrite before confirming.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Artifact type listing now warns when results are filtered by a type_query

Artifact type listing now warns Claude when a type_query search may hide matching types

**What**

When Claude asks to list artifact types and narrows the results with a `type_query` search term, the response now adds a note explaining that the list only shows types matching that search text, so a type the account actually has could be missing from what's shown. The note also explains how to list all types without narrowing.

**Why**

This stops Claude from assuming a narrowed search result is the complete list of available artifact types, reducing the chance it wrongly concludes a type doesn't exist.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Tool-call validation errors now include custom Zod issue messages

Tool-call error messages now include specific custom validation messages from Zod

**What**

When a tool call fails validation, Claude Code builds an error message describing what went wrong, such as missing, unexpected, or wrong-type parameters. That message now also includes any custom validation error messages produced by the validation library (Zod) when a check is specifically marked as "custom".

**Why**

This surfaces more specific, tool-author-written explanations of why a call failed, instead of only generic parameter-shape errors.

- Area: Tool Validation
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Auto-mode classifier logging no longer includes raw prompt/action text

Auto-mode classifier logs no longer include raw prompt or error text, only lengths

**Unclear.** Nothing has been read yet about whether the `tengu_auto_mode_malformed_tool_input` gate is on or off for this site's account.

**What**

Debug and telemetry logging for the auto-mode classifier (the internal system that classifies actions Claude is about to take) no longer includes the actual text being classified. Previously the log for "new action being classified" could include up to 500 characters of the action's text; it now logs only the tool name, the length of the action text, and the tool-use ID. Similarly, when input to the classifier is malformed, the log used to include the actual error message text; it now logs only the character count of that error.

**Why**

This reduces the chance of sensitive or raw prompt content ending up in logs, while still preserving enough information (lengths, identifiers) for debugging.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Remote Control unsigned-activity warnings now say "This session" for cloud-originated activity

Remote Control warnings about rejected unsigned activity now say "This session" for cloud-originated activity instead of "Remote Control"

**What**

When Claude Code rejects a burst of unsigned remote activity, it shows a warning. That warning now reads differently depending on where the activity came from: if it came from a cloud session, it says "This session" instead of "Remote Control". The explanatory hint text underneath also changes wording to match, saying "Use an app that does" for cloud sessions versus "Use the terminal or an app that does" otherwise.

**Why**

This makes the warning message accurately describe where the rejected activity originated, so the wording makes sense whether you're looking at a cloud session or a local Remote Control connection.

- Area: Remote Control
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### File-sync-stopped message rewritten to reassure about local work

The file-sync-stopped message now reassures that local work is untouched and unrelated to the remote copy

**What**

When file sync between a session and the user's attached machine stops, Claude Code now shows a rewritten message. It explicitly reassures that the local checkout is unchanged, remains the session's own copy, and that the user's remote folder is now a separate copy going forward. This replaces the older, terser wording that simply said the session began unbound.

**Why**

This makes it clearer to the user that stopping file sync doesn't put their local files at risk or overwrite anything, reducing confusion about what happened to their work.

- Area: File Sync
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Artifact thumbnail description rewritten as a sentence

The Artifact custom-thumbnail tool description was rewritten as its own sentence, with added path escaping

**What**

The tool description text explaining that sharing an Artifact can also upload a custom thumbnail image changed from a trailing clause tacked onto another sentence ("with a custom thumbnail X") to its own standalone sentence ("Also uploads a custom thumbnail, X."). Path values used with this feature are also now escaped and normalized.

**Why**

The added escaping and normalization of paths helps ensure thumbnail file paths are handled consistently and safely, regardless of how they were entered.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Unattested-request error message simplified

Error message for a rejected remote tool call now simply says the request lacked a device signature

**What**

When Claude Code rejects a remote tool call because it can't be verified, the error message shown to the user has changed. Previously it described the rejection in terms of an account-level requirement; now it plainly states that the call arrived without a valid device signature.

**Why**

The new wording is more direct about the actual cause, making it clearer to the reader why the request was blocked.

- Area: Attestation
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Cloud folder-sync error messaging simplified

Cloud folder-sync error messages simplified, dropping the explanation about folder sync being switched off

**What**

Several messages shown when a cloud session isn't picking up changes synced from a local folder have been reworded. They previously included a parenthetical explanation about 'its side of folder sync' being switched off; that explanation is now dropped in favor of plainer phrasing, such as stating that the cloud session never picked up anything synced from here and the session stops.

**Why**

The simpler wording is meant to be easier to understand for someone encountering a folder-sync problem, without getting into the internal mechanics of why sync failed.

- Area: Cloud Sessions
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Device-signature warning text made cloud-session aware

Unsigned-device-activity warning now differs for cloud sessions versus terminal sessions

**What**

Claude Code shows a warning when it detects activity from an app that doesn't cryptographically sign what it sends, as a security check. This warning message now branches based on whether the session is a cloud session. For cloud sessions, the phrasing 'or an app that does' (which refers to using a different terminal app) is dropped, since that suggestion doesn't apply outside a terminal.

**Why**

This makes the warning message more accurate for cloud sessions, where suggesting the user switch to a signing terminal app wouldn't make sense.

- Area: Attestation
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Effort level command validation gains a dedicated error message

New dedicated error message when update_settings is called with an invalid effortLevel

**What**

Claude Code now has a specific error message for when `update_settings` is called with an invalid `effortLevel` value (`effortLevel` sets a default [effort level](/docs/en/model-config#adjust-effort-level), how much reasoning a model does, for models without their own saved level). The new error text references the list of valid effort levels directly.

**Why**

This gives a clearer, more specific error when an invalid effort level is supplied, instead of a generic failure.

- Area: Settings
- Names: `effortLevel`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Hooks module error logging includes structured module label and error detail

Hook failure logs now name the failing hook and show its error message

**What**

When a hook (a user-configured script that runs at a specific point, like before or after a tool call) fails, the error log now shows the hook's name and a rendered version of the error inline, instead of one generic combined message.

**Why**

This makes it much easier to tell which hook failed and why when troubleshooting hook errors in logs.

- Area: Hooks
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Command-check permission prompt reworded

The message for an incomplete project command check now explains it as a permission issue

**What**

When Claude Code can't finish checking a project's commands on your computer, the message shown has changed. It previously read as a generic truncation notice, and now explicitly explains the situation as a permission request instead.

**Why**

The reworded message should make it clearer to you that the command check is stuck waiting on a permission decision, rather than leaving you to guess that something was simply cut short.

- Area: Permissions
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### AWS/GCP metadata SSRF blocklist extended

Cloud metadata blocklist now also covers EC2's instance-data hostname

**What**

Claude Code maintains a list of hostnames used by cloud providers to serve instance metadata, which is blocked from being fetched as a security precaution. That list now also includes `instance-data.ec2.internal`, an Amazon EC2 metadata hostname.

**Why**

This closes a gap where a request to this EC2 metadata hostname might not have been blocked, reducing the risk of leaking cloud instance credentials or metadata through a fetched URL.

- Area: Sandbox
- Names: `instance-data.ec2.internal`
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### New KeyMintRefusedError for API key creation failures

A new error message appears when the server fails to create an API key without explanation

**What**

Claude Code now has a dedicated error, `KeyMintRefusedError`, for when the server refuses to create an API key and doesn't give a readable reason. It shows the message: "The server did not create an API key and gave no readable reason. If this keeps happening, contact support."

**Why**

This gives a clearer, more specific message when API key creation silently fails, and points you toward contacting support if the problem persists instead of leaving you with an unexplained failure.

- Area: Auth
- Names: `KeyMintRefusedError`
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### claude-test explorer agent now also blocked from the app-launch MCP tool

claude-test's explorer subagent is now also blocked from launching the app via its browser MCP tool

**What**

The built-in `claude-test` plugin's read-only `explorer` subagent (a helper agent meant only to look around, not make changes) is now also barred from using the `claude_test_app_up` tool, which launches the app under test. This is in addition to the existing block on `claude_test_allow`.

**Why**

This keeps the explorer subagent strictly read-only, preventing it from starting up the application, which is an action beyond simple exploration.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Cell pixel size is re-probed on window focus and after paste

Terminal cell pixel size is re-measured when the window regains focus and after pasting

**What**

Claude Code now re-asks the terminal for its cell size in pixels whenever the window regains focus, as long as something is still holding a fine-pointer reference, and also re-measures it after a paste. This keeps the cached cell-pixel dimensions from going stale.

**Why**

Cell size can change between focus events (for example if the terminal font or window size changed), so re-probing it keeps pointer-based interactions, like fine-pointer selection, accurately aligned with the terminal grid.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### NO_PROXY-aware telemetry relay warning

Startup logging now warns when a telemetry destination matches NO_PROXY and will bypass the egress proxy

**What**

When Claude Code starts up, it now checks each configured telemetry forwarding destination against the `NO_PROXY` environment variable. If the egress-boundary proxy mode is active and a destination's URL matches `NO_PROXY`, it logs a message noting that exports to that host will skip the proxy.

**Why**

This helps administrators notice when telemetry data is bypassing an intended network proxy, which matters for environments that route all outbound traffic through a controlled egress point.

- Area: Telemetry
- Names: `NO_PROXY`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### File-read attribution message punctuation changed from em dash to colon

File-read source messages now use a colon instead of a dash, e.g. 'read from under X: in Y'

**What**

Messages that tell you where a file's content came from (of the form 'read from under X') now separate the location details with a colon instead of an em dash.

**Why**

This is a small formatting cleanup to these messages; it doesn't change what information is shown, only the punctuation used to present it.

- Area: File Tools
- Tier: You'll notice
- Useful: 1/5
- Signal: 0/5

### print --max-budget-usd halt message rewording

Internal log wording for the --max-budget-usd halt now says 'this run's spend' instead of 'total cost'

**What**

The internal log line printed when a headless (print mode) run hits its `--max-budget-usd` spend cap now reads "this run's spend" instead of "total cost".

**Why**

This is a wording change to the internal log message; the budget-halt behavior itself is unchanged.

- Area: Headless Mode
- Tier: You'll notice
- Useful: 1/5
- Signal: 0/5

## Bug Fixes

### Device link registration no longer silently retries on revoked key

Automatic re-registration after a revoked device key was removed; it's now reported as a distinct 'device_revoked' failure

**What**

Previously, when linking a device (in the attach-serve flow) failed because its device key had been revoked, Claude Code would automatically retry registration. That automatic retry has been removed. Instead, this failure is now classified distinctly as `device_revoked`.

**Why**

Instead of silently retrying on a revoked key, which could mask what's actually wrong, the failure is now surfaced clearly so it can be handled or reported as its own case.

- Area: Auth
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Headless cloud client validates repository-trust questions before forwarding to host

The headless cloud client now checks repository-trust prompts before forwarding them to the host, dropping suspicious ones

**What**

When a permission request needs to be passed from a headless/cloud client through to the host machine, and that request involves a repository-trust question (whether a given tool call should be trusted for the current repository), the client now verifies the request more carefully before forwarding it. If the request's input doesn't exactly match the digest the host actually served, or it's unclear what's attached, the request is dropped and a warning is logged instead of being relayed.

**Why**

This prevents a repository-trust prompt from being forwarded to the host if it's been tampered with or doesn't correspond to what the host actually asked about, closing off a potential way to trick the trust check.

- Area: Cloud Sessions
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Settings files behind symlinks to another host or unverifiable routes are refused, not read

Settings files reached through unverifiable or cross-host symlinks are refused, not followed

**What**

When Claude Code reads a settings file, it now checks whether the resolved path is a symlink (a file that points to another location) and whether that symlink is canonical (resolves cleanly and verifiably) or points somewhere the sandboxed path check can't confirm, such as another host. If the check fails, Claude Code refuses to read the file at all instead of following the link.

**Why**

This closes off a way a settings file could be used to redirect Claude Code into reading from an untrusted or unverifiable location.

- Area: Settings
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Null-byte injection in subprocess args/env now gets a specific diagnosis

Subprocess launch failures from null bytes in args or environment now get a specific diagnosis

**What**

When Node.js rejects launching a subprocess with an `ERR_INVALID_ARG_VALUE` error, Claude Code's `execFileNoThrow` helper now figures out whether the cause was a null byte in the working directory, the executable path, a command-line argument, an environment variable name, or an environment variable value. For environment variables specifically, it also reports whether the offending variable came from the process's inherited environment.

**Why**

This turns a generic subprocess-launch failure into a specific, actionable diagnosis, making it much easier to track down what actually caused the failure.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Hardened file-identity check for storage reads, using /proc/self/fd where available

File-identity checks for storage reads now use /proc/self/fd on supporting systems, falling back to stat comparison

**What**

After opening a file for a storage read, Claude Code now verifies the file's identity by checking, where available, that `/proc/self/fd/<fd>` still points at the expected path and isn't marked '(deleted)'. On systems where `/proc` isn't readable, it falls back to comparing stat information (link count, inode, and device) instead, and logs a one-time notice when it has to use that fallback.

**Why**

This strengthens protection against a file being swapped out from under Claude Code between opening it and reading it, while still working on systems that lack a readable `/proc`.

- Area: Internals
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### PDF page-extraction supports Windows long paths

PDF page extraction now handles Windows file paths longer than 259 characters

**What**

When extracting pages from a PDF, the `pdfinfo` step and the logic that creates a scratch directory for converting pages to images now use Windows' namespaced-path handling to support paths longer than 259 characters. If a scratch directory can't be created at all, Claude Code now falls back to rendering the page images directly into the tool-results directory, with a warning.

**Why**

This prevents PDF page extraction from failing outright on Windows systems with long file paths, and keeps it working even when a temporary scratch directory can't be set up.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Cross-filesystem (EXDEV) fallback for atomic sync-file writes

Sync-file writes now fall back cleanly when the staging area is on a different filesystem than the destination

**What**

Claude Code's local git object/directory-sync layer writes files atomically (all-or-nothing) by first hardlinking them into a staging area on the same device. If that fails with an `EXDEV` error, meaning the staging area is on a different filesystem than the destination, it now falls back to a direct write instead of throwing an error.

**Why**

This keeps sync-file writes working reliably even when the staging area and the destination live on different filesystems, a situation that previously caused a hard failure.

- Area: Git Internals
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Edit tool's \uXXXX-escape text search hardened with a length guard and clearer failure

Edit tool's handling of \uXXXX text in search strings is hardened with a size check and clearer error

**What**

The `Edit` tool can treat a literal search string containing `\uXXXX` unicode escape sequences as if it were a regular expression. Before building that regular expression, Claude Code now estimates how long the resulting pattern would be and checks that the escape sequences are well-formed, instead of just testing length and regex validity generically. If this check fails, it now logs a specific message explaining that the `\uXXXX`-escape search was skipped because the regex engine refused a pattern of a given length, rather than silently returning nothing.

**Why**

This makes it clearer when and why an edit search involving unicode escapes didn't work, instead of the tool failing silently.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### /plugin uninstall/removal flow now cleans up stray references across all settings scopes

/plugin uninstall now cleans up leftover plugin references across every settings scope, not just one

**What**

When removing a failed or disabled plugin through `/plugin`, Claude Code now loops over every settings scope and removes the plugin's id from each scope's `enabledPlugins` list, counting how many scopes it actually removed it from. Even if nothing was removed anywhere, it now checks whether to still show the message "Removed X from the list. It is not installed." The success message after uninstalling also now looks up and reports which plugin ids were affected by the cleanup.

**Why**

Previously, a plugin's id could stay listed as enabled in some settings scope even after being uninstalled elsewhere. This ensures removal is thorough across all scopes and gives clearer feedback about what was actually cleaned up.

- Area: Plugin Install
- Names: `/plugin`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Sandboxed shell commands get a $TMPDIR backstop when referenced but unset

Sandboxed shell commands get a fallback TMPDIR value when the command text references it but none is set

**What**

When Claude Code runs a shell command inside its sandbox (a restricted environment that limits what a command can access), it now checks whether the command text mentions the `TMPDIR` environment variable. If sandboxing is on, no explicit override for the sandbox's temporary directory exists, and the command references `TMPDIR`, Claude Code now computes a fallback value and passes it through as a backstop.

**Why**

This prevents commands that rely on `TMPDIR` from failing or misbehaving inside the sandbox when no temporary-directory value was otherwise configured.

- Area: Sandbox
- Names: `TMPDIR`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Marketplace declared-in-settings but unreadable/mismatched-name is now reconciled with a warning instead of silently failing

Unreadable or mismatched marketplace declarations in settings now trigger a warning and cleanup instead of silent failure

**What**

If a plugin marketplace is declared in settings but Claude Code can't read its manifest at the declared location, or the manifest it finds there declares a different marketplace name than expected, Claude Code now removes the stale declaration and shows a one-time warning explaining the mismatch and what to do about it.

**Why**

Previously this situation failed silently; now the user is told specifically that a marketplace name couldn't be verified, so they can fix the settings instead of wondering why the marketplace isn't working.

- Area: Plugin Install
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Prompt-shell command handoff now carries full tool options

Permission checks for handed-off skill shell commands now always see the tool in the tool list

**Unclear.** It is unclear what user-visible difference this makes, since the gate controlling this handoff path has no known configuration read.

**What**

Skills can include inline shell commands that Claude Code sometimes hands to the model to run explicitly instead of executing automatically. When that handoff happens, the permission check that decides whether the command is allowed now always runs with the tool included in the available tool options, adding it if it wasn't already present, rather than only sometimes including it.

**Why**

This makes the permission decision for handed-off shell commands more consistent, so the check isn't skipped or handled differently depending on whether the tool happened to already be in the list.

- Flag `tengu_iterative_falcon`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Skills
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### Artifacts publish tool: idempotent handling for retried publish calls

Retrying an Artifact publish call that already succeeded now says so, instead of claiming a fresh Artifact was created

**What**

When a call to publish an Artifact is retried and the result shows the Artifact was already created by an earlier attempt of that same call, Claude Code now returns a distinct message, "An earlier attempt of this call already created the Artifact...", instead of reporting it as if a new Artifact had just been created.

**Why**

This avoids a misleading "Created a new Artifact" response when a publish call is retried after it already succeeded, making it clear no duplicate was made.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Ink layout listeners now isolated from thrown errors

A crash in one terminal-layout listener no longer breaks layout for the rest of the interface

**What**

The engine that manages the terminal interface's layout now catches errors thrown by individual layout listeners instead of letting one failing listener crash layout for everything else. When a listener throws, Claude Code pauses all layout listeners until the current update finishes, logs a warning ("ink layout listener threw; layout listeners paused until this flush unwinds"), and caps how much debug logging it produces, noting once the cap is reached.

**Why**

This makes the terminal interface more resilient: a bug in one part of the layout system no longer takes down the whole display.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Headless (-p) stream-json write failures now flush pending queued messages before reporting the error

Headless mode no longer aborts mid-stream on a write failure, instead flushes queued messages first

**What**

In headless mode (`-p`, non-interactive), when writing to the `stream-json` output format fails, Claude Code no longer stops immediately in the middle of the output loop. Instead, it captures the error, keeps draining any messages still queued for output, and reports the failure only after the loop finishes naturally.

**Why**

This ensures that queued output messages aren't silently dropped just because one write failed, and the failure is still reported, just after any remaining output has been flushed.

- Area: Headless Mode
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Bundled 'claude-test' plugin gains conflict detection and stale-data cleanup

Built-in claude-test plugin now detects naming conflicts and cleans up its own stale data

**What**

The bundled `claude-test` plugin now cleans up old version folders and stale 'live' page directories left behind by earlier runs, removing ones older than a cutoff date. It also now detects when a separately loaded, differently-sourced plugin is also named `claude-test` and loads first, and reports an error in that case rather than silently conflicting with the built-in one.

**Why**

This keeps the plugin's own working data from accumulating unbounded stale files over time, and prevents confusing, silent conflicts when another plugin happens to share the `claude-test` name.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 2/5
- Signal: 1/5

### Empty assistant text blocks now sanitized in replayed transcripts

Empty assistant text blocks are now cleaned up when replaying or compacting conversation history

**What**

Claude Code now detects assistant messages that contain empty text blocks (a text content block whose text is an empty string) when replaying or compacting conversation history. It either drops these empty blocks, or, if one sits sandwiched between two tool-use blocks, replaces it with a placeholder marker showing `[Empty text removed]`.

**Why**

Empty text blocks can fail Anthropic's API validation when a transcript is replayed or compacted, so removing or replacing them keeps history processing from breaking on messages that happen to contain one.

- Area: Transcript
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Hook processes now killed if still running when spawn completes/aborts

Hook command processes are now force-killed if still running when cleanup happens

**What**

When Claude Code runs a hook (a user-configured command that runs automatically at certain points, like before a tool call), the code that cleans up after that command now explicitly kills the underlying process if it is still marked as "running" at cleanup time, in addition to the cleanup step that already existed.

**Why**

This helps prevent hook command processes from being left running in the background after they should have finished or been aborted.

- Area: Hooks
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Bridge/serve API now handles "folder already served elsewhere" as a distinct 409

Serving a folder that's already served elsewhere on the device now gives a clear error instead of a generic one

**What**

When registering a folder to be served (shared for remote access) fails because that same folder is already being served by another instance of Claude Code on the same device, the error is now recognized specifically and shown as a clear message telling the user to stop the other instance first, instead of falling through to a generic registration-failure message.

**Why**

This makes it obvious what actually went wrong and what to do about it, instead of leaving the user to guess at a generic error.

- Area: Remote Machines
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Transcript loader now repairs stray string content instead of only dropping rows

Transcript loader now repairs plain-string message content instead of dropping or ignoring it

**What**

When Claude Code loads or resumes a saved conversation transcript, a row where an assistant message's content is a plain (non-empty) text string, instead of the normal structured format, used to be either left alone or dropped entirely if malformed. Now that content is wrapped into a proper text block so it can be used normally. The cleanup log shown when loading or resuming a transcript now separately reports how many rows were cleaned, how many were wrapped, and how many were dropped.

**Why**

This recovers transcript rows that would previously have been silently discarded or left in an inconsistent format, reducing data loss when resuming past conversations.

- Area: Transcript
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### File-copy staging now detects a concurrent ctime change mid-copy and treats it as 'changed'

File copying now detects if a file changes mid-copy and treats it as changed instead of copying stale data

**What**

When staging a file for copying, Claude Code now re-checks the file's change timestamp (ctime) immediately after opening it, comparing it against the time the current copy pass started. If the file changed during that window, the copy is short-circuited and treated as "changed" rather than proceeding to hash and copy what may now be stale or inconsistent data.

**Why**

This avoids a race condition where a file is modified while it's being copied, which could otherwise result in copying a corrupted or inconsistent version of the file.

- Area: File Sync
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Update-check version responses are now validated as semver before use

Update checks now validate that version strings from GCS, npm, Homebrew and the binary repo actually look like versions

**What**

When Claude Code checks for updates, it fetches a version string from sources like Google Cloud Storage (GCS), npm, and Homebrew. Previously it would trust whatever string came back; now it validates that the string is a properly formed version number (using semver, the standard versioning scheme) before using it. If the response is invalid, it's logged (truncated to 300 characters) and treated as no result rather than acted on. The same validation was added to the logic that compares a target version against the current one to decide whether to skip an update check.

- GCS, npm-view, and Homebrew version fetches are now validated before use

- The binary-repo version check now throws an error if the fetched value doesn't look like a version, instead of silently accepting it

**Why**

This prevents a malformed or unexpected response from a version-check endpoint from being mistaken for a real version and causing incorrect update behavior.

- Area: Updater
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Relay now respects Retry-After on busy 503s instead of treating them as hard errors

Busy 503 responses from the relay now trigger a retry after the server's suggested delay instead of failing outright

**What**

When a request to the artifact-frame relay gets back an HTTP 503 ("service busy") response, Claude Code now checks for a `Retry-After` header telling it how long to wait. If that header is present, the request is routed back through the relay with that delay applied, and a new telemetry event called `relay_busy` is logged. Previously, this kind of 503 was simply treated as a relay error and not retried.

**Why**

This lets Claude Code recover automatically from a temporarily busy relay instead of surfacing it as a hard failure.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### File-sync now refuses to apply a branch that points at its own bookkeeping snapshots

File sync now rejects an incoming branch that points at its own internal bookkeeping commits

**What**

Claude Code's file-sync feature (which keeps files in sync between local and cloud) now checks an incoming branch before accepting it. If the branch's history includes one of file sync's own internal bookkeeping commits, it is rejected, with a message explaining that Claude's branch points at sync's internal reference markers rather than at real work.

**Why**

This prevents file sync's own internal bookkeeping from being mistaken for actual file changes and applied as if it were real work, which could otherwise corrupt or confuse the synced state.

- Area: File Sync
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Skill discovery now also checks the primary worktree when running from a linked git worktree

Skill discovery now also checks the main worktree's .claude/skills folder when run from a linked git worktree

**What**

When Claude Code looks for available skills and commands and it's running inside a linked git worktree (a secondary working copy that shares history with a primary repository checkout), it now also checks the `.claude/skills` folder in the primary worktree if the current worktree doesn't have its own accessible one.

**Why**

Previously, skills defined only in a project's primary worktree could be invisible when working from a linked worktree. This change means skills set up for a project are found regardless of which worktree you're currently working in.

- Area: Skills
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Device binding now retries registration on a stale device row

Device binding now retries automatically if the server has a stale record of your device

**What**

Device binding, which cryptographically ties a session to your device, now retries when the server rejects a bind attempt with a 404 error against the currently registered device. In that case, Claude Code re-registers the device and retries the signed bind request once with the new device identity, instead of simply failing and leaving the session unbound.

**Why**

This prevents a stale or outdated device record on the server from permanently blocking device binding, recovering automatically instead of requiring the user to intervene.

- Area: Device Binding
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### winget/apk update checks now report npm lookup failures instead of failing silently

Update checks on winget and apk installs now report failed lookups instead of failing silently

**What**

For Claude Code installed via winget (Windows) or apk (Alpine Linux), if the check for a newer version can't get a valid answer from the npm registry, Claude Code now prints "Could not check for updates (npm lookup failed or returned an invalid response)" along with manual upgrade instructions (`winget upgrade Anthropic.ClaudeCode` or `apk upgrade claude-code`). Previously this case produced no message at all.

**Why**

This means you'll know when an update check silently failed instead of assuming you're already on the latest version, and you're given the exact command to upgrade manually.

- Area: Updater
- Names: `winget`, `apk`
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### PDF page render (pdftoppm) hardened for Windows UNC paths and clearer errors

PDF-to-image rendering now cleans up error messages, including Windows network path prefixes, and handles a new move-failure case

**What**

When Claude Code converts a PDF page to an image (using the `pdftoppm` tool, part of reading PDF files), it now cleans up the error text before showing it to you:

- Temp-file paths embedded in the underlying tool's error output are replaced with the original filename, so errors reference the file you actually gave it

- Windows extended-length and UNC path prefixes (`\\?\UNC\`, `\\?\`) are stripped out of error text

- A distinct error is now reported if moving the rendered page images into the output folder fails

**Why**

This makes PDF rendering failures easier to understand, especially on Windows, where raw error text could otherwise show confusing internal path syntax instead of your file's name.

- Area: Elsewhere
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Agent memory entrypoint hardened against symlink escapes

Agent memory no longer reads MEMORY.md if it's a symlink or resolves outside the working copy

**What**

Claude Code's agent memory feature now refuses to read a `MEMORY.md` entrypoint file if it's a symlink or another special file type rather than a plain regular file. It also refuses to read a memory directory if the entrypoint resolves to a location outside the working copy, or through a dangling or unresolved symlink. When either of these checks blocks a read, it's logged for telemetry.

**Why**

This closes off a way a memory file could be used to sneakily point outside the project directory, which could otherwise be used to read or leak files it shouldn't have access to.

- Area: Memory
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### dir-sync clears stale round-skipped notices once a round succeeds

Directory-sync now clears a 'changes were skipped' warning once a sync round succeeds again

**What**

When a directory-sync round is no longer being skipped, Claude Code now actively removes any previously shown 'round-skipped' notice from its list of one-time notifications shown to the user.

**Why**

Previously a warning saying a sync round's changes were skipped could keep showing even after syncing recovered. Now that stale warning is cleared once the round succeeds, so the message reflects the current state.

- Area: Directory Sync
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Directory-sync file pull supports a staging directory with EXDEV fallback

Directory-sync file downloads can use a staging directory, falling back to direct writes across devices

**What**

The part of directory sync that writes incoming files can now optionally write them to a staging directory first. If that fails with a cross-device-link error (which happens when the staging directory and target are on different filesystems or drives), it retries once, writing the file directly instead.

**Why**

Staging writes first is generally safer, but this fallback makes sure directory sync still works correctly even when the staging and target locations are on different devices.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin settings UI clears stale errors when a plugin is enabled/disabled/uninstalled

Toggling a plugin on, off, or uninstalling it now clears its stale error messages from the settings UI

**What**

When you enable, disable, or uninstall a plugin in the settings UI, Claude Code now calls a new store method, `removeErrorsOf`, which clears out any previously shown errors tied to that plugin's ids or sources, before refreshing the displayed state.

**Why**

Previously an old error for a plugin could keep showing in the settings UI even after you'd already fixed it by toggling or reinstalling the plugin. This clears stale errors automatically.

- Area: Plugin Install
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Plugin MCP-call staging: fixed input/output lane_path validation using a shared helper

Fixed a bug where a plugin tool call's staged output-file validation could check the wrong file's path

**What**

Staged MCP tool calls (calls to a plugin-provided tool that stage input and output files) validate each file's `lane_path`. This validation was restructured into one shared helper used for both input and output files. Previously, the code checking output files could reference the wrong file's path when reporting or validating an error, instead of the specific entry actually being checked.

**Why**

This fixes a bug where an error about an invalid output file path could point at the wrong file, which would be confusing when trying to diagnose a staging problem.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Resume now also validates a message's turnOrigin field

Resuming a session now also checks and strips invalid turnOrigin values from user messages

**What**

When Claude Code loads a saved session back into memory, it already checked the `permissionMode` field on each user message and cleared it if it wasn't valid. Now it does the same for a field called `turnOrigin`: if a resumed message carries a `turnOrigin` value that isn't one of the recognized ones, Claude Code strips it out.

**Why**

This keeps resumed sessions from carrying forward corrupted or outdated `turnOrigin` data, matching the same safety check already in place for `permissionMode`.

- Area: Sessions
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Agent memory files refuse to load from symlinks/special files or outside the working copy

Agent memory files no longer load through symlinks or files outside the project, and fall back to read-only

**What**

When Claude Code reads an agent's persistent memory file, it now checks that the file is a genuine regular file, not a symlink or a special file, and confirms it's actually inside the current working copy before reading it. If that check fails, the memory content is treated as empty and the session is told the memory is read-only for that turn, instead of silently reading through the symlink as it did before.

**Why**

This prevents an agent's memory file from being swapped for a symlink or special file that points somewhere unexpected, such as outside the project, which could otherwise let memory reads leak or be tampered with.

- Area: Memory
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### File-identity stamping now distinguishes directories and avoids confusing a file with the null device

Directory sync now correctly stamps directories as directories and avoids mistaking files for the null device

**What**

The helper that stamps files for directory sync now explicitly detects when a path is actually a directory, and records it as `directory` instead of falling through to file-hashing logic meant for regular files. It also guards against a target being indistinguishable from the system's null device, and the warning message shown when stamping fails now mentions this case explicitly.

**Why**

This avoids directory sync mishandling directories as if they were regular files, and gives a clearer warning when a file genuinely can't be read or identified.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### permission_retry summary UI now shows raw content when no allowed commands exist

Permission-retry status line now falls back to raw text when there are no allowed commands

**What**

The status line shown for a `permission_retry` used to always render as "Allowed <commands>". It now checks whether there are any allowed commands to list; if there aren't, it instead renders the retry's free-form content text, and if both the commands list and the content text are empty, it renders nothing at all.

**Why**

This prevents the status line from showing an empty or misleading "Allowed" message when a permission retry didn't actually involve any specific allowed commands.

- Area: Tool Results
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### OAuth API-key creation now sends a User-Agent header and handles 4xx refusals distinctly

OAuth API key creation now sends a User-Agent header and reports outright refusals separately from other failures

**What**

When Claude Code mints an API key through OAuth (the login flow used to authorize the app), the request now includes a `User-Agent` header identifying the client. It also now tells apart two kinds of failure: a 4xx response that isn't already recognized as "you need to verify your account" now triggers a new `oauth_api_key_refused` telemetry event and a distinct error, instead of being lumped into the generic `oauth_api_key_request_failed` case.

**Why**

This makes it possible to tell, from telemetry, when the server actively refused to issue an API key rather than the request simply failing for some other reason, which should help diagnose account-setup problems.

- Area: Auth
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### JSON string repair now also guards against control-character unicode escapes

JSON repair for tool output now also leaves control-character unicode escapes alone

**What**

The routine that repairs double-escaped unicode sequences in tool JSON output now also detects `\u` escapes representing control characters (in the C0 and C1 character ranges) and skips repairing them, tracked with a new counter. This is in addition to the existing behavior of skipping Windows file paths.

**Why**

This prevents the repair logic from mangling legitimate control-character escapes, reducing the chance of it corrupting tool output that happens to contain them.

- Area: Tool Validation
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Artifact read guard: treat never-published artifacts as OK to proceed

Artifact reads for never-published artifacts now proceed instead of failing when guarded

**What**

When Claude Code tries to read an artifact (a generated file such as a document or piece of code shown alongside the chat) and that read fails in a specific, recognized way while running under a `client_guard` route, it no longer treats this as a hard failure. Instead it logs an event called `artifact_guard_autoread` with the mode `proceed_never_published`, and lets the operation continue.

**Why**

An artifact that was never published yet can look like a failed read even though nothing is actually wrong. This change stops that specific case from blocking the flow unnecessarily.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Session resume now discards detached/orphaned tool-call notifications

Resuming a session now discards leftover notifications for tool calls outside the restored history

**What**

When Claude Code restores a session's file-reading state after resuming, it now calls a new step that finds any tool calls that fall outside the restored range of messages and removes any pending notification-queue entries that still reference them.

**Why**

This prevents stale or orphaned notifications from a previous, no-longer-relevant part of the conversation from lingering after a session is resumed.

- Area: Sessions
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### '.ccr-seed' sync now refuses to push into its own reserved lane path

File sync now refuses to push files into its own reserved `.ccr-seed` directory

**What**

A new guard rejects any file-sync push whose path is, or is inside, the `.ccr-seed` directory, which is reserved for sync's own internal use. This is checked when pushing a synced file, when re-fetching a seed, and when scanning for changed files, and a rejection is logged with the reason `lane_path_reserved`.

**Why**

This prevents file sync from accidentally overwriting or interfering with its own internal state, which could otherwise corrupt the sync mechanism itself.

- Area: Directory Sync
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Terminal renderer reprobes cell pixel size on SIGWINCH/resize

Claude Code re-measures terminal cell pixel size whenever the terminal window is resized

**What**

When the terminal window is resized, including via the `SIGWINCH` signal (the standard Unix signal terminals send on resize), Claude Code now re-measures the pixel dimensions of a single terminal character cell, in addition to its existing resize handling and re-rendering.

**Why**

Knowing the current cell pixel size accurately matters for features like inline image display, which need to convert between character-cell and pixel measurements; re-measuring on resize keeps that conversion correct after the window changes size.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Artifact creation now distinguishes a retried/duplicate creation from a fresh one

Artifact creation errors now note when an earlier retry already created the artifact

**What**

When creating an Artifact from an Artifact type succeeds but then fails to publish its files, the error message now checks whether the artifact was already created by an earlier attempt of the same call. If so, it says "An earlier attempt of this call already created the Artifact ... so nothing new was created," instead of always claiming a brand-new Artifact was made.

**Why**

This avoids a misleading message when a retried operation actually just found the artifact that a previous, duplicate attempt already created, making it clearer that no duplicate artifact exists.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Terminal control-character detection widened to catch image placeholders and unpaired surrogates

Terminal rendering now also flags image placeholder characters and broken surrogate pairs as unsafe control characters

**What**

Claude Code checks rendered text for raw control characters (characters that don't print visibly but can affect terminal behavior) when they appear outside its own escape-sequence handling. This check now also catches two more cases: image placeholder characters, and unpaired surrogate halves (broken pieces of certain multi-part Unicode characters that should always come in pairs).

**Why**

Catching these additional cases helps prevent malformed or unexpected characters from corrupting terminal output or causing rendering glitches.

- Area: Terminal Rendering
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### CCR client: ack timestamp now set for every event in a batch, not just one

CCR client now stamps an acknowledgement timestamp on every event in a batch, not just one

**What**

When a batch of durable events is successfully sent to the server, the client that handles this (CCR) now loops through all events in the batch and stamps each one with `ackedAtMs`, the time it was acknowledged. Previously only a single event in the batch was stamped.

**Why**

This fixes a bug where only one event in a batch would be marked as acknowledged, even though the whole batch succeeded, which could have caused the other events to be treated as unacknowledged.

- Area: CCR
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Tool-invocable status forces reserved names like __proto__ to stay callable

A tool or command literally named __proto__ is now always kept callable regardless of visibility settings

**What**

Claude Code now has a guard that specifically checks for a command or tool named exactly `__proto__`. Regardless of user or policy settings that would normally control slash-command visibility, a tool with this name is treated as a 'reserved name' and its invocable status is forced to either 'on' or 'user-invocable-only'.

**Why**

This prevents a tool named `__proto__` (a special property name in JavaScript objects) from being hidden or disabled by normal visibility settings, likely avoiding a class of bugs where such a name would otherwise be treated unpredictably.

- Area: Permissions
- Names: `__proto__`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Account switch now clears an additional provider cache and reorders cache invalidation

Switching accounts now also clears a second cached-models store and adds another provider cache clear

**What**

When you switch accounts in Claude Code, it already cleared certain cached data. Now it also clears `providerCache.validatedModels` (moved to run earlier in the sequence, or duplicated there) and clears a second, previously-untouched cache.

**Why**

This helps ensure that stale cached data about validated models or providers from a previous account doesn't linger and affect behavior after you switch to a different account.

- Area: Auth
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Update staging directories now get a random suffix and are always cleaned up

Update staging folders now get a random suffix and are always cleaned up afterward

**What**

When Claude Code downloads a native update (including during a force reinstall), the temporary staging folder it uses now includes a random 4-byte hex string in its name, in addition to the process id and timestamp it already used, to avoid name collisions. The staging folder is now also always removed afterward, whether the update succeeded or failed, with a warning logged if removal itself fails.

**Why**

This prevents leftover staging folders from update attempts, whether from naming collisions or from failed cleanup, from piling up on your machine.

- Area: Updater
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Fast-mode toggle behavior adjusted while a background auto-mode setup is in flight

Fast mode's setting sync now behaves differently while a background auto-mode setup is still running

**What**

When background auto-mode setup is in progress, Fast mode's settings-sync logic no longer takes its usual early exit, and instead forces the Fast-mode toggle to apply only to the current session rather than being saved more broadly.

**Why**

This avoids Fast mode's setting sync racing with an in-progress auto-mode setup, keeping the toggle scoped to the current session until that setup finishes.

- Area: Models
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Agent memory now refuses to read through symlinks leaving the working copy

Agent memory files behind symlinks leaving the project folder are no longer read

**What**

Claude Code's agent memory feature (where an agent keeps notes in a MEMORY.md file) now checks that the memory directory or file actually resolves to a real location inside the current project folder before reading it. If it's a symlink pointing somewhere else, a broken (dangling) link, or a path that can't be resolved, Claude Code now skips reading it and records a telemetry event instead of silently following the link.

**Why**

This prevents agent memory from silently reading files from outside the project, which closes off a way memory content could leak in or out via a symlink.

- Area: Memory
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Duplicate-submit guard added to fleet dispatch and fleet reply (`sameChunk`)

Fleet dispatch and fleet reply now guard against accidentally sending the same command or reply twice

**What**

Fleet's command dispatcher and reply composer now record a short-lived timestamp per query to detect duplicate sends. If a duplicate fire happens within the same event cycle or a short time window, it's silently dropped instead of being processed a second time.

**Why**

This prevents a command or reply in FleetView from being submitted twice due to rapid duplicate triggers, such as double clicks or overlapping event handlers.

- Area: Fleet
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### minimumVersion / requiredMaximumVersion / update target now semver-validated

Version-enforcement settings and update targets are now checked for valid semver before being used

**What**

The code that decides whether the current build of Claude Code is blocked from updating now validates the version numbers it's working with. This applies to the update target itself, as well as to the `minimumVersion` and `requiredMaximumVersion` organization policy settings (`minimumVersion` keeps auto-updates from installing anything below a set version; `requiredMaximumVersion` refuses to start on a version newer than an organization allows). If any of these values isn't a properly formed version number, Claude Code now logs the raw value (truncated) and simply ignores that setting instead of trying to act on bad data.

**Why**

Previously, a malformed version string in one of these settings could have caused the version-enforcement logic to misbehave in unpredictable ways. Now a bad value is safely ignored and logged, so a typo in an organization's policy configuration won't silently break update or startup behavior.

- Area: Updater
- Names: `minimumVersion`, `requiredMaximumVersion`
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### "Artifact" capitalization fixed in path-display UI

UI text fix: 'new artifact from type' is now lowercase, and its file path is quoted

**What**

A small UI label shown when creating a new artifact from a file path now reads "→ new artifact from type" with a lowercase "artifact," instead of the previously capitalized "Artifact." The file path shown alongside it is now wrapped in quotes.

**Why**

This is a minor wording and formatting fix to make the on-screen label read more naturally and make the path easier to pick out visually.

- Area: Artifact Publish
- Tier: You'll notice
- Useful: 1/5
- Signal: 0/5

## In Development

### Read-only agent memory mode added to memory system prompt builder

Persistent memory can now be loaded in a read-only mode that tells the model it can't save new memories this session

**What**

The system prompt builder for Claude Code's persistent memory feature gained a `readOnly` option. When it's used, the model is told: "This memory is read-only this session — you cannot save new memories to it," and the usual instructions for saving or organizing memories, along with the list of memory types, are left out entirely.

**Why**

This lets a session load and use existing memory for context without the model being prompted to try to write new memories into it, which is useful for sessions where memory should stay unchanged.

- Area: Memory
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### New keepalive frames after Stop for remote (CCR) sessions, gated off by default

Remote (CCR) sessions gain keepalive messages after a turn stops, currently off by default

**What**

For remote sessions (using Claude Code Remote, referred to internally as CCR), Claude Code now has a mechanism that sends periodic "keepalive" messages after a turn stops, as long as background tasks are still running (up to a limit). This only applies when the `CLAUDE_CODE_REMOTE` environment variable is set, and is controlled by a setting called `tengu_ccr_keepalive_after_stop_enabled`. When a keepalive session ends, it logs an event recording why it stopped, how many keepalive messages were sent, and how long it was active.

**Why**

Keepalive messages help keep a remote connection alive while background work continues after you've stopped a turn. The setting controlling this, `tengu_ccr_keepalive_after_stop_enabled`, was found off both for this site's account and for the general baseline, and no reading has been taken yet under this release.

- Flag `tengu_ccr_keepalive_after_stop_enabled`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: CCR
- Names: `CLAUDE_CODE_REMOTE`, `tengu_ccr_keepalive_after_stop_enabled`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### New CLI session CRUD gate for CCR v2 wired into MCP client bootstrap

A new gated flag controls session create/read/update/delete support for CCR v2 in the CLI's MCP bootstrap

**Unclear.** What CCR v2 session CRUD actually changes for the user is not described in this finding.

**What**

The MCP (Model Context Protocol) client bridge's periodic status-announce call now includes a new flag, `ccrV2SessionCrudEnabled`, read from a setting called `tengu_ccr_v2_session_crud_cli`. This flag is forwarded downstream under the same name.

**Why**

This wires up a gate that controls session create/read/update/delete behavior for a system referred to as CCR v2, but does not itself describe what that behavior changes.

- Flag `tengu_ccr_v2_session_crud_cli`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: CCR
- Names: `ccrV2SessionCrudEnabled`, `tengu_ccr_v2_session_crud_cli`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### Idle plugin state refresh behind a new gate, with new timing telemetry

Claude Code can now refresh plugin state during idle time in the background, with new timing telemetry

**Unclear.** No reading of the `tengu_ccr_plugin_refresh_in_idle_enabled` gate has been taken, so whether it is active is unknown.

**What**

Claude Code now has an idle-time plugin refresh path that races syncing plugin state against however much time is left in the current turn; if it doesn't finish in time, it still completes the refresh afterward. A new inline helper bundles together computing suppressed MCP servers, reloading agent and plugin definitions, and re-syncing MCP servers, plus logic to decide whether to re-run the refresh if it collides with an install or another idle refresh. New telemetry fields `first_message_handle_ms`, `first_message_handle_cpu_ms`, and `first_message_handle_loop_lag_ms` are now also recorded, alongside a `plugin_state_refresh_join_ms` timing field.

**Why**

This is meant to keep plugin state fresh without blocking your turn, doing the sync work during idle moments instead. This behavior is controlled by a setting called `tengu_ccr_plugin_refresh_in_idle_enabled`.

- Flag `tengu_ccr_plugin_refresh_in_idle_enabled`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Plugin Install
- Names: `tengu_ccr_plugin_refresh_in_idle_enabled`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### New attach-sync safety check for directory sync (git worker), gated by tengu_violin_soundpost

Directory sync gains a pre-attach safety check to verify a checkout can attach cleanly, behind a new gate

**Unclear.** No reading of the `tengu_violin_soundpost` gate has been taken, so whether it is active is unknown.

**What**

The directory-sync git worker now has an `attachSyncEnabled` check that determines whether attaching to an existing remote or local checkout would succeed cleanly, before doing so. It returns one of several states: "unanswered", "switched_off", "commit_not_held", "other_branch", "lines_up", or "not_in_history". A companion function proactively re-triggers this check while sync is in a "listening" state.

**Why**

This is meant to catch cases where a directory-sync checkout can't cleanly attach to the expected commit or branch before problems occur, rather than after. This behavior is controlled by a setting called `tengu_violin_soundpost`.

- Area: Directory Sync
- Names: `tengu_violin_soundpost`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### New "refusal" message rendering for repository-trust folder waits, plus a rows-based renderer for detached/backgrounded tool results

New display styles for background tool results and for repository-trust folder-wait refusals

**Unclear.** It is unclear exactly which repository-trust wait reasons trigger the refusal message, since the feature is gated behind `tengu_violin_bridgepin`, which no reading has been taken of under this release.

**What**

When Claude Code shows the result of a tool call, it now has two new ways of displaying certain results before falling back to the usual error or success view:

- Results from a detached or background tool call (one running separately from the main conversation) are now shown in a new table-style, row-based layout instead of the standard tool-output view.

- When an error result isn't shown in verbose or transcript mode, Claude Code now checks for a "refusal" reason tied to waiting on a repository's trust status, and if found, shows a dedicated, localized message about that instead of the plain error view.

**Why**

This gives clearer, more specific feedback when a tool call is waiting on background work or on a folder's trust status, instead of showing a generic error or a plain tool-output block.

- Flag `tengu_violin_bridgepin`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Tool Results
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### New repository trust confirmation tool pairing

New MCP tools and settings support confirming trust for a repository folder

**What

- Area: Cloud Sessions
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### Repository-trust answer naming flag, off by default

New nameRepositoryTrustAnswers capability flag added, currently off

**Unclear.** What nameRepositoryTrustAnswers actually enables is not stated in the finding.

**What**

A new capability flag, `nameRepositoryTrustAnswers`, was added to the tool/hook feature-flag set. It's controlled by a helper that requires both a first-party account check and a growthbook flag, `tengu_violin_bridgepin`, to be enabled.

**Why**

The flag server currently returns off for this site's account and for the anonymous baseline, so this capability is not active yet; no reading has been taken under this release.

- Flag `tengu_violin_bridgepin`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Cloud Sessions
- Names: `nameRepositoryTrustAnswers`, `tengu_violin_bridgepin`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### New 'directory sync' feature under construction: reserved path, checkout_empty seed kind, and warning about foreign snapshot commits

Early signs of a new 'directory sync' feature: a reserved path, a new seed kind, and a warning message

**Unclear.** The finding doesn't say what directory sync does end-to-end or when it becomes usable.

**What**

Several pieces point to a new, still-developing 'directory sync' subsystem:

- A reserved top-level path check, so anything under a certain directory is now treated as reserved for directory sync

- A new user-facing warning message about snapshot commits belonging to directory sync

- A new `checkout_empty` case added to at least three switch statements that previously only handled `seed`, `clone`, and `folder`

**Why**

These are groundwork pieces for a directory sync feature that isn't fully described yet; the reserved path and warning suggest it will manage its own snapshot commits separately from a user's own.

- Area: Directory Sync
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### device_mcp_consent control-request kind defined but no caller found in this slice

A new 'device_mcp_consent' message format was added for approving MCP server changes on a device, though nothing yet appears to trigger it

**Unclear.** No caller of this new message format was found, so it's unclear when or whether it is currently shown to users.

**What**

A new internal message format called `device_mcp_consent` has been defined. It describes a consent prompt that would list MCP servers (Model Context Protocol servers, external tools Claude Code can connect to) that were changed or added on a device, with a default answer of "not now" if no response is given.

**Why**

This appears to be groundwork for a future feature asking you to approve MCP server changes per device; no part of Claude Code currently triggers this prompt.

- Area: Device Binding
- Names: `device_mcp_consent`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### New "sync at attach" flow for cloud/dir-sync sessions, gated behind two flags plus a peer capability

A new 'sync at attach' step can pull a peer's files in before directory sync starts, gated behind flags and a peer capability

**What**

When a cloud or directory-sync session attaches to a peer, a new function now runs first to check whether the peer advertises a `sync_at_attach` capability and whether the account-level `tengu_violin_soundpost` setting is enabled (which itself depends on the broader `tengu_violin_wood` remote-tools setting). If both conditions hold, Claude Code pulls the peer's files into the local session before the usual push/pull cycle begins, and reports this with a `tengu_dir_sync_attach_offer` telemetry event and a `ccr_dir_sync_attach` counter.

**Why**

This is meant to make attaching to a synced session start from a more complete, up-to-date state by pulling in the peer's files first. The underlying `tengu_violin_wood` remote-tools setting is currently reading off for both this site's account and the anonymous baseline, and no reading for this release has been taken yet for the other settings involved, so it's not yet clear who this applies to.

- Flag `tengu_violin_wood`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Directory Sync
- Names: `tengu_violin_soundpost`, `tengu_violin_wood`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### Device-bind 'elevated tier' ask flow gated behind an unresolved, apparently-off flag; new reregister-and-retry path

Device-bind session creation gains a retry that re-registers the device after a 404, alongside the still-inactive elevated-tier request

**What**

When Claude Code creates a device-bound session, it can ask the server for an 'elevated' security tier, a request now controlled by the `tengu_breezy_fairy` setting together with a check for whether the user's organization enforces a particular policy.

Separately, there's a new retry path: if the server refuses to create the bound session with a 404 (not found) error, Claude Code now re-registers the device and retries the session creation with the newly registered device, only falling back to an unbound (non-device) request if that also fails.

**Why**

The retry path means a stale or missing device registration no longer forces an immediate fallback to an unbound session; Claude Code first tries to fix the registration and retry. The elevated-tier request itself isn't newly introduced here, and this site's account is reading the `tengu_breezy_fairy` setting as off, as is the anonymous baseline, so it has no visible effect for now.

- Flag `tengu_breezy_fairy`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Device Binding
- Names: `tengu_breezy_fairy`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### Dormant prompt-suggestion "plugin owns" opt-out path added but inert

New but currently inert opt-out path lets a plugin skip Claude Code's inline prompt suggestions

**What**

Claude Code's inline prompt-suggestion feature now checks a new condition before generating a suggestion, and if it holds together with an existing agent-context check, skips the suggestion entirely and logs `plugin_owns`. As shipped, though, the new condition always evaluates to false, so this skip path can't currently trigger.

**Why**

This lays groundwork for a plugin to take ownership of prompt suggestions and opt out of Claude Code's own inline suggestions, but the path is not yet reachable in this build.

- Area: Prompt Suggestions
- Names: `plugin_owns`
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### Served-folder notices deduped and capped via a small ring buffer, gated by tengu_violin_chinrest

Notices for shared/served folders are now deduplicated and capped instead of fired one by one

**Unclear.** Nothing has been read yet about whether the `tengu_violin_chinrest` gate is on or off for this site's account.

**What**

When Claude Code starts a headless "served" session (one shared for another device to connect to), it can generate notices about things like folder sync or device binding. Previously these notices were sent out as they occurred. Now they pass through a small bounded buffer that keeps only the latest notice per key and drops duplicates, so the same notice cannot be repeated endlessly.

This behavior is controlled by a gate named `tengu_violin_chinrest`.

**Why**

This prevents a served session from flooding the user with repeated or stale notices about the same underlying condition, keeping folder-sync and device-binding messages relevant and readable.

- Area: Cloud Sessions
- Names: `tengu_violin_chinrest`
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### New terminal-title-suppression gate for SDK-CLI entrypoint

Terminal title can now be suppressed for the SDK-CLI entrypoint, behind a new flag

**What**

Claude Code has logic that decides whether to hide the change to your terminal window's title. It now also suppresses the title when Claude Code is launched with `CLAUDE_CODE_ENTRYPOINT` set to `sdk-cli`, but only if neither `CLAUDE_AGENT_SDK_VERSION` nor `CLAUDE_CODE_REMOTE_SESSION_ID` is set. This is controlled by a new gate, `tengu_quizzical_thimble`.

**Why**

This keeps the terminal title from changing unexpectedly when Claude Code is invoked through this specific SDK-CLI path without the environment markers that would normally indicate an SDK or remote session.

- Flag `tengu_quizzical_thimble`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Terminal Rendering
- Names: `CLAUDE_CODE_ENTRYPOINT`, `tengu_quizzical_thimble`
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### Remote-attach announcement of served tools now feeds repository-trust and dir-sync state

Remote-attach flow now feeds served-tools info into repository-trust and directory-sync state

**Unclear.** The gate `tengu_violin_bridgepin` read off for this site's account and off for the anonymous baseline, with no reading yet taken under this release, so it's unclear whether or how it governs this behavior.

**What**

When attaching to a remote session, Claude Code now updates internal state based on the outcome of announcing which tools it can serve. That state feeds into the payload used to keep a cloud session in sync. The sync payload also gains two new fields: `repositoryTrust`, included when the repository-trust feature is active, and `localTools`.

**Why**

This lets a remote or cloud session know more accurately which tools and repository-trust state are available locally, so it can make correct decisions about what to run.

- Flag `tengu_violin_bridgepin`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Cloud Sessions
- Names: `repositoryTrust`, `localTools`
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### Repository-trust question gated behind tengu_violin_bridgepin

Headless cloud client now restricts a repository-trust permission request to a single-hash format before forwarding it

**Unclear.** The gate `tengu_violin_bridgepin` controlling this was read as off for both this site's account and the anonymous baseline, with no reading yet taken under this release.

**What**

In the headless cloud client, a permission request tied to repository trust is now only passed on to the host if it names exactly one input (a content digest hash) plus a short description. If the request doesn't match that exact shape, it is blocked and a warning is logged instead of being forwarded.

**Why**

This is a tightening of what counts as a valid repository-trust request, closing off requests that try to attach anything other than the expected digest before they reach the host.

- Flag `tengu_violin_bridgepin`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Cloud Sessions
- Names: `tengu_violin_bridgepin`
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### Policy-limits client lazily composed at startup, behind an unresolved gate F()

Policy limits client for the agents view is now lazily loaded at startup behind an internal gate

**Unclear.** What the internal gate condition and `catalogDecision` setting actually control is not established by the evidence.

**What**

A new startup routine checks a catalog decision setting, and if it isn't already set, dynamically loads a policy-limits client module for the agents view. It only actually composes the client when an internal condition is true and a `storageV5` option is present; failures are caught and logged as a warning rather than crashing. It always waits for a "cold start" step to finish before continuing.

**Why**

This defers loading policy-limits code until it's needed and guards startup against failures in that composition step, so a problem there produces a warning instead of breaking the agents view.

- Area: Policy Limits
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### New bash sandbox auto-allow denylist check is wired in but its data source is a stub returning null

New always-block checks for sandboxed bash commands are wired up but their block list is currently empty

**What**

Claude Code's sandboxed bash mode (which runs commands in a restricted environment and can auto-allow certain ones without asking) and a related excluded-command check now both consult a new function meant to supply a list of command substrings and commands that should always be blocked, on top of the existing sandbox configuration.

**Why**

The function that is supposed to supply this always-block list currently just returns nothing, so it has no effect yet. This looks like groundwork for a future denylist rather than a change users will notice now.

- Area: Bash Safety
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### New tengu_violin_bridgepin gate, off by default

New tengu_violin_bridgepin gate controls an unspecified bridging behavior

**Unclear.** What the bridging behavior actually does is not stated in the finding. No reading of this gate has been taken under this release yet, so its current status here is unknown.

**What**

A new remote-configuration gate called `tengu_violin_bridgepin` was added. It's checked with a fallback of off, and combined with another condition before enabling some bridging behavior.

**Why**

The finding does not describe what the bridging behavior does, only that it exists behind this new gate.

- Flag `tengu_violin_bridgepin`: Off in both readings (read for one account on one subscription tier against v2.1.277; this account: off, anonymous baseline: off, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Feature Gates
- Names: `tengu_violin_bridgepin`
- Tier: Nothing to try yet
- Useful: 1/5
- Signal: 3/5
- Present in the build but not switched on

### New gate tengu_parsed_willow (default on) with env override

New tengu_parsed_willow gate (defaulting on) added with CLAUDE_CODE_PARSED_WILLOW env override

**Unclear.** What capability tengu_parsed_willow actually controls is not stated.

**What**

A new function checks the `CLAUDE_CODE_PARSED_WILLOW` environment variable, falling back to a gate called `tengu_parsed_willow`, which itself defaults to true.

**Why**

Nothing has been read yet about how this gate is currently configured, and the finding doesn't say what capability it controls, so its practical effect isn't yet known.

- Flag `tengu_parsed_willow`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Feature Gates
- Names: `CLAUDE_CODE_PARSED_WILLOW`, `tengu_parsed_willow`
- Tier: Nothing to try yet
- Useful: 1/5
- Signal: 2/5
- Present in the build but not switched on

### Remote-tools serving stubbed out with 'external_build' reason in this bundle

Remote-tools serving now always reports 'external_build' as unavailable in this bundle

**Unclear.** The finding doesn't say what 'external_build' means in context or whether this is a temporary state during development.

**What**

The function responsible for populating the list of served remote tools (part of the device-bridge feature that connects tools across devices) now always returns `servedToolsUnavailable: "external_build"`, no matter what's passed to it. Its signature also expanded from three parameters to five, though the two new parameters aren't currently used.

**Why**

In this build, remote tools served through this path are unconditionally reported as unavailable because of being an external build, rather than based on any actual check. This looks like scaffolding for a feature that isn't wired up yet in this bundle.

- Area: Remote Machines
- Names: `external_build`
- Tier: Nothing to try yet
- Useful: 1/5
- Signal: 2/5
- Present in the build but not switched on

## Internal Changes

### update_settings tool can now target more than localSettings, including userSettings.effortLevel

The internal update_settings tool can now write userSettings.effortLevel, not just localSettings

**What**

The internal `update_settings` tool used to only accept writes where the source was `localSettings`. It now also accepts `userSettings` as a source. When writing to `userSettings`, only the `effortLevel` key is allowed, and its value must be a recognized effort level; otherwise the write is rejected with an error.

Writing `effortLevel` through `userSettings` saves it under `modelSettings` as the default for the session's current model, the same path the `/effort` command uses. It explicitly does not persist the `max` effort level (that stays session-only) and does not apply the change live to the currently running session.

**Why**

This gives Claude Code an internal way to save a default effort level for a model without going through the `/effort` command directly, while keeping the same rules `/effort` follows around `max` being session-only.

- Area: Settings
- Names: `userSettings.effortLevel`
- Tier: Under the hood
- Useful: 3/5
- Signal: 3/5

### Rate-limit usage schema adds severity and is_active fields

Rate-limit status data now includes a severity level and whether a limit is active

**Unclear.** How severity and is_active are used or surfaced to the user isn't stated in the finding.

**What**

The data Claude Code reads about rate limits now includes two new fields per limit: `severity` and `is_active`, alongside the existing information about the limit's group, percent used, reset time, and scope.

**Why**

This gives Claude Code more information to work with when showing or reacting to rate limit status, such as distinguishing limits by how severe they are or whether they're currently in effect.

- Area: Rate Limits
- Names: `severity`, `is_active`
- Tier: Under the hood
- Useful: 3/5
- Signal: 3/5

### New pasted_content field on user/replay prompt messages

User prompt messages gain a pasted_content field for text pasted rather than typed

**What**

User-message formats, including the one used for replaying prompts, now carry a `pasted_content` field: content the user pasted into the prompt rather than typed, appended after the typed text (optionally wrapped in `<pasted_content>` tags). Any image or document blocks inside pasted content are ignored; those still need to go in the message's main `content` field instead. Internal handling of user turns was updated to carry this pasted content through as well.

**Why**

This lets Claude Code represent and process pasted text separately from typed text within a prompt, though pasted images or documents must still be attached the normal way.

- Area: SDK
- Names: `pasted_content`
- Tier: Under the hood
- Useful: 3/5
- Signal: 3/5

### New per-tool "backgrounding" policy field, most tools opt out

Tools now declare a backgrounding policy; most tools opt out of running in the background

**Unclear.** The finding doesn't say what "self" backgrounding means in practice or which tool uses it.

**What**

Tool definitions now carry a `backgrounding` field that controls whether a tool call can be moved to run in the background while it's still going. Many built-in tools were updated to explicitly set `backgrounding: "never"`, including:

- `ExitPlanMode`, `KillShell`, `WebFetch`, `PushNotification`, `RunWorkflow`

- `FetchInboxMessage`, `ReadMcpResource`/`ReadMcpResourceDir`

- `ScheduledPrompt` tools and self-hosted-runner tools

Tools that don't set this field also default to `"never"`, and at least one tool now uses `backgrounding: "self"`.

**Why**

This makes explicit which tools are safe to move to the background versus which must run to completion in the foreground, reducing the chance a tool is backgrounded in a way that breaks its expected behavior.

- Area: Background Tasks
- Names: `backgrounding`
- Tier: Under the hood
- Useful: 3/5
- Signal: 3/5

### New tool `backgrounding` field controls detach/self/never execution mode

Tools gain a `backgrounding` setting controlling whether they can keep running in the background

**Unclear.** The finding does not say which tools are actually marked as detach-capable versus self or never, or when background results become visible to the user.

**What**

Many built-in tools — including `WebFetch`, `WebSearch`, `Bash`, `Task`, `PowerShell`, MCP (Model Context Protocol) tools, and various read-only lookup tools — now carry a `backgrounding` property set to one of three values: `"detach"`, `"self"`, or `"never"`. Tools without a value default to `"never"`. A new internal check looks at whether a tool's `backgrounding` is `"detach"` to decide if that tool call is allowed to keep running in the background, with its result delivered later through a separate message once it finishes.

**Why**

This lays the groundwork for certain tools to run in the background instead of blocking the conversation while they complete, letting Claude Code (and the user) continue working while a long-running tool call finishes elsewhere.

- Area: Background Tasks
- Names: `backgrounding`
- Tier: Under the hood
- Useful: 3/5
- Signal: 3/5

### New `onCancelAsyncMessage` callback threaded through Remote Control bridge session setup

Remote Control session setup now threads through a new callback for cancelling a queued message

**What**

The setup code for Remote Control bridge sessions (used to connect Claude Code to remote clients like a mobile app) now accepts and passes along a new `onCancelAsyncMessage` callback, alongside its existing handlers for things like interrupting or stopping a task.

**Why**

This is plumbing to support cancelling a specific queued message from a remote client mid-session, rather than only being able to interrupt an entire turn.

- Area: Remote Control
- Names: `onCancelAsyncMessage`
- Tier: Under the hood
- Useful: 2/5
- Signal: 3/5

### Deferred tool description loading

Tool descriptions can now be marked as deferred and built through a new describe-hooks step

**Unclear.** It isn't clear which tools use deferred descriptions or what a user would observe differently as a result.

**What**

When Claude Code builds a tool's schema and description, a tool can now be marked as having a "deferred" description. Deferred tools now run through a new describe-hooks step during setup, unless a `withoutToolDescribeHooks` option is set to skip it, and Claude Code records whether the deferred flag actually changed.

**Why**

This adds a mechanism for building certain tool descriptions later rather than upfront, though the finding doesn't specify which tools use it or what practical difference a reader would notice.

- Area: Tool Schema
- Names: `withoutToolDescribeHooks`
- Tier: Under the hood
- Useful: 2/5
- Signal: 3/5

### Model catalog version bump and per-surface model reassignment

Bundled model catalog updated to version 629 with model reassignments across ccr, ccd, and other surfaces

**Unclear.** The finding does not specify which surfaces ended up on which of the three models after this swap.

**What**

The bundled model catalog that Claude Code ships with was updated from version 554 to version 629, with a new issue and expiry window. Several catalog surfaces, including `ccr` and `ccd`, had the model assigned to their existing slot swapped between `claude-fable-5-1`, `claude-sonnet-5`, and `claude-opus-5`.

**Why**

This changes which model a given surface falls back to when using the bundled catalog, continuing the same kind of reassignment seen in earlier catalog updates for `ccr` and `ccd`.

- Area: Models
- Names: `claude-fable-5-1`, `claude-sonnet-5`, `claude-opus-5`
- Tier: Under the hood
- Useful: 2/5
- Signal: 3/5

### claude.ai plugin/skill sync flags renamed

Flags controlling claude.ai plugin and skill sync were renamed to claudeai-scoped names

**What**

The feature flags that control whether plugins and skills sync from claude.ai were renamed, moving from account-scoped names to claudeai-scoped names such as `tengu_claudeai_plugins_sync_enabled` and `tengu_claudeai_skills_sync_enabled`.

**Why**

This is an internal rename rather than a behavior change for users; the underlying sync functionality is unaffected.

- Flag `tengu_claudeai_plugins_sync_enabled`: Gate removed from the code (read for one account on one subscription tier against v2.1.277; this account: on, anonymous baseline: on, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Flag `tengu_claudeai_skills_sync_enabled`: Gate removed from the code (read for one account on one subscription tier against v2.1.277; this account: on, anonymous baseline: on, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Feature Gates
- Names: `tengu_claudeai_plugins_sync_enabled`, `tengu_claudeai_skills_sync_enabled`
- Tier: Under the hood
- Useful: 2/5
- Signal: 3/5

### Directory-sync git worker gains an 'attached machine' / standing-journal mode

Directory sync's git worker gains an 'attached machine' mode with standing journals and new detach reasons

**What**

The git-based directory-sync worker gained a substantial new code path around live syncing to a remote machine:

- journals (its sync records) can now be "standing" as well as the previous "note"-based kind

- checkouts can be "attached" to a live remote machine, tracked with a new `attached` flag and a `bookkeepingOnBranch` state

- a new detach flow ends sync for specific reasons, such as `branch_switched` or `machine_stopped`, instead of only the previous generic "ended" flow

- new fields `foldedInstall`, `readsStanding`, and a `keepCheckoutPath` marker (with a companion `.offered` file) track this state, letting an existing checkout be recognized as already attached instead of always redoing the initial setup

**Why**

This lets directory sync track and recover a live connection to a remote machine more precisely, distinguishing why a sync session ended and avoiding unnecessary rework when a checkout is already properly set up.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 2/5
- Signal: 3/5

### Announcement-style context blocks can be repositioned to just before the closing line

Certain system announcements can now be moved to sit right before the closing line at session start

**Unclear.** The finding does not say what effect this repositioning has on model behavior or when it is triggered versus the default placement.

**What**

Claude Code has a mechanism for placing 'announcement' blocks (informational content injected into a session, such as `sandbox_instructions`, `environment`, `model`, `proactivity`, `attention_budget`, `deferred_tools_delta`, `agent_listing_delta`, `mcp_instructions_delta`, `mcp_dropped_tools_delta`, `skill_listing`, `output_style_instructions`, `language`, and `auto_mode`) into the conversation. A new placement option lets these be moved, at the start of a session, to just before the closing line instead of their normal position. Internally this is tracked with telemetry noting either why a move was skipped (for example, no reason to announce anything, no user message yet, or a model that doesn't support system messages) or how many announcements were actually moved.

**Why**

This changes where certain system-level notices appear in a session's context without changing their content, which can affect how models weigh information that arrives right before they respond.

- Area: System Prompt
- Tier: Under the hood
- Useful: 2/5
- Signal: 3/5

### Remote bridge gains an onCancelAsyncMessage RPC handler

Remote clients can now cancel a queued background message instead of only interrupting an active turn

**What**

The remote-bridge transport, which lets a remote client control a Claude Code session, gained a new `onCancelAsyncMessage` handler. It lets a remote client cancel a message it previously sent asynchronously (in the background) by removing it from the queue by its ID, or by withdrawing it before it's processed.

**Why**

Before this, a remote client could interrupt an active turn but had no way to take back a background message it had already queued. Now it can cancel a queued message directly.

- Area: Remote Control
- Names: `onCancelAsyncMessage`
- Tier: Under the hood
- Useful: 3/5
- Signal: 2/5

### Per-tool 'backgrounding' classification rolled out across nearly all built-in tools

Nearly every built-in tool now carries a 'backgrounding' classification of never, self, or detach

**What**

Almost all of Claude Code's built-in tools — including `Bash`, `Task`, `WebFetch`, `WebSearch`, MCP tools, `Edit`, `NotebookEdit`, `Read`, `Glob`, the todo tools, `SendMessage`, and various self-hosted-runner tools — now declare a `backgrounding` field set to `"never"`, `"self"`, or `"detach"`. A new helper function fills in a default value for any tool that doesn't set one.

**Why**

This lays groundwork for Claude Code to treat tools differently depending on how they should behave when work is pushed into the background (for example, whether a running command can safely detach and keep going versus needing to stay tied to the current turn). It's an internal classification rather than something you configure directly.

- Area: Background Tasks
- Names: `backgrounding`
- Tier: Under the hood
- Useful: 3/5
- Signal: 2/5

### Plugin UI render pipeline gains Image/Raster component restamping

Plugin UI rendering adds support for a new 'Image' element type alongside the existing 'Raster' type

**What**

The machinery plugins use to render and update UI elements now handles a new `Image` element type in addition to the existing `Raster` type, with matching logic for tracking and refusing invalid updates. A new error message appears when a render hook tries to return an image it didn't actually draw itself.

**Why**

This adds a distinct image element type for plugin UIs while keeping the same safeguards against a render hook incorrectly claiming an image it didn't produce.

- Area: Plugin UI
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Prompt queue gains explicit withdrawal tracking and delivery class tracking

Claude Code now tracks whether queued prompts have been withdrawn and what delivery class they used

**What**

The internal system that tracks queued prompts and commands now keeps an explicit record of whether each queued item has been withdrawn, using a lookup keyed by item id along with helper functions to register and check-and-withdraw entries. The delivery-recording logic also now tracks which items were held alongside a delivery class, and tracks lineages it has already seen.

**Why**

This is internal bookkeeping for how queued prompts move through the system; it isn't described as changing what a user sees, but it should make the queue's withdrawal and delivery state more reliable to track.

- Area: Prompt Queue
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Plugin install supports a preview download path with randomized temp filename

Plugin preview downloads now use a randomized temp filename and are left in place instead of being installed

**What**

When Claude Code downloads a plugin archive from a URL with a preview flag set, it now writes the download to a temp file named `<name>.preview-<random-hex>.part`, instead of the normal temp filename. Unlike a regular download, this preview file is left where it is rather than being moved into the plugin cache.

**Why**

This lets Claude Code download a plugin for preview purposes without actually installing it, keeping the preview file separate from a normal installed plugin.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Attachment rendering can now rewrite or drop transcript entries via ELr lookup

Transcript rendering can now drop or rewrite individual entries based on a per-entry lookup

**Unclear.** What determines whether an entry is marked left-out or rewritten, and what triggers the bypass flag, isn't stated in the finding.

**What**

A new function wraps the part of Claude Code that turns an attachment into a displayed transcript message. It checks a per-entry lookup to see if that attachment's rendering has been marked "left-out" or "rewritten":

- If marked "left-out", nothing is rendered for it, unless a bypass flag is set

- If marked "rewritten", the rendered text is replaced using a new helper

**Why**

This gives Claude Code a way to suppress or alter how specific transcript entries are displayed, rather than always rendering an attachment as-is.

- Area: Terminal Rendering
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Prompt/turn queue rendering gets a new 'humanTurn prompt' redaction path

Queued prompts shown in 'prompt' mode now get a redaction pass applied before display

**Unclear.** What content the redaction function removes or hides isn't stated in the finding.

**What**

When building the transcript, Claude Code now detects a specific case: a queued command attachment in a human turn's "prompt" display mode that isn't a meta entry and meets a couple of internal conditions plus a gate. When this case is detected, the message content for the relevant non-meta rendered entries is passed through a new redaction function before being added to the displayed transcript.

**Why**

This suggests certain queued-command content shown in prompt mode is now filtered or redacted before being displayed, though the finding doesn't say what specifically gets redacted.

- Area: Terminal Rendering
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New enterprise validation for marketplace-restriction settings

Marketplace allow/block settings are now checked for enforceability, with unsafe entries handled differently by list

**What**

Entries in `strictKnownMarketplaces` (an allowlist of marketplace sources) and `blockedMarketplaces` (a blocklist) are now validated to make sure they can actually be enforced:

- regex patterns in these settings must compile successfully

- GitHub-source entries using an owner wildcard must be written exactly as `<owner>/*`

- git-source wildcards are only allowed in GitHub-style entries

- refs (branch/tag references) can't contain a `*`

An entry in `blockedMarketplaces` that fails this check is kept anyway, with a warning, because dropping it would loosen restrictions. The same kind of invalid entry in `strictKnownMarketplaces` is dropped instead.

**Why**

A malformed pattern that can never match anything would silently do nothing. Keeping unenforceable blocklist entries (rather than dropping them) makes sure a typo doesn't accidentally open up access that was meant to stay restricted.

- Area: Settings
- Names: `strictKnownMarketplaces`, `blockedMarketplaces`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Settings alias handling gains an explicit 'unset via null' mode

Setting a renamed settings key's old alias to null can now explicitly reset it instead of just being dropped

**What**

Some settings keys have both a current name and an older alias. Previously, setting the alias to `null` had one behavior. Now, when a special mode called `loneNullAlias === 'rename'` applies and the current (canonical) key has no value set, setting the alias to `null` is treated as an explicit reset: Claude Code writes `null` onto the canonical key before removing the alias. In other cases, the alias is just dropped as before.

**Why**

This lets a `null` on an old setting name still express 'clear this setting' after it has been renamed, instead of that intent getting lost.

- Area: Settings
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Device registry registration gains a forced 're-learn' path and stricter conflict handling

Device registration gains a forced re-registration path and clearer handling of already-registered devices

**What**

The function that registers a device now accepts a `relearn` flag that skips any cached registration and re-registers the device even if a cached device UUID already exists. Separately, when the server responds with HTTP 409 (or a specific error code) along with a `revoked_at` timestamp, this is now treated as a distinct 'already exists, needs relearning' condition with its own error class, rather than being folded into the generic revoked-key error handling.

**Why**

This distinguishes 'this device needs to be re-registered' from a genuine revoked-key failure, and gives a way to force re-registration when needed.

- Area: Auth
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New sync-journal 'reason' enum for why a remote/local git hold state changed

Sync journal for git 'hold' state now records a specific reason code for each change

**What**

Claude Code's sync journal, which tracks why a remote or local git repository is put on 'hold' (paused from syncing), now uses a fixed set of reason codes: `commit_not_held`, `not_in_history`, `other_branch`, `switched_off`, `diverged`, `branch_switched`, and `machine_stopped`. A new check function detects start-failed or detached states, and any reason that doesn't match the known set is recorded as `other`.

**Why**

This gives a consistent, structured record of why sync was held at any given point, rather than a loosely defined reason.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Attribution tracking gains multi-root support

Code-attribution tracking now supports multiple project roots

**What**

The attribution tracker that records how much of each file's content came from Claude versus a human (used for the code-attribution report) now records an optional `root` alongside each file's content hash, Claude-contribution data, and modification time. The key used to look up a file's attribution state is now computed relative to a resolved root, instead of using a flat path-based key as before.

**Why**

This lets attribution tracking correctly handle files across multiple project roots, rather than assuming everything lives under a single root.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### FileHistory backup restore returns structured outcomes instead of throwing

File-history backup restore now reports structured failure reasons instead of crashing

**What**

When Claude Code restores a backup file during a rewind or checkpoint, the restore step now returns a structured result describing what happened, instead of throwing an error. The result says whether the restore failed, was already present, or was migrated, and, on failure, at which stage it failed: a bad backup source, or a problem at the source, link, copy, or rename step.

Rename failures now log a clearer explanation of the likely cause, such as a scanner or sync tool still holding the newly written file, or a mount that allows creating files but not renaming them.

**Why**

This makes backup-restore failures easier to diagnose instead of surfacing as a generic crash, and it explains real-world causes like antivirus scanners or cloud-sync tools interfering with file operations.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New per-turn wait for staged files before handoff (tengu_turn_handoff_staged_files_wait)

Claude Code now waits for in-flight staged file operations to settle before handing off a turn

**Unclear.** Nothing has been read yet about whether the `tengu_turn_handoff_staged_files_wait` gate is on or off for any account.

**What**

Claude Code now tracks staged file operations that are still in progress, and before handing off control at the end of a turn, it waits (up to a timeout) for those operations to finish. It records an event, `tengu_turn_handoff_staged_files_wait`, with the outcome, how long it waited, and how many operations were still pending, and logs a warning if the wait times out.

**Why**

This is meant to avoid a turn handing off while file staging is still mid-flight, though it isn't yet known whether this behavior is active for any given user.

- Area: Turn Handling
- Names: `tengu_turn_handoff_staged_files_wait`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### CCR auth-token refresh now accepts 'gateway placeholder' session tokens, not just JWTs

CCR auth-token refresh now also accepts a non-JWT 'gateway placeholder' session token

**What**

When Claude Code Remote refreshes its authentication token, the session token it receives can now be one of three things: a decodable JWT (checked as before for expiry and staleness), a non-JWT "gateway placeholder" token that must match either the token currently held in the process or a previously verified JWT, or a token that gets rejected outright. When a placeholder token is adopted, it's logged in the `cli_worker_auth_refresh_adopted` event with a new `session_token` field describing which of these cases matched.

**Why**

This lets remote authentication refresh handle a wider range of valid session token formats without weakening the checks that reject tokens that don't match anything trusted.

- Area: CCR
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New 'standing' lightweight status message in cloud dir-sync

Cloud directory-sync gained a lightweight 'standing' status message separate from full sync reports

**What**

The protocol Claude Code uses to keep a cloud sandbox's files in sync with your local copy (built on git) can now send a new, lightweight message kind called `standing`, decoded by a new `decodeWorkerStanding` function. This is distinct from the existing full sync note/report messages. When a `standing` message arrives, the client updates its local record from it and reports a new outcome code, `peer_standing`, instead of the usual `nothing_new` or `applied`.

**Why**

This gives the sync protocol a smaller, cheaper way to report status between the cloud and local sides without sending a full sync report each time.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Footer can now claim ownership of a key before prompt-input handles it

The footer can now claim a keypress before the prompt input box handles it

**Unclear.** The finding does not say what footer element or keys this applies to.

**What**

The main prompt-input component (the box where you type your message) now receives a `footerOwnsKeyOf` callback. When a keybinding is pressed, the input's keybinding wrapper checks this callback first, and if the footer reports it already owns that key, the input's own chat keybinding handler is skipped.

**Why**

This avoids conflicts where a key press meant for something shown in the footer would otherwise also trigger an action in the prompt input box.

- Area: Terminal UI
- Names: `footerOwnsKeyOf`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Cloud/remote directory-sync 'empty git start' now distinguishes detached vs attached sessions and checks reflog

Cloud directory-sync's initial-checkout logic now distinguishes detached from attached sessions and checks the reflog

**What**

The logic that determines the starting state of a git checkout when syncing a sandbox or cloud checkout now explicitly tracks whether the branch is detached (has no branch name), and records this along with an origin value in its telemetry. It also now checks for matching refs under both the existing turns-ref prefix and a new second ref prefix, and checks whether a HEAD reflog exists, before deciding whether a checkout should be treated as 'unborn' (no commits yet) or 'committed'.

**Why**

This makes the sync system's judgment about a fresh checkout's state more accurate, covering detached-branch sessions and an additional ref location that weren't distinguished before.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### SDK bridge re-announce now also reacts to MCP command-list changes

SDK bridge now re-announces its init state when the list of MCP commands changes, not just model or permission settings

**What**

The function that decides whether the SDK needs to re-send its 'system/init' bridge announcement now also factors in the sorted list of non-terminal MCP command names, in addition to the model, permission mode, fast-mode, and effort settings it already checked.

**Why**

This means that if the set of available MCP commands changes during a session, SDK-connected clients are now notified via a fresh announcement, keeping their view of available commands in sync.

- Area: MCP
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### API client builder gains a permissionContext parameter and querySource default

The internal API client builder gained a permissionContext parameter and a querySource setting

**Unclear.** What permissionContext and querySource actually affect in the client's behavior is not described in this finding.

**What**

The internal function that builds the Anthropic API client, handling headers, authentication, and provider routing for Bedrock, Vertex, Foundry, gateway, and similar setups, now accepts a new `querySource` parameter, which defaults to the existing `source` value, and a new `permissionContext` parameter. Some existing fields were also renamed to `agentContext`, `credentials`, and `storageV5`.

**Why**

This finding shows the API client builder gaining new inputs but does not describe what they change in the client's behavior.

- Area: API Client
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Conversation-construction pass gains a queued-item flush step before reminder bookkeeping

Conversation rebuilding now flushes a queued-item buffer before its reminder bookkeeping, and does so more often

**What**

The function that reconstructs the message list sent to the model, folding in reminders, truncation notices, and tool-result repairs, now maintains a queue of pending items and a flush step that merges them into the last user message, or adds a new one if needed, before its existing reminder-handling logic runs. This flush now runs at more points in the process, including around system, user, and assistant messages, than the previous reminder-clearing step did.

**Why**

This changes how and when queued conversation items get folded into the message history sent to the model, running the merge more consistently across message types.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Tool dispatch gains a 'detached' result path, and hook-output-mismatch errors now carry reason codes

Tool results get a new 'detached' stop path, and hook output errors now carry machine-readable reason codes

**What**

Tool result handling now checks for a `detached` flag; when set, it shows a distinct message and stops early, sometimes reporting 'Execution stopped by hook' if a hook triggered it. Separately, when a `PostToolUse` hook's `updatedToolOutput` (a hook's replacement for a tool's result) fails validation or mapping, the error message now includes a machine-readable reason code — `schema_invalid issues=...`, `mapper_undefined`, or `mapper_throw` — alongside the existing human-readable message.

**Why**

The reason codes make it easier to diagnose exactly why a hook's tool-output rewrite was rejected, rather than only seeing a generic failure message. The detached path gives tool execution a distinct, clearly-labeled way to stop when a hook halts it.

- Area: Tool Validation
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Skills with reserved names get a new 'reserved-name' override lock in the plugin/skills manager

Skills with reserved names are now locked to user-invocable-only in the plugin/skills settings UI

**What**

When the settings UI computes whether a skill can be enabled or overridden, a skill whose name fails a new reserved-name check is now locked with `lockSource: "reserved-name"`. This forces the skill's override to on and user-invocable-only, ignoring any user override setting for it.

**Why**

This prevents skills with reserved names from being disabled or reconfigured in ways that could conflict with how those reserved names are meant to work.

- Area: Skills
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Hook execution supports an injected sandbox/exec wrapper

Hook commands can now optionally be run through a sandboxed execution wrapper before they start

**What**

The internal function that runs hook commands now accepts an extra parameter that can optionally acquire a sandboxed executable resource before starting the hook process. If that sandboxed resource can't be obtained, the hook is now treated as having failed to spawn, rather than running normally.

**Why**

This lets hook commands be run inside a sandbox when needed, and ensures that if the sandbox can't be set up, the hook fails safely instead of running outside the sandbox unexpectedly.

- Area: Hooks
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Turn duration now accounts for detached/background tool calls separately

Turn-duration tracking now holds off recording while a detached background tool call is still pending

**What**

Claude Code records how long each conversation turn takes. Now, when a turn ends but a detached tool call (a task or agent running in the background) is still queued or in progress, Claude Code holds off on recording the turn's duration instead of recording it right away. Once the background work finishes, it recomputes the duration and related background-wait counts, then writes the updated duration into the transcript.

**Why**

This keeps recorded turn durations from being cut short by background tasks that are still running, so the timing shown reflects when the work actually finished rather than when the main turn technically ended.

- Area: Turn Handling
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Inbound bridge messages can now be withdrawn mid-ingest

Incoming remote-control messages can now be cancelled while still being processed

**What**

Claude Code's remote-control bridge (the connection that lets a remote client, such as a cross-platform relay, control a running session) now wraps incoming messages in a cancellable handle while they're being ingested. If the message is withdrawn partway through processing, for example before its attachments have been fully loaded, it is dropped instead of being queued, and the system records the attempt as cancelled rather than completed.

**Why**

This prevents a message that's no longer wanted from being processed anyway just because it was already partway through ingestion, and gives more accurate status reporting for messages that get pulled back mid-flight.

- Area: Remote Control
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Transport allocator adds backpressure and refusal callbacks

The data-transport layer gained backpressure detection and refusal callbacks instead of always resending

**What**

The internal channel/frame allocator that manages data transport (its allocate, transmit, and free operations) now supports:

- an `onRefused` callback that can run per allocation

- backpressure detection (`isBackedUp`) checked before resending data

- tracking of orphaned sequences when an allocation is freed

- a `resend` flag on transmit, instead of the previous model of always resending

**Why**

This makes the underlying transport more resilient: it can now detect when it's sending faster than the other side can handle (backpressure) and react to refused sends, rather than blindly resending every time.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Project-context reload now triggered by policy verdict arriving

Project context now reloads automatically once an organization's policy verdict arrives

**What**

The loader that reads a project's context now triggers a reload when the project context comes back empty, tagged with a new reason, `policy_verdict`. A matching status message, "after the organization's policy arrived," was added alongside the existing reload reasons such as `session_start`, `compaction`, and `directory_added`.

**Why**

This ensures project context gets refreshed as soon as an organization's policy decision comes in, rather than staying stale until one of the other reload triggers fires.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Plugin hook manifests now validated against the surfaces they're actually raised on

Plugin manifests are now checked to confirm their UI hooks actually match surfaces where the component appears

**What**

Claude Code now validates a plugin's manifest-declared hooks (for example, a `ToolProgress` hook) against a fixed table of which surfaces, such as the terminal or the desktop app, each UI component actually renders on. If a plugin registers a hook for a surface that component never appears on, or misspells a component or surface name, validation now reports a specific message, such as "no component is named X" or that a component "is raised on the terminal surface only" when the hook names desktop instead.

**Why**

This catches plugin manifest mistakes early, so a plugin author finds out a hook is misconfigured or targeting the wrong surface at validation time rather than discovering it silently does nothing at runtime.

- Area: Plugin Hooks
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New cloud-sync branch-parked reasons: bookkeeping_in_range and scratch_unavailable

Cloud commit sync gets two new explanations for why a branch was parked: bookkeeping_in_range and scratch_unavailable

**What**

Cloud-session commit sync messaging now includes two new cases explaining why commits were parked on a separate branch:

- `bookkeeping_in_range`, explaining that those commits are never made part of your history, though the files themselves were synced as usual

- `scratch_unavailable`, explaining that file contents still sync, and that Claude's cloud commits are in the session's history

These join the existing cases: `not_descendant`, `withheld_in_range`, `kept_path_changed`, and `protected_path`.

**Why**

This gives clearer, more specific explanations for why certain cloud-session commits weren't merged directly into your branch history, so it's easier to understand what happened to your files versus your commit history.

- Area: Cloud Sessions
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Env-var-prefix stripping in shell-command normalization now conditional

Shell-command normalization can now skip stripping VAR=value prefixes when matching permission rules

**Unclear.** The finding does not say which call sites pass false or what practical difference this makes for a user writing permission rules.

**What**

When Claude Code checks a shell command against permission rules, it first normalizes the command text by stripping leading `VAR=value` environment-variable assignments and shell wrapper keywords like `builtin` or `noglob`. That stripping step is now controlled by a new boolean parameter, `n`, which defaults to true. Several existing call sites already pass false, meaning they skip the `VAR=value` stripping and match against the command text as written.

**Why**

This lets some permission checks see the full original command, including any environment-variable prefix, instead of always having that prefix stripped away first. That can affect whether a permission rule matches a command that starts with a variable assignment.

- Area: Bash Safety
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Host-side command cancellation via fold/queue withdrawal

Claude Code can now cancel an in-flight or queued command from the host side by its ID

**What**

A new internal cancellation path can stop a command that is currently running or still waiting in the queue, identified by its ID (`uuid`). Depending on the command's state, it either marks an in-flight operation for cancellation, removes a matching command from the queue, or withdraws an inbound message from a remote client. Once done, it reports the command as cancelled.

**Why**

This gives Claude Code a unified way to stop a specific command wherever it happens to be in its lifecycle, whether it's already running, still queued, or arriving from a remote connection, rather than needing separate handling for each case.

- Area: Remote Control
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Sandbox rules now merge startup read rules with runtime rules, plus new startup_read_rules telemetry

Sandbox rule resolution now merges startup read rules with runtime rules, and reports a startup_read_rules count

**What**

Claude Code's sandbox (the restricted environment tool calls run inside) now combines a set of startup read rules with the runtime rules it already computed, instead of returning only the runtime set. Telemetry for this process also now reports a `startup_read_rules` count.

**Why**

This means the sandbox's effective rule set reflects permissions established at startup as well as those computed while running, so reads that were allowed at startup should no longer be missed when rules are resolved later in a session.

- Area: Sandbox
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Project memory ancestor search now skips remote workspaces and supports a lower bound directory

Project memory file search now skips remote workspaces and can stop at a lower-bound directory

**What**

The search that walks up the directory tree looking for CLAUDE.md and other project memory files now returns early, with a log message, when the current workspace is remote. It also accepts an optional lower boundary directory ('below'), so the upward walk stops once it would go above that path instead of continuing further up the filesystem.

**Why**

Skipping remote workspaces avoids searching a directory structure that likely isn't meaningful to walk this way, and the lower-bound option lets callers limit how far up the search goes, avoiding unnecessary lookups outside a project's boundaries.

- Area: CLAUDE.md Rules
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New prompt-source classification for message origin telemetry

Internal telemetry now classifies where each message came from into one of nine categories

**What**

Claude Code now sorts every incoming message into one of nine origin categories for internal telemetry: `human`, `sdk`, `scheduled`, `task_notification`, `auto_continuation`, `peer`, `host_synthetic`, `system`, or `unknown`. It works this out from more detailed signals than before, including what woke the session up and specific origin types like a scheduled trigger, a peer sending a message, or a relay between projects.

**Why**

This is internal bookkeeping used for telemetry rather than something a user configures directly. Sorting messages this precisely lets Claude Code's own systems tell apart, for example, a message a human typed from one generated by a scheduled job or forwarded from another session.

- Area: Telemetry
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Headless stream-json status frames can now carry a serving notice

Headless status updates from cloud sessions can now include a serving notice message

**What**

The internal format for status updates sent during headless, cloud-hosted sessions (the stream-json status frames) now documents a `notices` field, which can carry a short serving notice message. This joins existing fields covering the serving word/reason, connection status, tool calls, and directory sync.

**Why**

This gives cloud sessions a channel to surface a short informational notice alongside their regular status, rather than only the fixed set of fields that existed before.

- Area: Cloud Sessions
- Names: `notices`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Artifacts gain a live-room join declaration and stricter "open" tool semantics

Artifacts get a live-room join option and clearer rules for when to use "open" versus publish/create

**What**

The description text for artifact tools (used for things like documents, slides, or interactive content generated during a session) now covers a new `room` declaration: joining an artifact's live room means viewer page events arrive back as notifications, and any outbound sends from the artifact need approval first.

- The guidance also tightens when the `open` action should be used versus when a publish or create call has already displayed the artifact, to avoid redundant opens.

- It adds a note that a slide deck built for email or as an attachment, when made from the Slides type, downloads as a `.pptx` or PDF file.

**Why**

This gives the artifact tools clearer rules for interactive, live-updating artifacts and for exporting a deck in a usable file format, reducing confusion about which action to call when.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### set_cwd (headless /cd) now documented to re-anchor session state before the first turn

The internal /cd tool now re-anchors a session's whole state when the move happens before any turn has run

**What**

The internal `set_cwd` tool, used behind the `/cd` command to move a session to a new working directory, now documents a special case: if the directory move happens before any turn has run, it re-anchors the whole session's starting state as if the session had begun in the new directory all along, with no separate notice about the move. If a turn has already run by the time the move happens, the prior conversation context is kept as-is and the move is instead appended as a notice.

**Why**

This avoids cluttering a session with a redundant "directory changed" notice when the move happens right at the start, before there's any conversation to interrupt, while still clearly flagging the move for sessions already underway.

- Area: Directory Change
- Names: `set_cwd`, `/cd`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Remote/cloud session: repository-trust permission answers can now be named and flagged

Remote/cloud repository-trust permission answers can now be named and flagged as user rejections

**What**

When a remote or cloud session responds to a permission request for the `confirm_repository_trust` tool, and the `config.nameRepositoryTrustAnswers` setting is turned on, the response is now annotated with the tool's name, the same way allowed responses were already annotated elsewhere via `nameToolOnPermissionAllow`. A denial of this request can now also carry a `decisionClassification` of `user_reject`.

**Why**

This gives remote and cloud sessions more detailed information about repository-trust permission decisions, including explicitly marking a denial as a deliberate user rejection.

- Area: Cloud Sessions
- Names: `config.nameRepositoryTrustAnswers`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Session-create events can defer the first prompt for device-bound sessions

Device-bound session creation can now defer sending the first prompt separately

**Unclear.** It's unclear exactly how or when the deferred first prompt gets sent after session creation.

**What**

Session creation for device-bound sessions now supports a `deferFirstPrompt` flag. When set, it filters the first user event out of the events sent when the session is created.

**Why**

This appears to allow the first prompt to be sent separately after the session is created, rather than bundled in with session creation, though the finding doesn't specify exactly how that separate send happens.

- Area: Session Lifecycle
- Names: `deferFirstPrompt`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New "separate checkout" project-location kind

New "separate checkout" description added for a session's own dedicated project location

**What**

The function that describes a tool's project location now has a new case, "separate", which describes the location as the session's own dedicated checkout — "the primary copy for this session's work" — alongside the existing default, machine, and unknown cases.

**Why**

This gives Claude Code a distinct, clearer way to describe when a session is working from its own separate checkout of a project, rather than lumping it in with other location types.

- Area: Remote Machines
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New "two copies of the project" guidance for machine/session file-tool calls

New prompt guidance explains linked machines as separate, unsynced project copies with a commit-based workflow to move work between them

**What**

Claude Code's prompt now includes a large new block of guidance about working with a linked machine's copy of a project. It explains that:

- The linked machine's folder is a separate copy of the project that is not automatically kept in sync

- Tools like Read, Edit, Write, and Grep act on the current session's own checkout of the project

- The same tools, when called against the linked machine, act on that machine's separate copy under that machine's own permission rules

- A full git-based workflow is provided for moving work between the two copies, using commit IDs only

- Branch or tag names should never be used for this, and `git pull` should never be used

**Why**

This clears up a source of confusion when a session is linked to another machine: without it, Claude could easily assume both copies of a project are the same or automatically synced, and make edits in the wrong place or lose track of which copy has which changes. The commit-ID-only workflow gives a precise, unambiguous way to move work between the two.

- Area: Remote Machines
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Directory-sync now writes/reads a git-keep marker file to detect prior sync state

Directory sync writes a small marker file to detect whether a folder was previously synced

**What**

Directory sync now reads and writes a small JSON marker file inside a synced directory, recording a version number and the time it was written. It's created exclusively so it can't silently overwrite an existing one, and failures to read or write it are logged. A companion piece of logic also maps the various reasons directory sync can detach from a folder (commit not held, not in history, on another branch, branch switched, switched off, diverged, machine stopped) to explanations shown to the user.

**Why**

The marker file lets directory sync detect whether a folder was already under sync before, which helps it behave correctly across restarts, while the clearer detach-reason mapping means users get a specific explanation instead of a generic one when sync stops.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Plugin UI test API `$.ui.press` now supports non-terminal surfaces

Plugin test helper `$.ui.press` can now press buttons on non-terminal surfaces

**What**

The plugin test API's `$.ui.press` (used by plugin tests to simulate pressing a button) used to only find and press buttons rendered on the "terminal" surface. It now accepts an optional `surface` parameter, so it can filter by and press buttons drawn on other surfaces too. When a press is ambiguous, the error message now names both the request ID and the surface involved to help pinpoint the issue.

**Why**

This lets plugin authors write tests that exercise UI drawn outside the terminal, and makes failures easier to diagnose when multiple matching buttons exist.

- Area: Plugin UI
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### callModel wrapper resolves prompt.attachment hooks before each model call

Model calls now resolve `prompt.attachment` hooks just before each call, if enabled

**What**

A new wrapper around the function that calls the model now checks, before each call, whether hooks are enabled for the current agent and whether the `prompt.attachment` hook is active. If so, it resolves any attachment-rewriting hooks against the outgoing messages before the model call proceeds.

**Why**

This is the mechanism that actually applies the new `prompt.attachment` hook to real model calls, ensuring any attachment rewrites or removals a plugin makes take effect before the message reaches the model.

- Area: Plugin Hooks
- Names: `prompt.attachment`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Cloud session creation can defer sending the first prompt until permission mode is confirmed

Cloud session creation can now send the first prompt separately, after permission mode is confirmed

**What**

When creating a remote or cloud ("teleport") session, the client can now opt in to a mode where the first prompt is left out of the initial signed session-create request and sent separately afterward, once the permission mode it establishes has been stored on the server. This is controlled by a new `deferInitialMessage` option, and the create response can indicate the first prompt was withheld so the caller knows to send it itself.

**Why**

This ensures the permission mode for a new remote session is confirmed and stored before the first prompt is sent, avoiding a case where a prompt could be processed before its governing permission mode is actually in effect.

- Area: Cloud Sessions
- Names: `deferInitialMessage`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### User messages now carry a turnOrigin field describing why the turn started

User messages now record a turnOrigin field describing why that turn started

**Unclear.** The finding does not say what turnOrigin is used for downstream, such as display, logging, or behavior changes.

**What**

After Claude Code builds the result of a query, the first relevant user message is now stamped with a `turnOrigin` value, computed from the message's origin, whether it's a meta message, what woke the session up, where the prompt came from, and what initiated it on the host, unless a value was already set.

**Why**

This records, for each turn, what actually triggered it, which is useful for understanding and debugging how and why a given turn of conversation started.

- Area: Turn Handling
- Names: `turnOrigin`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Hooks worker heartbeat timeout made remotely configurable

The timeout for detecting a stuck hooks worker can now be set remotely instead of always being fixed at 5 seconds

**What**

Claude Code runs a background "hooks worker" process to execute hooks (scripts that run automatically at certain points). It detects a stuck, unresponsive worker by checking whether it has answered a heartbeat check within a timeout. That timeout used to always be a fixed 5000 milliseconds. Now, as long as there are no pending loads or builds in progress, the timeout value can instead come from a remotely configured setting, falling back to the same 5-second default otherwise.

**Why**

This lets the stuck-worker detection threshold be tuned remotely without needing a new release, while keeping a safe fallback during load or build activity.

- Area: Hooks
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Hooks module-reload diagnostics gain a human-readable 'why did we refold' explainer

Hooks diagnostics now explain in plain language why the hooks list was recalculated

**What**

Claude Code can now generate a human-readable explanation of why its internal set of hooks (scripts that run automatically at certain points, often added by plugins) was recalculated ("refolded"). The explanation names which plugin's hooks changed and how — for example, loaded fresh, added to, or removed from the set — or notes that a plugin crashed leaving work withheld, or that the order of the kept modules changed.

**Why**

This makes it easier to understand, when debugging, why the active set of hooks changed rather than just seeing that it did.

- Area: Hooks
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Terminal image-support capability detection reworked into a settle/cache class

Terminal image-support detection was rebuilt around a proper pending/settled state machine

**What**

Claude Code detects whether the terminal it's running in can display images inline. That detection logic has been rewritten to use a small internal state machine with clear stages: not yet asked, currently asking, and settled (answer known), with a way for other parts of the app to be notified once the answer settles. This sits inside a new container class that groups terminal capability checks together. The `CLAUDE_CODE_FORCE_TERMINAL_IMAGES` environment variable still works the same way, immediately forcing the detection to a settled, true state.

**Why**

This is an internal restructuring of how image-support detection is tracked; it should make the detection state more reliable to reason about, without changing the forced-on behavior of `CLAUDE_CODE_FORCE_TERMINAL_IMAGES`.

- Area: Terminal Rendering
- Names: `CLAUDE_CODE_FORCE_TERMINAL_IMAGES`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Image UI element gains a plugin-stamping check and named-key support

Image elements without a resolvable source now must be explicitly marked as coming from a plugin

**What**

The validation for Image elements used in Claude Code's UI now accepts an optional `key` prop, which must be a non-empty string when given. More notably, if an image has no explicit columns/rows and no source that can be resolved, it must now be marked as "stamped by a plugin of this chain." If it isn't, validation now reports a specific error, `Image "<key>" is not stamped by a plugin of this chain`, instead of a generic size-or-source error.

**Why**

This makes it clearer, when an image fails to render, whether the problem is a missing source/size or a plugin-provided image that wasn't properly attributed, which should make such failures easier to diagnose.

- Area: Plugin UI
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New settings validation for strictKnownMarketplaces and blockedMarketplaces

Invalid strictKnownMarketplaces or blockedMarketplaces settings now fail safe instead of being silently misapplied

**What**

Claude Code's settings loading now separately validates two plugin marketplace settings, `strictKnownMarketplaces` (an allowlist of marketplace sources) and `blockedMarketplaces` (a blocklist):

- an invalid `strictKnownMarketplaces` value now falls back to an empty allowlist, meaning no marketplaces are admitted until the setting is fixed

- an invalid `blockedMarketplaces` value is dropped, with a warning that its entries can't be enforced

**Why**

Both failure modes err on the side of restricting rather than silently letting through marketplace sources that shouldn't be trusted, so a broken configuration doesn't accidentally loosen access.

- Area: Settings
- Names: `strictKnownMarketplaces`, `blockedMarketplaces`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Fable/voice model availability logic reworked around gateway vs first-party routing

Availability logic for the fable voice model was reworked around whether requests go through a gateway or directly to Anthropic

**Unclear.** Whether this changes fable's actual availability for any specific group of users, versus just restructuring how the check is computed, isn't clear from the evidence.

**What**

The logic that decides whether the "fable" voice model is available was reworked. It now checks a gate together with another condition earlier in the process, and for accounts not using multi-account routing, it branches on whether requests are routed "firstParty" (directly to Anthropic, always available) or through a "gateway" (routed through an intermediary, where availability is checked separately). This replaces the previous logic, which gated first-party availability differently and had separate fallback handling.

**Why**

This changes how fable's availability is determined depending on how a user's requests are routed, though the finding doesn't specify what practical difference users will see.

- Area: Models
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Command/skill schema gets a builtin marker to resolve name collisions

Commands and skills now carry a builtin flag to resolve naming clashes with plugin or MCP commands

**What**

The schema describing an available skill or command now includes an optional `builtin` field, a true/false value that is set to true only for Claude Code's own built-in commands. It's used to decide which command a bare `/name` invocation should resolve to when a user, project, plugin, and MCP (Model Context Protocol) server all define a command with the same name.

**Why**

This gives Claude Code's own commands a documented way to take precedence over same-named commands from other sources, avoiding ambiguity when names collide.

- Area: Slash Commands
- Names: `builtin`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Raster/paint tool can now target an Image source, not just cell data

A drawing tool can now update an Image using a full image source, not just raw cell data

**Unclear.** It is unclear exactly which tool this applies to or what user-facing feature relies on it.

**What**

A tool used for drawing or painting now accepts two different shapes of input: the existing `{ requestId, key, cells }` form, which supplies encoded cell data for a Raster, or a new `{ requestId, key, source }` form, which supplies a key and a new ImageSource for an Image.

**Why**

This suggests a related image-handling tool can now be updated by pushing a complete image source directly, instead of only being able to send encoded raster (cell-by-cell) data.

- Area: Plugin UI
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New diff-sidebar auto-enable gate function requires a git repo, focus, and terminal width

The diff sidebar now auto-enables only when the repo is git, the main pane is focused, and the terminal is wide enough

**What**

Claude Code now uses a single centralized check to decide when the diff sidebar (the panel that shows file changes alongside the conversation) should turn on automatically. All of these must be true:

- the sidebar feature itself is enabled

- the terminal is in fullscreen mode

- the client is not a "thin" client (a lighter-weight connection type)

- the main pane currently has focus

- the terminal is at least a minimum number of columns wide

- the current working directory is inside a git repository

**Why**

Bundling these checks into one place means the sidebar won't pop up in situations where it wouldn't fit or wouldn't make sense, such as a narrow terminal window, an unfocused pane, or a folder that isn't a git repository.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### SDK init can expose the session's scratchpad path

SDK init can now include the session's scratchpad directory path

**What**

The initialization payload sent by the SDK (the interface other applications use to embed Claude Code) can now include a `scratchpad_path` field, giving the client the absolute file path of the session's scratchpad directory (a working-storage area). This field is left out when the scratchpad feature is disabled, and it is also removed from the redacted version of init data sent over Remote Control or to a hosted worker.

**Why**

This lets SDK clients that need to know where the scratchpad lives access that path directly, while keeping it out of contexts where exposing a local file path wouldn't be appropriate, such as remote or hosted connections.

- Area: SDK
- Names: `scratchpad_path`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Turn schema gains a host-supplied 'initiator' label

Turns can now record an 'initiator' label showing what started them, like a scheduled task or a person

**What**

Claude Code's turn data (the record of one exchange in a conversation) now has an optional `initiator` field recording what started that turn. Examples given include a desktop app's `scheduled-task` or `sleep-auto-resume` features, as distinct from a turn started by a person. This is also threaded through internally as `hostInitiator` in turn context and message equality checks. It does not change how the turn itself runs.

**Why**

This field exists for usage attribution, letting Claude Code distinguish turns that were kicked off automatically (like a scheduled task or auto-resume after sleep) from turns a person started directly.

- Area: Turn Handling
- Names: `initiator`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Host filesystem bridge gains read/stat options and ancestor-search bound

Plugin filesystem read and stat calls gain configurable options, and ancestor search gets an optional lower bound

**What**

The filesystem bridge that plugins and hooks (scripts that run at specific points) use to interact with files now accepts more options:

- `read` takes an `as` option controlling the encoding to read as, defaulting to "text"

- `stat` takes a `resolve` option, defaulting to false

- `ancestors` (which searches upward through parent directories) takes an optional `below` bound limiting how far up it searches

**Why**

These options give plugins and hooks finer control over how files are read and inspected, and let ancestor directory searches be bounded so they don't search further up the filesystem than intended.

- Area: Plugin Hooks
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Compact-handoff-adjacent: transcript lineage tracking added to kept-message keys

Message-key tracking used near compaction now also records transcript lineage and rewind info

**Unclear.** The finding does not say what user-visible effect this added tracking has, only that the data structure carries more fields.

**What**

The internal structure that tracks which message keys were kept or forked (used around conversation compaction, the process that condenses a long conversation history) now carries more information than before. In addition to the plain list of keys, it now includes `transcriptLineages`, a `keysWithClass` subset of messages that meet a particular class check, and a `rewound` flag.

**Why**

This gives Claude Code more detailed bookkeeping about how a conversation's history was split or rewound, which can support more accurate handling of conversation state, though the finding doesn't specify exactly what new behavior it enables.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### max_thinking_tokens / thinking_display schema tightened

Validation for max_thinking_tokens and thinking_display is now stricter

**Unclear.** The finding does not say what triggers this control or who sets these values.

**What**

A new validation schema now checks the internal `set_max_thinking_tokens` control more strictly: `max_thinking_tokens` must be an integer or `null`, and `thinking_display` must be one of a fixed set of allowed values or `null`. Requests that don't match produce a clear error message.

**Why**

This catches malformed values earlier and with a clearer error, instead of letting invalid thinking-token settings pass through silently.

- Area: Thinking Display
- Names: `max_thinking_tokens`, `thinking_display`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Hook manifest scan capability list expanded

The 'scan' hook set's allowed capabilities were expanded and ui.toast was removed

**What**

The capability manifest for the 'scan' hook set (a declared list of what that group of hooks is allowed to do) now permits calling `env.get`, `telemetry.log`, and `telemetry.mark`, and explicitly lists reading the `HOME` and `USERPROFILE` environment variables. The `ui.toast` call, previously allowed, was removed from this set's permitted calls.

**Why**

This changes what 'scan' hooks are allowed to do: they gain access to environment lookups and telemetry logging, but can no longer show toast notifications directly.

- Area: Plugin Hooks
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New settingsHooksOff session option suppresses hooks

settingsHooksOff now suppresses hooks across more isolation and permission checks

**What**

The `settingsHooksOff` option, which disables hook execution for a session or subagent run, is now checked in more places: isolation checks (`isIsolated`), tool-description hook gating (`withoutToolDescribeHooks`), module handler gating (`withoutModuleHandlers`), and permission-check gating.

**Why**

This closes gaps where a run with `settingsHooksOff` set could still trigger hooks through one of these other paths, making the setting more reliably suppress all hook activity.

- Area: Hooks
- Names: `settingsHooksOff`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Pasted content can now be inline and excluded from certain flows

Pasted content can now be marked inline and excluded from prompt persistence and submission

**Unclear.** The finding doesn't say what triggers content being marked inline or where a user would notice the difference.

**What**

Pasted content (text or files pasted into a prompt) can now be marked as `inline`. Code that previously included all pasted entries now filters out ones marked `inline` in two places: when computing paste IDs for saving prompt history, and when building the list of pasted values attached to a submitted prompt.

**Why**

This lets certain pasted content be treated as part of the prompt text itself rather than as a separate attachment, so it isn't double-counted or stored as a distinct pasted item.

- Area: Prompt Input
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New bridge inbox message download support

Bridge inbox messages can now include a direct download link instead of only inline text

**Unclear.** What content types make use of the new download object is not stated.

**What**

The `bridge_inbox_fetch` function, which retrieves messages from a bridge inbox, now can return a `download` object containing a `baseUrl` and an `accessToken` alongside the message text.

**Why**

This suggests that attachments or full messages fetched through the bridge can now be downloaded directly rather than only read inline, though the finding doesn't specify what kind of content uses this new path.

- Area: Remote Control
- Names: `bridge_inbox_fetch`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### per_turn_timing added to model capability/prompt-invalidation list

New per_turn_timing capability flag added alongside per_turn_effort for model prompt construction

**Unclear.** The finding does not say what per_turn_timing controls or how it affects prompt construction.

**What**

A list of capability flags relevant to model prompt construction and cache invalidation gains a new entry, `per_turn_timing`, next to the existing `per_turn_effort`.

**Why**

Since `per_turn_effort` is looked up through a name-to-flag table against remote feature flags, `per_turn_timing` likely works the same way, letting Claude Code track and react to per-turn timing information similarly to how it already tracks per-turn effort.

- Area: Elsewhere
- Names: `per_turn_timing`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Plugin publish states for rate limiting and contract rollout

Plugin publishing gains rate-limited and contract-rollout states

**What**

The plugin publish flow gains two new named states, `publish_rate_limited` and `publish_contract_rollout`, which are also folded into a broader status set used elsewhere in Claude Code.

**Why**

This lets Claude Code distinguish a publish attempt that was throttled for making too many requests from one that is being held back for a staged contract rollout, giving clearer feedback when publishing a plugin doesn't go through immediately.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Plugin hook dispatch deep-copies input for a fixed set of UI/registration events

Plugin hooks now receive a deep copy of the event payload for UI and registration events, not the original

**What**

For a fixed list of plugin events, `ui.open`, `ui.toast`, `ui.status`, `ui.log`, `ui.notice`, `ui.ask`, `tool.register`, `command.register`, `agent.register`, `prompt.fill`, and `prompt.suggest`, Claude Code now passes hooks a deep copy of the event's data instead of the original object, before any hook has a chance to see or change it.

**Why**

This stops a plugin hook from being able to mutate the original event data that Claude Code itself still relies on, isolating hook side effects to their own copy for these UI and registration events.

- Area: Plugin Hooks
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New 'sync_at_attach' capability lets a peer push a fresh file sync as soon as it's attached

A new sync_at_attach capability lets a peer trigger an immediate full file sync on attaching

**What**

A new function offers to proactively sync all files to a peer as soon as it attaches to a session. This only happens if the peer advertises the `sync_at_attach` capability and a local check passes, which itself requires a base capability check to succeed.

**Why**

This means a peer that just attached to a session can be brought fully up to date with the latest files right away, instead of waiting for the usual incremental sync process.

- Area: Directory Sync
- Names: `sync_at_attach`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Session tracker now tracks a distinct "head hooks pending" state before recording transcript history

Session history recorder gains a pending state that holds messages until startup hooks finish

**What**

Claude Code's internal session-history tracker now has a "head hooks pending" state. When it's active, incoming messages are held instead of being recorded immediately, and are replayed once the hooks that run at the start of a session finish resolving. The underlying hook lifecycle machinery now publishes this pending state and waits until after the transcript is spliced in before releasing it, rather than releasing right away.

**Why**

This avoids recording conversation history out of order or before session-start hooks have had a chance to run, keeping the saved transcript consistent.

- Area: Session Lifecycle
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Cloud session view now reports a repositoryTrust fingerprint and retention cutoff for directory-synced sessions

Cloud sessions now report a repository trust value and a retention cutoff for directory-synced files

**Unclear.** The finding does not say how repositoryTrust or the retention cutoff are surfaced to the user, or what specific values they can take.

**What**

When a session is synced to the cloud from a local directory, Claude Code now computes and sends a `repositoryTrust` value describing the trust state of the synced folder. Separately, a new lookup computes a retention cutoff date for directory-synced sessions, determining how far back synced data is kept; if this lookup fails, it falls back to an "unknown" state.

**Why**

These values let the cloud session view show more accurate information about how trusted a synced folder is and how long its synced data is retained.

- Area: Cloud Sessions
- Names: `repositoryTrust`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Policy-limits cache gets a 'held-start' signal separate from verdict-changed

Policy-limits cache adds a separate signal for held starts and a fail-open flag

**Unclear.** The finding does not say what triggers `failOpenVerdict` to be set or what user-visible effect fail-open behavior has.

**What**

The internal cache that tracks policy limits (restrictions on what a session is allowed to do) now emits a `heldStartSignal` every time its verdict-changed event fires. It also tracks a new `failOpenVerdict` boolean alongside the cache's session data, which a helper function reads to decide whether an unresolved policy check should be treated as allowed rather than blocked.

**Why**

This is internal plumbing for how Claude Code's policy gate handles cases where a limits check hasn't resolved yet, distinguishing a 'held' state from a definite verdict change and giving explicit control over whether such a state defaults to allowing an action.

- Area: Compliance
- Names: `failOpenVerdict`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Worktree sync protocol: downApplied history now branches on ack state, adds readsStanding capability

Worktree sync responses now branch on whether the client acknowledged the current commit, and add a readsStanding flag

**Unclear.** The finding does not say what capability `readsStanding` signals to the client or what behavior it unlocks.

**What**

When Claude Code syncs a git worktree (a checked-out copy of a repository) between a client and its session, the response now builds its history of applied changes (`downApplied`) differently depending on whether the client has already acknowledged the current worktree commit. If it has, the history folds in downstream applied changes on top of what was already sent; if not, it falls back to just the reversed sent history. The response also now always includes a new `readsStanding` flag set to true, alongside the existing `acceptsHeldParents` flag.

**Why**

This makes worktree sync responses more accurate for clients that haven't yet caught up to the latest commit, avoiding history that assumes acknowledgment that hasn't actually happened.

- Area: Git Internals
- Names: `readsStanding`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Session resume now tracks transcript lineages and a 'rewound' state, adds class-filtered keys

Session resume now tracks conversation lineage history and a 'rewound' flag, with a new class-filtered key list

**Unclear.** The finding does not say what `rewound` represents in user terms or what distinguishes a 'fresh' turn from one 'with class'.

**What**

When Claude Code resumes a previous session's transcript, the internal helpers that do this now return richer information: a `transcriptLineages` field tracking the history of transcript branches, and a `rewound` boolean. They also now return a `keysWithClass` field, a list of turns filtered down to those matching a particular classification, separate from the full list of turn keys. The logic that picks where to resume a session from was also reworked: instead of scanning for the first turn not already held, it now classifies turns as 'fresh' or 'with class' and picks the resume point from whichever is found first.

**Why**

This is internal restructuring of how Claude Code figures out where to pick back up in a resumed session, adding more explicit state (like whether a session was rewound) that other parts of the system can rely on.

- Area: Sessions
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Attestation check for automated control requests now covers two ID sets instead of one

Attestation checks for automated requests now match against two ID sets and compute a trust status

**Unclear.** The finding does not say what user-facing feature relies on this attestation check or what happens when a request fails it.

**What**

Claude Code has a function that checks whether an incoming response corresponds to a request it previously sent and vouched for (attested). Previously it only checked one list of request IDs; it now checks two: `automatedOutboundRequestIds` and `deviceOutboundRequestIds`. A new helper also computes a request's trust status, for example downgrading a status like server-authored or server-replayed to unspecified when the request didn't come from a cloud worker, and granting extra weight to a verified keyless device's vouching unless that vouching was specifically withheld.

**Why**

This broadens and refines how Claude Code verifies that automated or device-originated requests can be trusted, which matters for security features that depend on distinguishing genuine, previously-approved requests from others.

- Area: Attestation
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Artifact publish tool gains a 'reserved slug' bookkeeping path

Artifact publishing now tracks reserved slugs separately and handles never-published targets

**What**

The artifact publishing flow now keeps a separate list of "reserved" slugs (the short identifier used in an artifact's URL) alongside the existing list of "stranded" ones. A slug is added to the reserved list when a publish attempt reports one back, and both lists are cleared if a naming conflict occurs. A new outcome, meaning the target slug was never published before, is also now recognized so that overwrite checks can proceed as if there were no prior page at that slug.

**Why**

This makes publishing artifacts to a slug more reliable by keeping better track of slugs that are reserved but not yet published, and by correctly handling the case where a slug has no publishing history at all.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Cowork/artifact tool catalog gains docs-type gating flags

A docs/type-related artifact tool is now gated behind new typeCatalogOn, typeCreateOn, quickstartOn and docsTypeOn flags

**What**

A tool related to artifact types and quickstart documentation is no longer always offered. It's now included in the tool list only when a set of flags are enabled together: `typeCatalogOn`, `typeCreateOn`, and `quickstartOn` (or, in the Cowork-host variant, `docsTypeOn`).

**Why**

This lets Anthropic control the rollout of this tool independently per account, rather than shipping it to everyone at once.

- Area: Artifact Publish
- Names: `typeCatalogOn`, `typeCreateOn`, `quickstartOn`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New 'contract_rollout' artifact-publish error path, restricted to latestContract responses

Artifact publishing now recognizes a distinct 'contract rollout' failure, separate from the existing contract-mismatch error

**What**

When publishing an artifact fails with a 422 error, Claude Code now recognizes a new kind of failure called "contract rollout", identified by a message about the contract being newer than the preferred one. This only applies when the request asked for `contract:'latest'` and there wasn't already a pinned contract version. It's handled as a separate case from the existing "contract echo rejected" error.

**Why**

This lets Claude Code respond more precisely when an artifact publish fails because the contract version is rolling out, rather than lumping it in with the unrelated contract-mismatch error.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Extensive new prompt guidance for tool calls against a 'separate' (unsynced) machine copy

New built-in guidance tells Claude how to safely handle tool calls against a separate, unsynced copy of a project on a remote machine

**What**

Claude Code now includes detailed built-in instructions for situations where a remote or bridged machine's project folder is a separate copy of the repository that isn't kept in sync with the current session's checkout. The guidance covers:

- File tools only act on the current session's own checkout, not the remote copy

- Moving work between the two copies must go through `git fetch`, `rev-parse`, and reviewing the commit ID

- Warnings about risks from hooks, submodules, `.gitattributes`, `.lfsconfig`, and Git LFS (Git's large file storage extension) when working across separate copies

This is wired in as a new "separate" case alongside existing handling for other machine-relationship states.

**Why**

This reduces the risk of Claude Code confusing two unsynced copies of a project when operating across a remote or bridged machine, and steers it toward safe, reviewable ways to move changes between them.

- Area: Remote Machines
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New prompt.attachment resolution wired into query pipeline via th()

Model calls now run a new prompt-attachment resolution step, still skippable via settingsHooksOff

**What**

A new wrapper function around model-calling now checks whether a `prompt.attachment` hook is registered before generating a response. If one is present, it imports and runs an attachment-resolution step over the message list first. This step is skipped if the caller passed `settingsHooksOff`, or if hooks are otherwise turned off for that agent context.

**Why**

This adds a hook point that can modify or resolve attachments in a prompt before the model sees it, while still honoring the existing per-run `settingsHooksOff` opt-out that disables all hook execution for that agent or subagent run.

- Area: Plugin Hooks
- Names: `prompt.attachment`, `settingsHooksOff`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Plugin component events generalized beyond terminal via a new 'surface' field

Plugin UI component events can now report a surface other than 'terminal'

**What**

When Claude Code builds an event for a plugin's UI component, it used to always mark the event's `surface` as `"terminal"`. It now takes the surface value from whoever triggered the event instead, and the request format was updated to accept an optional `surface` field with its own validation.

**Why**

This allows plugin component events to be correctly labeled when they happen somewhere other than the terminal, which matters as Claude Code runs in more surfaces beyond the terminal.

- Area: Plugin UI
- Names: `surface`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### New error-kind enum for a policy/validation path (network/not-found/permission/policy/validation/in-use/unknown)

A new error-kind list (network, not-found, permission, policy, validation, in-use, unknown) was added for classifying operation failures

**Unclear.** It's unclear which specific operation or feature this error classification applies to.

**What**

Claude Code added a fixed list of error kinds — covering things like network problems, not-found, permission, policy, validation, in-use, and unknown — along with a matching set and validator to check values against it.

**Why**

This appears to support more precise classification of failures for some operation, though the finding doesn't identify which feature it belongs to.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Two feature-availability checks (FWt, oyn) gained an extra gate function ryn

Two feature-availability checks now require an additional gate function to pass

**Unclear.** What the added gate function actually checks, and which two features are affected, isn't stated in the finding.

**What**

Two nearly identical checks that decide whether a feature is available already required a few existing conditions to pass. They now additionally require a new gate function to pass before the feature is considered available.

**Why**

This adds an extra condition that must be satisfied for these two features to be considered available, though the finding doesn't say what that condition checks for.

- Area: Feature Gates
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### RemoteSessionManager control-request handling no longer threads raw attestation data to served-channel requests

Remote session control requests no longer pass raw attestation data through to served-channel requests

**What**

`RemoteSessionManager`'s `handleControlRequest` no longer accepts or forwards `attestationRaw` (raw attestation data) when handling served-channel requests, such as serving a tool call or dialog. The `attestationStatus` field is still passed through as before.

**Why**

This reduces the amount of raw attestation data that gets threaded through served-channel request handling, while still preserving the status information consumers need.

- Area: Remote Control
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### Text-input editing now feeds a keystroke recorder

Editing text in the prompt input can now feed a keystroke recorder, excluding pasted text

**Unclear.** The finding does not say what the recorded keystrokes are used for.

**What**

The core key handler for the prompt input box now sends each text-changing edit to a recorder, capturing the text and cursor state before and after the edit, whenever recording is active. Paste-like automatic insertions are excluded from this via a new skip flag.

**Why**

This lays groundwork for capturing keystroke-level editing history in the input box, while deliberately not recording pasted content.

- Area: Prompt Input
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### Side queries drop the 'Reporting outcomes' honesty-reminder system text

Background side queries no longer include the system-prompt reminder telling the model to report actual outcomes, not intentions

**What**

Side queries (background calls to the model, such as sub-agent or utility calls) used to have an extra block of system-prompt text appended, starting with "# Reporting outcomes," instructing the model to report what it actually did rather than what it intended to do. In the rewritten side-query builder, this block is no longer appended.

**Why**

This removes a reminder that previously nudged background/sub-agent responses toward describing actual results instead of stated intentions; side queries no longer carry that particular instruction.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### fork_conversation gains extra availability gates

Forking a conversation via remote control now checks two more availability conditions

**Unclear.** What conditions the two new checks (`Un()` and `At()`) actually test is not stated in the finding.

**What**

The `fork_conversation` remote-control request, which lets a remote client branch off a running session's conversation at a specific point, now performs two additional checks before proceeding. If either fails, the request returns "unsupported," the same result already returned when the existing sdkUrl-based check fails.

**Why**

This narrows the circumstances under which a conversation can be forked remotely, presumably to block the request in situations where forking isn't actually safe or possible, though what those two new checks specifically test for isn't stated.

- Area: Remote Control
- Names: `fork_conversation`
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### SSE transport now surfaces user-frame UUIDs via onUserFrameReceived

The streaming connection now surfaces user-message UUIDs via a new onUserFrameReceived callback

**What**

The client's SSE (server-sent events) streaming transport now calls a new `onUserFrameReceived(uuid, rawPayload)` callback whenever it receives a frame whose payload type is "user" and that carries a string UUID, before it passes the data on to the normal data handler.

**Why**

This lets other parts of Claude Code react specifically to incoming user-message frames and their identifiers as they stream in, rather than only handling them generically alongside every other frame type.

- Area: Elsewhere
- Names: `onUserFrameReceived`
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### Model family list touched at several offsets (opus/sonnet/mythos cycling)

Several entries in the internal model-family table were reassigned between opus, sonnet, and mythos

**Unclear.** Which specific models changed family, and what practical effect the reassignment has, is not stated.

**What**

Multiple rows in the internal table that tracks each model's capability `family` had their value changed among "opus", "sonnet", and "mythos" across a number of separate edits.

**Why**

This affects how these models are internally categorized for capability purposes, though the finding doesn't specify which models moved or what depends on their family assignment.

- Area: Models
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### New gate function jce for first-party base-URL eligibility

A new internal check gates a capability to first-party accounts using the default API endpoint

**Unclear.** What capability this eligibility check controls is not stated.

**What**

A new helper function checks whether the account's auth type is `firstParty` and several other conditions, including that `ANTHROPIC_BASE_URL` (which overrides the API endpoint, for example to route through a proxy) is not set, plus region and configuration checks, before allowing some capability to proceed.

**Why**

The finding doesn't say what capability this gates, but requiring first-party auth and the default API endpoint fits the existing pattern where certain features are disabled when requests are routed through a non-Anthropic endpoint.

- Area: Feature Gates
- Names: `ANTHROPIC_BASE_URL`
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### New 'editRelay' input prop threaded through the TUI text input stack

New editRelay prop added to the terminal text input components

**Unclear.** What `editRelay` does or enables isn't stated by the finding.

**What**

Claude Code's core text-input handling in the terminal interface now accepts and passes through a new `editRelay` prop, alongside the existing `selectionAnchor` and `selectionLinewise` props, at multiple call sites including the main input field.

**Why**

This is an internal plumbing change to the input-handling stack.

- Area: Prompt Input
- Names: `editRelay`
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### Second condition added to a feature-availability gate for two related capabilities

Two related capabilities now require an extra runtime condition on top of the existing enabled-list check

**Unclear.** What the added runtime condition actually checks, and which two capabilities these are, is not established by the evidence.

**What**

Two nearly identical feature-availability checks, each for a related tool/capability, now require an additional runtime condition (`ryn(H0e)` and `ryn(_Te)` respectively) to pass, on top of the existing check against the enabled-features list.

**Why**

This narrows when these two capabilities are considered available, adding a further runtime condition beyond simply being enabled.

- Area: Feature Gates
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### Unresolved: Yl() plugin-marketplace check with no visible caller in this excerpt

A new internal check flags plugins not listed in the marketplace or already tracked, cause unclear

**Unclear.** No caller of this function is visible, so it's unclear what user-facing behavior (if any) results from a plugin being flagged.

**What**

A new internal function checks whether an installed plugin appears in the marketplace's plugin list, or is already tracked by another internal tracking function. If the plugin is found in either place, the check reports nothing; otherwise it reports the plugin as unaccounted for.

**Why**

Nothing in this build shows what calls this check or what happens with a flagged plugin, so it's not yet clear what effect this has for someone using Claude Code's plugin/marketplace features.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### Git helper functions accept an overridable env for subprocess calls

Internal git helper functions can now accept a custom environment instead of always using the default

**What**

Internal helper functions that detect the current git branch and the default remote branch used to always run git with a fixed environment. They now accept an optional environment override that gets passed through to the underlying git call.

**Why**

This is an internal plumbing change that lets other parts of Claude Code invoke these git lookups with a customized environment when needed, rather than being locked into one fixed setup.

- Area: Git Internals
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Promo banner telemetry gains an entry_point dimension

Promo banner clicks and opens now record which entry point triggered them

**What**

The promo banner shown in Claude Code now tags its telemetry with an `entry_point` field, in addition to the existing `surface` field. This applies to both the click event and the open-result event recorded when a user interacts with the banner. The value is drawn from a shared constant so all promo banner events use the same entry point identifier.

**Why**

This gives Anthropic more detail on where a promo banner interaction originated, which helps them understand how the banner performs across different contexts.

- Area: Elsewhere
- Names: `entry_point`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### linguist-generated file check now supports explicit git-dir/work-tree (worktree awareness)

The check for git-generated files now works correctly across separate git worktrees

**What**

Claude Code checks whether a file is marked as "linguist-generated" in git (a marker used to decide whether to treat a file as auto-generated, for example skipping it in diffs). This check now accepts an explicit git directory and working tree path, passing them to the underlying `git check-attr` command when given, and caches results separately per git directory.

**Why**

This makes the generated-file check work correctly when Claude Code is operating on a git worktree other than the main one, since it no longer has to rely on the current working directory being the right one.

- Area: Git Internals
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### A tool-input schema case (C4) was removed from a validator

A tool-input validation case for task_id/agentId/bash_id fields was removed from a validator

**Unclear.** Whether this removal is connected to the previously-described coordinator Bash safety check isn't established by the finding.

**What**

A validator function that previously had a specific case for handling input shapes with `task_id`, `agentId`, `bash_id`, `block`, and `timeout` fields no longer has that case. That input type now falls through to the validator's default, which returns false.

**Why**

An earlier entry described a related but separate safety check for coordinator Bash calls involving these same fields (`agentId`, `bash_id`) that existed in code but was compiled off. This finding is about a different piece, a validation case being deleted from a validator, so this specific input shape is no longer recognized as valid by this function.

- Area: Tool Validation
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Tool-input JSON parse failures now log MCP status and richer Zod error detail

Tool-input JSON parse failure logs now show whether the tool was an MCP tool and give richer Zod error detail

**What**

When Claude Code fails to parse a tool's input as JSON, the internal telemetry event `tengu_tool_input_json_parse_fail` now records an `isMcp` field noting whether the tool came from an MCP server (a way of connecting external tools to Claude Code). Related error logging for schema-normalization failures (checked with a library called Zod) now includes the tool's display name, the list of specific Zod issue codes, and the length of the error message, instead of a single flattened error string.

**Why**

This gives more structured detail for diagnosing why a tool call's input failed to parse, without changing what happens for the user in the moment.

- Area: Tool Validation
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### System-prompt-block and request-content telemetry now fail closed

System-prompt-block and request-content telemetry no longer crash Claude Code if they fail

**What**

Two internal telemetry functions, one that reports on system-prompt blocking (`tengu_sysprompt_block`) and a new wrapper around request-content telemetry, are now wrapped so that an error inside them no longer throws and interrupts anything. If telemetry fails, Claude Code just logs 'system prompt block telemetry failed' or 'request content telemetry failed' and moves on.

**Why**

Telemetry recording is meant to be a side effect, not something that can break your session. This change makes sure a bug in telemetry reporting can't cause a visible failure.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### PreToolUse hook warnings identify the tool generically, not by literal name

PreToolUse hook warnings now name tools generically instead of by their literal name

**What**

`PreToolUse` hooks (which run before a tool call executes and can block it) can return `permissionDecision=defer`. Warnings shown when this happens in interactive mode, or when multiple tool calls are batched together, now identify the tool using a generic classifier rather than printing its raw name.

**Why**

This keeps the warning informative without exposing the literal tool name, consistent with similar changes to other tool-related log messages.

- Area: Hooks
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Message enqueue telemetry gains detailed timing breakdown

Message-enqueue telemetry now breaks down timing into parsing, dedup, flag, hook, and attachment stages

**What**

When a message is enqueued, Claude Code now records detailed timing information alongside the existing `cli_user_message_enqueued` event, including:

- `parse_to_enqueue_ms`: time from parsing to enqueueing

- `dedup_ms`: time spent deduplicating

- `flag_settle_ms`: time spent waiting for settings/flags to settle

- `receive_hook_ms`: time spent in the receive hook

- `attachments_ms`, `attachment_count`, and `inlined_images`, when the message has attachments

- `parked_ms`, when a park timestamp is supplied

**Why**

This gives much finer-grained visibility into where time goes between a message being received and being enqueued, which helps diagnose slowness in message handling.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Container/dirSync file-mirroring now runs a one-time staging sweep

Sandboxed-container file mirroring now runs a one-time staging sweep per session

**Unclear.** The finding doesn't say what the staging sweep actually does beyond being tied to the file-write path, so its concrete effect on file mirroring is unclear.

**What**

When Claude Code mirrors file changes from a sandboxed container back to the host machine, it now runs a one-time "staging sweep" step. This sweep happens once per session: it's only triggered if it hasn't already run in that session, and once it has run, later calls skip it.

**Why**

This ensures the staging sweep for container file mirroring happens exactly once per session rather than repeatedly, which likely avoids redundant work.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Git fast-forward path moved its temporary index into a managed scratch directory, with a new failure mode

Git fast-forward operations now use a managed scratch directory for their temp index, with a new failure if it can't be created

**What**

The internal routine that fast-forwards a git branch (used when advancing a worktree or checkout) now writes its temporary working index copy into a managed scratch directory instead of placing a temp file directly next to the git directory. If Claude Code can't create that scratch directory, the operation now fails with a new, distinct error result, `scratch_unavailable`.

**Why**

Using a managed scratch location instead of a hand-placed temp file is more robust, and the new explicit failure mode means a missing or inaccessible scratch directory is now reported clearly rather than failing in some other way.

- Area: Git Internals
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Skill overrides now stored via null-prototype objects; new message for name collisions with Settings storage

Skill overrides use a safer storage format, and settings now warn when a skill's name can't be stored

**What**

The local `skillOverrides` setting, which lets you hide or collapse a skill from settings without editing its file, is now built using a storage object with no inherited prototype instead of a plain JavaScript object. This avoids clashes with built-in object properties.

- The settings dialog used for managing skills now checks which skill names would collide with properties that Settings storage can't hold.

- When a skill's name can't be stored or toggled for this reason, a new message now surfaces explaining that Settings can't store an entry with that name.

**Why**

This prevents a skill whose name happens to match a reserved property name from silently failing to save its override, and tells you clearly when that happens instead of failing silently.

- Area: Settings
- Names: `skillOverrides`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New prompt.edit / prompt.attachment telemetry validation checks

New validation checks were added for prompt-edit and prompt-attachment telemetry replay data

**What**

Two new validator objects were added for telemetry events: one for `prompt.edit` and one for `prompt.attachment`. Each includes functions to restore, check, and measure recorded arguments, such as origin, key, text, cursor position, input text, and attachment text, verifying that replayed telemetry data is well-formed before comparing recorded values against live ones.

**Why**

This strengthens the internal telemetry system's ability to catch malformed or unexpected data when comparing recorded prompt-edit and prompt-attachment events against what actually happened.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Timing telemetry added around user-message ingestion in headless bridge

Headless bridge mode now records per-stage timing for incoming user messages and warns if a flag-settle step runs late

**What**

The part of the headless/bridge loop that processes incoming user messages now records timings for several stages: deduplication, waiting for flags to settle, running the receive hook, and inlining attachments. If a particular flag-settle wait (related to a component called 'hearth-relay') takes longer than its expected deadline, a warning-level event is now emitted.

**Why**

This timing data and warning make it possible to spot when user-message processing in headless mode is running slower than expected, and pinpoint which stage is responsible.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Wall-clock tracking of when user frames arrive over the wire (RemoteIO)

Claude Code now tracks the wall-clock time each user input frame arrives over the remote connection

**What**

The RemoteIO worker (used for remote/CCR connections) now keeps a bounded record of when each user input frame actually arrives, via a new transport callback `setOnUserFrameReceived`. This timing data can be pulled out later per session with `takeUserFrameReceivedWallMs`.

**Why**

This is internal timing instrumentation. It gives Claude Code a way to measure delay between when you type something and when it's received, which other telemetry (such as flag-settle timing) can use to diagnose lag.

- Area: Remote Control
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New helper disarms the startup wedge watchdog on background-agent kickoff

Starting a background agent now disarms a startup watchdog that could otherwise flag it as stuck

**What**

When a background agent is kicked off, Claude Code now also calls `disarmStartupWedgeWatchdog()` on the server, in addition to the existing startup call that already ran.

**Why**

This prevents the startup watchdog (a mechanism that detects a process stuck, or "wedged", during startup) from misfiring against background agents as they start up.

- Area: Background Tasks
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Directory-sync journal gets a new 'detached' halt state

Directory sync now treats a new 'detached' journal state the same as 'ended' when stopping

**What**

The directory-sync git worker's journal reader now stops in response to a new `halted === "detached"` state, treating it the same way it already treated `halted === "ended"`. It also records a new `detached` boolean on the stored halt-state object.

**Why**

This adds a distinct way for directory sync to recognize and halt cleanly when a sync session becomes detached, rather than only recognizing an explicit end.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### reload_skills IPC response now marks bundled/builtin skills

The reload_skills command now marks which skills are built in

**What**

When Claude Code responds to a `reload_skills` control request (an internal command used to refresh the list of available skills), each skill entry in the response can now include a `builtin: true` field, set when the skill's resolved name matches one of the skills bundled with Claude Code.

**Why**

This lets tools consuming the skill list distinguish bundled, built-in skills from ones you've added yourself.

- Area: Skills
- Names: `reload_skills`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Marketplace `settings`-source schema defers reserved-name rejection to load time in one code path

Marketplace 'settings' source schema can defer reserved-name checks to load time instead of at compile time

**What**

The schema builder for marketplace sources now takes a parameter that changes how reserved names are handled for the `settings` source type. When set, the `name` field skips the old compile-time rejection of reserved names and instead defers that check to load time, via a function called `revalidateReservedNameEntry`, which rejects a reserved name per entry as it loads. When not set, the old inline rejection at schema-compile time still applies.

**Why**

Deferring the reserved-name check to load time allows each marketplace entry to be validated individually as it's loaded, rather than rejecting the whole schema upfront.

- Area: Settings
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New helper `ir()` detects wildcard characters in git/URL marketplace source strings

New helper detects wildcard characters in git or URL marketplace source addresses

**Unclear.** The finding does not say what uses this detection or what happens when a wildcard is found.

**What**

A new function checks whether a marketplace source string, whether written as a URL or as an SCP-style git address (like `user@host:path`), contains a wildcard `*` character in its host or path. It normalizes SCP-style syntax and strips a trailing `.git` before checking.

**Why**

This gives Claude Code a way to detect wildcard patterns in marketplace source addresses, which other logic can use to handle or reject such patterns appropriately.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Ultrareview launches from the SDK request path now flagged confirmsBeforeLaunch

Ultrareview launches from Claude Code's SDK request path now skip certain confirmation-error and recovery-offer behavior

**Unclear.** The finding doesn't say what a user actually sees differently, such as whether a confirmation dialog is skipped when ultrareview is triggered via the SDK.

**What**

`/code-review ultra` (ultrareview) runs a deep, multi-agent code review in a cloud sandbox. When it's launched through Claude Code's internal SDK request handler, the launch call now always passes `confirmsBeforeLaunch: true`. Elsewhere in the code, this setting suppresses certain confirmation-required error paths and skips offering recovery telemetry.

**Why**

This changes how ultrareview launches started through the SDK path are handled internally, bypassing confirmation-error and recovery-offer behavior meant for other launch paths.

- Area: Slash Commands
- Names: `confirmsBeforeLaunch`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin binary-asset provisioning gating consolidated into a single check

Setting up a plugin's binary assets now runs through one combined check instead of three separate ones

**What**

When Claude Code provisions the binary files a plugin declares it needs, it now runs a single combined check covering schema validation, marketplace trust, and feature availability, rather than running those three checks separately.

**Why**

This is an internal simplification of the gating logic before a plugin's binary assets are set up; it doesn't change what gets checked, just how the checks are organized.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### FileReadTool bookkeeping map write no longer guarded by an empty-string check

A file-read bookkeeping record is now always saved, even in a case that previously skipped it

**Unclear.** The finding doesn't explain what the bookkeeping map (`fNt`) is used for, so the practical effect of always recording it isn't clear.

**What**

After Claude Code reads a file, it records some information about that read into an internal bookkeeping map. This recording now happens whenever a renamed condition, `Pb(r)`, is true, whereas before it only recorded the value if a derived string was non-empty.

**Why**

This is an internal bookkeeping change to when a file-read record gets saved.

- Area: File Tools
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin hook modules now skip reload when unchanged

Claude Code now skips reloading plugin hook modules that haven't changed, instead of rebuilding them every time

**What**

The loader that (re)builds plugin function-hooks now checks whether the incoming set of hook modules is identical to what's already loaded. If so, it skips the rebuild and logs "hooks modules unchanged, kept as loaded." When only some modules change, it logs which ones are kept versus reloaded ("hooks modules kept as loaded, unchanged"), and when everything changes it logs a full reload ("hooks modules reloaded in full").

**Why**

This avoids unnecessary teardown and rebuilding of plugin hooks when nothing about them has actually changed, and the added logging makes it easier to tell what happened during a reload.

- Area: Plugin Hooks
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### fork_conversation precondition check reworked

fork_conversation's internal precondition check was simplified from four conditions to three

**What**

The `fork_conversation` feature, which lets a remote client branch off a running Claude Code session, has an internal check that decides whether the request can proceed. That check used to test four separate conditions; it now tests three, checking a freshly computed session-identifier value directly for being unset rather than referring to a separately named variable holding the same thing.

**Why**

This is a change to the internal logic behind `fork_conversation`'s validation; it does not change what the feature does for someone using remote control, only how the check is written.

- Area: Remote Control
- Names: `fork_conversation`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Inline plugin zip re-extraction skipped when the zip is unchanged

Inline plugin zip files are no longer re-extracted if their contents haven't changed

**What**

When Claude Code loads a plugin that was provided as an inline zip file, it now compares the new zip against what's already been extracted. If the contents are unchanged, it reuses the existing extraction and logs "Inline plugin zip unchanged; loading..." instead of extracting the zip again.

**Why**

This avoids unnecessary re-extraction work when reloading a plugin whose zip file hasn't actually changed.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Prompt-suggestion generation for SDK turns drops the cached 'turnBriefNext' shortcut

SDK prompt suggestions no longer reuse a cached shortcut and now always generate fresh

**What**

When the SDK generates a suggested next prompt for a turn, it used to first check a cached value (`promptSuggestion.turnBriefNext`) tied to the last assistant message, and only generate a fresh suggestion if nothing was cached. That caching shortcut has been removed, so prompt suggestions are now always generated in full each time.

**Why**

This means SDK-generated prompt suggestions are computed fresh rather than potentially reused from a stale cached value.

- Area: SDK
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Queued-command lifecycle schema doc clarifies remote-control cancel semantics

Internal docs clarify that queued-command 'cancelled' status can now come from a remote client withdrawing a prompt

**What**

Claude Code tracks the lifecycle of queued commands (prompts waiting to run) in its telemetry. The internal documentation for this tracking has been expanded to explain that a "cancelled" state can now also happen when Remote Control is enabled and one remote client withdraws a prompt that a different remote client had queued. The documentation notes that such cancellations are purely informational and shouldn't be treated as something to resend.

**Why**

This is a documentation clarification for how queued-command cancellations should be interpreted when multiple remote clients are involved, so a cancellation in that situation isn't mistaken for an error needing a retry.

- Area: Prompt Queue
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin file watcher gains scope/entry tracking and retarget on reload

Plugin file watcher now tracks scope and entry per plugin and can retarget after reloads

**What**

The file watcher that monitors plugin directories for changes now keeps track of a scope and an entry for each plugin alongside its manifest. Before reloading a plugin, it checks with a gate to confirm the reload should proceed, and it can retarget what it's watching both after the list of plugins updates and after a reload finishes.

**Why**

This keeps the watcher pointed at the right files as plugins are added, changed, or reloaded, reducing the chance it watches stale or incorrect locations.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Skill directory discovery gains a pre-scan hook

Skill discovery now checks for nested project skill directories before loading

**Unclear.** The exact effect of detecting this nested case (for example, skipping or merging) is not stated in the finding.

**What**

Before Claude Code logs which skill directories it's loading from, it now runs an extra check against the project's skill directories and its "skills" configuration setting. This appears to detect whether a project's skills directory is actually located inside another project's already-loaded `.claude` configuration directory.

**Why**

This likely helps avoid loading the same skills twice or getting confused when one project's skills folder is nested inside another project's configuration directory.

- Area: Skills
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Deploy/publish telemetry adds retry and slug-reservation context

Publishing errors now record retry timing and reserved-slug details

**What**

When publishing an artifact fails, the error report sent for telemetry now includes a `retryAfter` value (taken from the server's retry-after response header), whether a `reservedSlug` (a name held for the artifact) exists, and a `created` field. When a rate-limit error occurs but a slug was already reserved, the extra explanatory text normally appended to the error message is now left out.

**Why**

This gives more precise information about why a publish attempt failed and whether it can be retried, and avoids cluttering the error message with redundant text when a slug reservation already succeeded.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Git sync snapshot push gains staging-trash path resolution

Cloud git-sync push logic adds a staging-trash path and a new push option

**What

- Area: Git Internals
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Hooks module reload now tracks an 'isSetRecord' dirty flag tied to plugin-dir watch

Hook reloading now tracks a dirty flag tied to plugin-directory watching

**Unclear.** The user-facing effect of this state tracking is not stated in the finding.

**What**

When the internal hooks worker respawns or reloads, it now clears an internal flag called `isSetRecord` before starting the reload, and only marks it set again once the reload succeeds. A single-module reload path also checks whether the module changed via the new plugin-directory watcher or an external scan, and if so, clears `isSetRecord` instead of treating the reload as authoritative.

**Why**

This is internal bookkeeping that keeps the hooks system from treating a reload as complete and trustworthy when it was actually triggered by an external file change still in progress.

- Area: Plugin Hooks
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Session-inbox tool gets project-thread-specific envelope guidance

Session-inbox tool description gains extra guidance for project-thread messages

**What**

When a session is of type 'project', the description for the session-inbox tool (which Claude reads to understand how to use the tool) now adds a paragraph of guidance: only the element marked `<message from="human" trigger="true">` represents the user's actual words, other quoted elements are context rather than requests, and attachments are downloaded and referenced as `@path` inside the payload's attachments key.

**Why**

This should help Claude correctly distinguish an actual user instruction from surrounding quoted context in project-thread messages, and know how to locate any attached files.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Artifact tool's 'read' action documents supported URL formats and tool preference

Artifact tool's 'read' action now documents which claude.ai link formats it supports

**What**

The description of the publish/read/list artifact tool's 'read' action now spells out that it accepts any claude.ai artifact link, in either the `claude.ai/artifact/{id}` or `claude.ai/code/artifact/{uuid}` format, and explicitly tells Claude to read these links using this tool action rather than `WebFetch` or `curl`.

**Why**

This steers Claude toward using the correct, more reliable tool for reading artifact links instead of general-purpose web fetching, which likely wouldn't handle them properly.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Team-memory multi-store sync refines empty/removed-receipt bookkeeping

Team-memory sync now tracks empty and removed memory-store receipts with more precise reasons

**Unclear.** The finding does not say what user-visible behavior, if any, depends on this distinction.

**What**

The internal logic that syncs team memory across multiple storage locations now separates out more specific bookkeeping cases: it distinguishes an 'absent' receipt from other reasons a receipt can't be used as a basis for comparison, and it separately tracks whether an on-disk receipt was empty (`empty_store`) versus unreadable for some other reason, rather than lumping these cases into one flag.

**Why**

This is internal bookkeeping refinement for team memory sync; more precise state tracking reduces the chance of sync logic misinterpreting why a memory receipt is missing or empty.

- Area: Team Memory
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Transcript builder gains a 'withoutAttachmentHooks' bypass option

Transcript building gained a withoutAttachmentHooks option to skip attachment hooks

**Unclear.** What situation triggers use of withoutAttachmentHooks, and what practical effect it has, is not stated.

**What**

When Claude Code rebuilds the transcript sent to the API, a new option called `withoutAttachmentHooks` lets the caller skip the normal attachment hooks and instead use a plain path when re-serializing a human turn's attachments.

**Why**

The finding does not say why a caller would want to bypass attachment hooks, only that the option now exists.

- Area: Transcript
- Names: `withoutAttachmentHooks`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Model list insertion for local/self-hosted entries now requires firstParty context

Local/self-hosted model entries now only get added when the context is explicitly first-party

**Unclear.** The finding doesn't explain what problem the previous, looser check caused in practice.

**What**

The internal check that decides whether to insert a synthesized entry for a local or self-hosted model into the model list now requires an additional condition: the value must be `null` and the context must equal `"firstParty"`, on top of the two checks it already required.

**Why**

This tightens when Claude Code will add a synthesized local/self-hosted model entry to the list, avoiding cases where it might otherwise show up in the wrong context.

- Area: Models
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Project context loading now also reports plugin instruction file stats

Project context loading now always reports plugin instruction file counts and total size

**What**

When Claude Code assembles project context, the result now always includes a `pluginInstructionFiles` field, giving a file count and total content length for plugin instruction files, alongside the existing `claudeMd`, `instructionFiles`, and `memoryFiles` fields.

**Why**

This gives Claude Code, and anyone inspecting context loading, visibility into how much instruction content plugins are contributing, on top of what was already tracked for CLAUDE.md and other instruction and memory files.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Attribution billing header gains a cc_turn_origin field

First-party API requests now carry a cc_turn_origin field in their billing header

**What**

The internal billing and attribution header attached to first-party API requests now includes a `cc_turn_origin=` field, validated against a lowercase-letters-and-underscores pattern, alongside the existing `cc_version`, `cc_entrypoint`, `cc_workload`, `cc_is_subagent`, `cc_prev_req`, and `cc_prompt_id` fields. It's only added when the request is from a first-party account and a valid origin string is available.

**Why**

This lets Anthropic attribute API requests to what triggered the turn, alongside the other attribution fields already sent, for a first-party account.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New wall-clock latency telemetry fields for turn timing over --sdk-url

New wall-clock latency telemetry fields break down turn timing when using --sdk-url

**What**

When a session reads its input from an SSE (server-sent events) stream via `--sdk-url`, Claude Code now records several new optional telemetry fields: `first_stream_post_queue_wait_ms`, `first_stream_post_queued_behind`, `frame_received_wall_ms`, `frame_enqueued_wall_ms`, `turn_started_wall_ms`, `first_text_post_ms`, and `first_text_post_wall_ms`. Together these break a turn's latency down into transit time, queueing time, and processing time.

**Why**

This gives much finer-grained visibility into where time is spent during a turn when driving Claude Code over `--sdk-url`, useful for diagnosing latency issues in that setup.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### attestationRaw field dropped from remote tool call telemetry

Remote tool call telemetry drops the attestationRaw field and adds a detached flag for detached runs

**What**

Telemetry sent for remote tool calls no longer includes the `attestationRaw` field; it still includes `attestationStatus` and other fields. Separately, tool execution telemetry now includes a `detached: true` flag when a tool run's abort signal indicates the run was detached.

**Why**

Dropping the raw attestation data while keeping its status suggests the raw form wasn't needed downstream, and the new `detached` flag lets telemetry distinguish detached tool runs from normal ones.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### WebFetch tool description reworks its claude.ai-artifact exception into a general mode parameter

WebFetch's internal prompt-building switched from a simple on/off flag to a named mode string

**Unclear.** What the mode values other than the default "none" actually change in the description is not stated.

**What**

The internal code that builds the description text for the `WebFetch` tool used to take a simple true/false flag (`leanPrompt`) that controlled a single special-case explanation about claude.ai artifacts. It now instead takes a mode, a text value that defaults to `"none"`, passed through to the helper functions that assemble the description.

**Why**

A mode that can hold more than two values suggests more variations of the `WebFetch` description are possible than the old on/off flag allowed, though what those other modes do isn't specified. The visible `WebFetch` description text itself is unchanged in this release.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Session-process-exit error result can now flag a terminal setup failure

Crashed-session error reports can now flag that a setup failure was unrecoverable

**What**

When the process running a session crashes during its setup phase, Claude Code builds a synthetic error result describing what happened. That error-building function now accepts a `setupTerminal` option, and when it's set, the resulting `runner_exit` detail for a setup-phase failure includes `terminal: true`.

**Why**

This lets whatever consumes these error reports distinguish a setup failure that can't be recovered from other, presumably retryable, setup failures.

- Area: Session Lifecycle
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Hooks-module-not-loaded diagnostics reformatted to identify the module, not just the plugin name

Log messages about skipped plugin hooks now name the specific hooks module, not just the plugin

**What**

When a plugin's hooks module (the file defining its custom hooks) doesn't get loaded, Claude Code logs why. Previously the message used a fixed phrasing naming just the plugin and its source; now it uses a generated identifier that names the specific module instead. This applies across all three cases: the rollout flag being off, a duplicate plugin name, and `disableAllHooks` being set.

**Why**

More specific log output makes it easier to tell exactly which hooks module was skipped and why, especially for plugins that define more than one.

- Area: Plugin Hooks
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Team/agent-commit bookkeeping tracks how many commits were already installed

Multi-agent commit tracking now knows exactly how many agent commits have already been installed

**What**

When multiple agents' work gets merged together, Claude Code now tracks an explicit count, `agentCommitsBookkeeping`, of how many agent commits have already been installed elsewhere. Previously, the merge result's `parkedAt` field was only ever cleared (set to null) in the case where the commit landed in the worktree; now it's also cleared once this new count reaches the total number of agent commits, meaning all of them have been installed somewhere.

**Why**

This avoids incorrectly leaving a merge result marked as "parked" (waiting) once every agent commit has actually already been installed, keeping the bookkeeping accurate for multi-agent work.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Session-cost-tracker snapshot gains a restoredCostUSD field, separate from hasUnknownModelCost

Session cost tracking now stores a restored cost separately from the unknown-model-cost flag

**What**

The internal mechanism that saves and restores a session's cost tracking now keeps a distinct `restoredCostUSD` value. Previously this shared a single internal field with `hasUnknownModelCost`, meaning the two were conflated. Calling `reset()` on the tracker now also explicitly zeroes out `restoredCostUSD`.

**Why**

Separating these two values fixes a case where they could interfere with each other, making cost restoration and the unknown-model-cost flag behave more predictably, including after a reset.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Multi-store-sync basis loader now recognizes a non-empty 'held' set as valid state

A sync data store with a non-empty 'held' set is no longer wrongly treated as empty

**What**

When Claude Code loads the saved state used to keep multiple stores in sync, it used to treat a store with zero entries as automatically empty. Now, if that store has a non-empty `held` set, it's no longer considered empty just because its entry count is zero.

**Why**

This avoids an incorrect "empty store" rejection for a store that actually holds valid state in its `held` set, preventing that state from being wrongly discarded during sync.

- Area: Team Memory
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New SDK query() usage/cost fields get detailed docs

SDK docs now spell out that query() usage and cost totals accumulate across turns and reset on /clear

**What**

The descriptions for the SDK's `query()` result fields covering model usage and total cost have been expanded. They now explain that per-model token totals (`modelUsage`) and the cumulative estimated cost (`totalCostUsd`-like field) both accumulate across turns within a streaming session, and reset when `/clear` is used to start a new conversation.

**Why**

This clarifies for SDK users exactly what window of activity these numbers cover, so a running cost or usage total isn't mistaken for a single-turn figure or misunderstood after a `/clear`.

- Area: SDK
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Status-digest line told not to answer the user's question

Background progress status lines are now told not to answer the user's question early

**What**

The internal prompt used to generate the short one-line status shown while background work is in progress now explicitly forbids it from stating a verdict or an answer to the user's question. It's required to only describe progress, leaving the actual answer for the agent's final reply.

**Why**

This stops the progress line from prematurely announcing a conclusion before the work is actually finished, which could otherwise be misleading if the real answer ends up different once the task completes.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Usage-limits null semantics tightened for failed fetches

Usage-limits data is now documented as null whenever the usage fetch is failing, not just when it predates rate limits

**What**

The documentation for the usage-limits data (`limits[]`) now clarifies that this field is null not only when the server's response predates the usage meters, but also any time the usage fetch is currently failing. Even though the CLI may separately build its own fallback row from rate-limit response headers, that fallback is never surfaced through this field — it stays null during a failure.

**Why**

This clarifies that a null value doesn't distinguish between "no data yet" and "the fetch is currently failing," and that a fallback estimate elsewhere in the CLI won't appear here.

- Area: Rate Limits
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### claude.ai artifact links: explicit tool-routing guidance added

Claude is now told to read claude.ai artifact links with the Artifact tool or WebFetch, never curl or a headless browser

**What**

Claude Code's instructions now explain that claude.ai artifact links — of the form `claude.ai/artifact/{id}` or `claude.ai/code/artifact/{uuid}`, including on `preview.claude.ai` — are published artifacts and should be read using the `Artifact` tool's "read" action, or via `WebFetch` using the user's claude.ai login. The instructions explicitly warn against fetching such links with `curl` or a headless browser, which return either the app's empty page shell or a Cloudflare 403 error.

**Why**

This steers Claude toward methods that can actually retrieve artifact content and away from methods that reliably fail on these links, avoiding wasted attempts and confusing error pages.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Directory-sync install tracking reworked to fold/dedupe re-sent installs

Directory-sync install tracking for claude --cloud now dedupes re-sent installs that haven't materially changed

**What**

The bookkeeping that tracks which file installs have been sent during `claude --cloud` directory sync was reworked. Installs are now compared against a tracked "folded install" record, and only re-included if they materially differ — specifically if the turn, a truncated flag, or the set of not-installed files changed.

**Why**

This avoids re-sending an unchanged install list after an internal generation bump, cutting down on redundant sync traffic for `claude --cloud` sessions.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New "folder_relation" telemetry field for sync topology

Sync telemetry can now report a folder as a separate, unsynced copy rather than a project sync

**What**

The data Claude Code sends about how a device or session relates to your project folder now includes a new optional field, `folder_relation`, which can carry the value `separate_copy`. This sits alongside the existing `project_sync` value used for the same field.

**Why**

This lets Claude Code's internal telemetry distinguish a folder that is a standalone, unsynced copy of a project from one that is actively kept in sync, which is useful groundwork for features that deal with multiple copies of the same project.

- Area: Telemetry
- Names: `folder_relation`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Artifact 'auto_open' description: connectors never open on first write

Artifact auto_open guidance now tells Claude to skip it for connector-backed content like Claude Docs

**What**

The instructions Claude Code gives to Claude about the artifact `auto_open` setting now explicitly say to leave it out when the artifact's content is written through a connector, such as a Claude Docs document, rather than through a normal publish or store step.

**Why**

Connector-backed content doesn't go through the publish/store write that would normally trigger the artifact to open, so setting `auto_open` in that case wouldn't do anything. The updated guidance stops Claude from adding a setting that has no effect for these artifact types.

- Area: Artifact Publish
- Names: `auto_open`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New per-turn latency telemetry: cli_turn_started

New cli_turn_started telemetry tracks how long a turn waits before starting

**What**

When frame timing information is available, Claude Code now emits a `cli_turn_started` telemetry event each time a turn (one round of the conversation) is dispatched. It records the turn's unique ID, the batch size, and `enqueue_to_start_ms`, the time elapsed between when the turn was queued and when it actually started.

**Why**

This gives visibility into how much delay builds up between queuing a turn and starting it, which is useful for diagnosing latency in the CLI.

- Area: Telemetry
- Names: `cli_turn_started`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Cloud session commit set-aside notice avoids repeating already-reported commits

Cloud session's "commits set aside" notice no longer repeats commits already reported

**What**

When a cloud session's branch changes and Claude's commits get set aside, Claude Code shows a message explaining this. That message now subtracts a running count (`agentCommitsBookkeeping`) of commits already reported from the total, and only shows the message at all if the branch actually switched or if there are new commits beyond what was already accounted for.

**Why**

This stops the same set-aside commits from being reported to the user more than once.

- Area: Cloud Sessions
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin directory loading cleans up downloaded preview files

Loading a plugin preview now cleans up its temporary download folder afterward

**What**

When Claude Code loads a plugin from a marketplace preview, it now deletes the temporary folder the preview was downloaded into once loading finishes, whether loading succeeded or failed. If that cleanup itself fails, a warning is logged.

**Why**

This prevents leftover temporary preview files from accumulating on disk after previewing plugins.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### tengu_remote_tool_forward telemetry gets a caller_gate field

Remote tool forwarding telemetry now records whether the in-session permission gate ran and allowed the call

**What**

The `tengu_remote_tool_forward` telemetry event, which tracks tool calls forwarded to another machine, now includes a `caller_gate` field reflecting whether the new in-session permission check ran and whether it allowed the call, alongside the event's existing outcome and refusal-reason fields.

**Why**

This gives more visibility into where in the forwarding process a tool call was allowed or blocked, which is useful for diagnosing why a remote tool call did or didn't go through.

- Area: Telemetry
- Names: `tengu_remote_tool_forward`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Artifact creation calls now pass an idempotency key

Creating an artifact now sends an idempotency key to prevent accidental duplicates

**What**

When Claude Code creates a new artifact (a generated file or piece of content, like a document or piece of code shown to the user), the request now includes an idempotency key, a unique value that lets the server recognize if the same creation request was sent more than once.

**Why**

This prevents duplicate artifacts from being created if a creation request is retried, for example after a network hiccup.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### tengu_thinking_drop telemetry gains a context_compacted dimension

The tengu_thinking_drop telemetry event now also records whether context was compacted

**What**

The `tengu_thinking_drop` telemetry event, which logs when "thinking" blocks (the model's intermediate reasoning content) are stripped from a request, now also records a `context_compacted` value. This tracks whether the drop happened alongside a context compaction (the process that trims earlier conversation history to save space).

**Why**

This gives more detail on why thinking blocks get dropped, making it easier to tell whether compaction was a factor in a given case.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### SSRF/private-IP check for local tooling simplified and a normalization step added

The check for whether an address is local was simplified and now strips IPv6 zone identifiers first

**What**

Claude Code has an internal check for whether a network address counts as "local," used to control whether local tools can bind to it. This check now strips IPv6 zone identifiers (extra suffixes like `%eth0` sometimes attached to IPv6 addresses) before evaluating an address. It also consolidates loopback and unspecified-address handling into a single computed result, and hands off unmatched cases to a new helper function instead of separately hardcoding checks for AWS and GCP metadata service IP addresses.

**Why**

This is a defensive check related to preventing server-side request forgery (SSRF), where a request is tricked into reaching an unintended internal address; normalizing IPv6 zone identifiers first helps make sure such addresses aren't misclassified and slip past the local-address check.

- Area: Sandbox
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Meter-row schema tightened: severity and is_active are no longer optional/nullable

Usage meter rows now always require severity and is_active, no longer optional

**What**

The schema for status-meter rows sent by the server (used for things like usage or limit meters) has been tightened: the `severity` and `is_active` fields, previously optional and allowed to be null, are now required on every row. The schema's description was updated to clarify that every row comes from the server, so the client never decides these values itself.

**Why**

This makes clear that grading of meter status is entirely the server's responsibility; the client just displays what it's given, rather than filling in missing severity or active-state values on its own.

- Area: Rate Limits
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin/marketplace error store gains a targeted removeErrorsOf method

Plugin error tracking can now clear errors for just one plugin instead of wiping the whole list

**What**

Claude Code keeps a record of errors that occur with plugins and marketplaces (the catalogs plugins are installed from). A new `removeErrorsOf` method lets that record be cleared for a specific plugin, matched by its id or by its name plus marketplace, instead of requiring the entire error list to be reset at once.

**Why**

This allows stale or resolved errors for one plugin to be cleared without discarding error information about every other plugin, which is useful when managing multiple plugins at once.

- Area: Plugin Install
- Names: `removeErrorsOf`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### UI blit now distinguishes Raster vs Image sources

The UI blit drawing operation now also tracks changes to whether an image source is present

**What**

The `ui.blit` action (which paints, or "blits," pixel data onto the interface) now treats a change in whether its `source` field is present or absent as a meaningful change worth reacting to, not just changes to the source's contents. Its description was also updated to say it covers "the Raster or Image being blitted," rather than referring only to a Raster.

**Why**

This means `ui.blit` now recognizes Image sources alongside Raster sources, and correctly detects when a source is added or removed rather than only when its content changes.

- Area: Plugin UI
- Names: `ui.blit`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Attestation status parsing simplified and extended to hook_callback

Device attestation status parsing now also covers hook_callback and drops an old raw-value side channel

**What**

Claude Code's derivation of device attestation status (a signal used for verifying a device's identity) now also applies to `hook_callback` subtypes, in addition to the subtypes it already covered. At the same time, the code drops a prefix-stripping and raw-value side channel (`attestationRaw`), replacing it with a simpler direct uppercase pass to the classifier.

**Why**

Extending attestation-status handling to `hook_callback` means that code path now gets the same status classification as other subtypes, while the simplified parsing removes an extra step that previously handled raw values separately.

- Area: Attestation
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Double-escaped-unicode repair telemetry adds control-escape tracking

Unicode double-escape repair now also tracks a controlEscapeSkips counter in its telemetry

**Unclear.** The finding does not say what specifically counts as a control-escape skip or how it affects repair behavior.

**What**

Claude Code has an internal pass that repairs text where unicode characters got escaped twice. It already tracked how many strings it repaired and how many Windows file paths it skipped fixing. It now also tracks a third count, `controlEscapeSkips`, and reports it alongside the other two in the same telemetry event.

**Why**

This gives more visibility into how often the repair pass avoids touching control-character escapes, which helps diagnose text-corruption issues without changing any user-visible behavior.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Worker/environment start now reports machine_id

Worker/environment start requests now include a machine_id field

**What**

When Claude Code starts a worker or environment, the metadata it sends now includes a `machine_id` value when one is available, in addition to the existing `worker_type` field.

**Why**

This gives Anthropic more detail about which machine started a given worker or environment, useful for diagnostics and tracking.

- Area: Telemetry
- Names: `machine_id`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Sandbox/bash env gains a TMPDIR backstop

Sandboxed shell commands can now get a TMPDIR fallback if it isn't already set

**What**

When Claude Code builds the shell setup for a sandboxed or spawned command, if a new `tmpDirBackstop` option is set, it now adds a step exporting the `TMPDIR` environment variable, but only if `TMPDIR` isn't already set.

**Why**

This guards against commands failing or behaving unexpectedly in sandboxed environments where `TMPDIR` might otherwise be unset.

- Area: Sandbox
- Names: `TMPDIR`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin manifest discovery gains folder scope and entry module path

Plugin discovery from folders now records a folder scope and resolves an entry module path

**What**

When Claude Code discovers plugins from folders, it now records a `scope: "folder"` marker on the discovered manifests, and if a manifest declares a `modulePath`, it resolves and records an `entry` module path for it. Previously only the manifest list itself was recorded.

**Why**

This gives Claude Code more structured information about where a plugin's manifest came from and where its entry module lives, which supports handling folder-based plugins with module paths.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### post_turn_summary telemetry payload shrunk

post_turn_summary telemetry event now records 4 fields instead of 9

**What**

The `post_turn_summary` telemetry event, which records information about a turn's summary, previously recorded nine fields including `description`, `points`, `summary`, `next_why`, and `reply_options`. It now records only four: `summarizes_uuid`, `status_category`, `status_detail`, and `needs_action`.

**Why**

This reduces the amount of data captured in this telemetry event, dropping several detail fields in favor of a smaller, more focused set.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### ui.render hook matcher gets startup advisory logging

Claude Code warns at startup if a hooks module registers a ui.render matcher with advice available

**What**

A new check runs when a hooks module (a script that registers hook handlers) subscribes to the `ui.render` event with a matcher (a filter deciding which calls the hook applies to). If there's advice available about that matcher, Claude Code now logs a warning at startup showing the matcher's contents.

**Why**

This surfaces potential problems with a hook's `ui.render` matcher up front, rather than leaving the author to discover an issue only when the hook misbehaves.

- Area: Plugin Hooks
- Names: `ui.render`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Permission decision helper marks 'promptless' outcomes with a reason string instead of boolean

Permission-prompt skip decisions now report a specific reason instead of yes/no

**What**

The internal function that decides whether a tool call can skip the permission prompt now returns one of three specific reasons instead of a plain true/false: `"none"`, `"artifact-tool"`, or `"webfetch"`.

**Why**

This lets the code that consumes this decision know exactly why a permission prompt was or wasn't needed, rather than just whether it was, which supports more precise handling of each case.

- Area: Permissions
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### claude.ai discovery tool schema no longer always deferred

claude.ai content-search tool no longer always defers loading its schema

**What**

The tool that searches claude.ai content (used for discovery by keyword) previously always deferred loading its schema. It now only defers when the schema wasn't already loaded up front, via a conditional check rather than a fixed setting.

**Why**

This avoids unnecessarily deferring the tool's schema when it's already available, which can make the tool ready sooner in cases where its schema was preloaded.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New device-registration-revoked error for cowork/remote device

New error reports when a device's remote-session registration has been revoked

**What**

A new error is now raised when the local machine's device registration has been removed from the account, as used by the device registry for cowork/remote-device sessions. This is logged with the telemetry event `cowork_remote_device_registration_revoked`.

**Why**

This gives a clearer, specific error when a device's remote-session access has been revoked, instead of it failing in a less identifiable way.

- Area: Device Binding
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Repository trust now recorded in remote session directorySync payload

Remote session join payload now includes a repositoryTrust field alongside directorySync

**Unclear.** What repositoryTrust is used for once included in the payload is not stated.

**What**

The payload sent when joining a bridge/remote session now includes a `repositoryTrust` field next to the existing `directorySync` field, populated by a new function call.

**Why**

This passes repository trust information along when establishing a remote session, though the finding doesn't specify how that information is used on the receiving end.

- Area: Remote Control
- Names: `repositoryTrust`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Restored session cost is now tracked separately

Restored session cost is now tracked as its own separate figure

**What**

The cost-tracking system gained a `restoredCostUSD()` accessor backed by a new internal counter, tracking cost carried over when a session is restored separately from cost accrued during the current run. The cost-state schema's `totalCostUSD` now also has a minimum floor value instead of being unconstrained.

**Why**

This lets restored cost be reported and reasoned about separately from newly accrued cost, and the added floor guards against `totalCostUSD` ending up as an invalid or nonsensical value.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Reserved skill/tool name category added: reserved-name

A new 'reserved-name' category joins policy and flag as reasons a permission mode won't cycle

**Unclear.** The finding doesn't say what triggers the 'reserved-name' origin or which skill/tool names are reserved.

**What**

Claude Code has an internal helper that cycles through permission modes (the settings that control how much Claude can do without asking first). It already knew to leave the mode unchanged when a restriction came from a "policy" or a "flag". It now recognizes a third origin, "reserved-name", and treats it the same way: the mode stays put instead of cycling.

**Why**

This prevents the permission mode from changing when the restriction is tied to a reserved skill or tool name, keeping behavior consistent with how policy- and flag-based restrictions are already handled.

- Area: Permissions
- Names: `reserved-name`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New marketplace field presentsAs surfaced from plugin metadata

Plugin marketplace metadata now includes a presentsAs field

**Unclear.** What presentsAs controls or displays is not stated.

**What**

When Claude Code reads metadata for a plugin or marketplace entry, it now also picks up a `presents_as` value from the source data and exposes it internally as `presentsAs`, alongside the existing `marketplaceName` and `installationPreference` fields.

**Why**

The finding doesn't say what `presentsAs` is used for, but capturing it suggests plugin listings may soon be able to present themselves differently than their underlying name or source.

- Area: Plugin Install
- Names: `presentsAs`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Compaction 'phase' enum gains a 'kept' state

Compaction status can now be recorded as 'kept', a new fourth state

**Unclear.** What causes a conversation to be marked 'kept', and what that means for the user, is not stated.

**What**

Compaction is the process where Claude Code condenses a long conversation to save space. The internal tracking for a conversation's compaction status previously allowed three values: "clearing", "cleared", and "untouched". It now allows a fourth: "kept".

**Why**

The finding doesn't say what triggers the "kept" state, but its addition implies there's now a way for content to be explicitly preserved during compaction rather than only being cleared or left untouched.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New telemetry event names added

Six new internal telemetry event names appeared, hinting at features in progress

**Unclear.** None of these event names are tied to any described user-facing feature yet.

**What**

Several new event identifiers were added to Claude Code's internal telemetry event list:

- `mermaid_render`

- `query_tool_detach`

- `bridge_cancel_queued_message`

- `device_mcp_host_consent`

- `ccr_dir_sync_attach`

- `usage_limit_grace_wrapup_subagent`

**Why**

These are just event names added to internal tracking, so no user-facing behavior is confirmed yet, but they hint at work in progress around rendering diagrams, detaching a query tool, canceling queued bridge messages, MCP host consent on devices, directory-sync attachment, and a grace period around usage limits involving subagents.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Git dir-sync checkout gains new terminal states

Directory sync's git checkout logic gains several new named outcome states

**What**

The directory-sync feature, which checks out git state to keep a synced copy up to date, now recognizes several new outcome states for a checkout operation:

- `checkout_mid_operation`

- `checkout_unmerged`

- `checkout_unborn`

- `checkout_unreadable`

- `snapshot_refused`

- `no_ref`

- `acknowledge`

- `other`

A new sync kind, `checkout_empty`, was also added.

**Why**

More granular outcome tracking lets Claude Code distinguish between different reasons a directory-sync checkout didn't complete cleanly, such as a repository mid-operation, unmerged paths, or an unborn branch, rather than lumping them together.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### PromptHint recognized as a pane region

A new 'PromptHint' pane region is now recognized alongside AbovePrompt and Pane

**Unclear.** What PromptHint contains and how recognizing it changes the display is not stated.

**What**

The layout logic that decides where prompt-related visibility rules apply now also checks a new region called "PromptHint", in addition to the existing "AbovePrompt" and "Pane" regions.

**Why**

The finding doesn't specify what content lives in the PromptHint region or what changes as a result, but it extends the same visibility framework already used for panes shown above the prompt.

- Area: Terminal Rendering
- Names: `PromptHint`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New UI type ToolProgressHint

A new ToolProgressHint UI element type was added for tool-progress display

**Unclear.** What ToolProgressHint displays and when it appears is not stated.

**What**

Claude Code's UI type mapping now includes a new entry: `ToolProgress` maps to a component called `ToolProgressHint`, joining the existing mappings for `ToolUse`, `ToolResult`, and `ToolGroup`.

**Why**

This suggests a dedicated visual element for showing progress on an in-flight tool call, separate from the existing tool-use and tool-result displays, though the finding doesn't describe what it looks like or when it appears.

- Area: Plugin UI
- Names: `ToolProgressHint`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Reserved artifact mints tracked separately from stranded mints

Artifact tracking now separates reserved mints from stranded mints

**Unclear.** What a 'mint' is and how an artifact being reserved differs from stranded is not explained.

**What**

Claude Code tracks "mints" related to artifacts, and previously kept a `strandedMints` set. It now also keeps a separate `reservedMints` set, cleared at the same points as `strandedMints` and also consulted when deciding whether an artifact is stale.

**Why**

The finding doesn't explain what a "mint" represents in this context, but tracking reserved mints separately from stranded ones suggests Claude Code can now distinguish artifacts that are intentionally reserved from ones that were simply abandoned, when deciding whether an artifact is out of date.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Queued command attachments narrowed

Stripping of render-state fields from queued messages now only applies to queued-command attachments

**What**

When Claude Code processes queued messages, it strips out internal `rendered` and `renderedInHumanTurn` fields before further handling. This stripping now only happens when the attachment's type is specifically `queued_command`, rather than for any attachment type.

**Why**

This narrows the cleanup logic so it no longer accidentally touches fields on unrelated attachment types, reducing the chance of other queued attachments losing data they shouldn't.

- Area: Prompt Queue
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New 'peer_standing' outcome for sync/push operations

Sync/push operations gain a new 'peer_standing' outcome state

**Unclear.** What condition produces the peer_standing outcome and what Claude Code does differently for it is not stated.

**What**

A retry-outcome switch and a related status list used in sync/push operations now include a new case, `peer_standing`, alongside existing states such as `no_journal`, `yielded`, `upload_only`, and `refused`.

**Why**

The finding does not explain what triggers this outcome or how it's handled, only that it's a newly recognized state in the sync/push retry logic.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Rate-limit options UI now requires the Ink renderer

Rate-limit options screen now requires the Ink terminal UI to be available

**What**

The hidden feature flag controlling the 'Show options when rate limit is reached' screen now declares `requires: { ink: true }`, meaning this feature is gated on the Ink terminal rendering library being available.

**Why**

This ensures the rate-limit options screen only activates in environments that support Ink-based rendering, avoiding attempts to show it where the terminal UI framework it depends on isn't present.

- Area: Rate Limits
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Model usage/dependency tracking now watches growthBookVersion

Rate-limit usage display now re-renders when GrowthBook feature-flag data updates

**What**

A component that displays model usage and rate-limit information now watches `growthBookVersion` as part of its re-render logic. This means the display updates whenever the underlying GrowthBook feature-flag snapshot changes version.

**Why**

This keeps the usage display in sync with the latest feature-flag configuration, so changes delivered through GrowthBook (the service Claude Code uses to manage remote feature flags) are reflected without requiring a restart or unrelated re-render.

- Area: Rate Limits
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### session_id telemetry suppressed for remote-trigger entrypoints

Telemetry no longer records a session_id when Claude Code was started via a remote trigger

**What**

A telemetry helper that used to attach the current `session_id` to outgoing telemetry whenever one was available now leaves it out if the process was launched through a remote trigger entrypoint (a way of starting Claude Code programmatically rather than by hand).

**Why**

This means telemetry from remotely-triggered runs is harder to tie back to a specific session, which matters mainly for diagnosing issues in automated or remotely-started Claude Code runs.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Settings-sync invalidation now includes a policy_verdict trigger

Settings and hooks can now be invalidated by a new policy_verdict trigger

**What**

The list of reasons that can cause Claude Code to invalidate and reload its settings and hooks now includes a new `policy_verdict` entry, alongside the existing `settings_sync`, `account_change`, and `hooks_invalidate` reasons.

**Why**

This lets a policy decision (such as one made by an organization's admin controls) trigger a refresh of settings and hooks, so changes driven by policy take effect without needing one of the other existing triggers.

- Area: Settings
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New plugin-directory identifiers recognized

Claude Code now recognizes two new plugin marketplace directory names

**Unclear.** The finding does not give the exact new names beyond "anthropic-plugin-directory" for the Anthropic-branded one, nor say what the generic Claude-branded one is called.

**What**

The set of accepted plugin marketplace directory identifiers now includes both an Anthropic-branded name and a generic Claude-branded name, in addition to whatever names were already accepted.

**Why**

This lets Claude Code recognize additional official-style plugin directories, so plugins published under either of these names are picked up correctly.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Session/checkout ID format tightened to a strict UUID regex

Device attestation status now validates session/checkout IDs as strict UUIDs

**What**

A constant used in device attestation status checks, which previously matched an ID by string prefix, is replaced with a strict regular expression that only matches a properly formatted UUID (a standard 36-character identifier format).

**Why**

This makes the check stricter: an ID has to be a well-formed UUID to pass, rather than merely starting with the right prefix, which should reduce the chance of a malformed or spoofed ID being accepted.

- Area: Attestation
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New 'checkout_empty' terminal/session state

A new checkout_empty state is added to session/folder seeding logic, always reported as not seeded

**Unclear.** The finding does not say what triggers the checkout_empty state or where a user would see it.

**What**

A function that classifies the state of a session's checkout or folder (previously handling clone and folder-being-seeded cases) gains a new case, `checkout_empty`, which is always treated as "not seeded."

**Why**

This gives Claude Code a distinct way to represent a checkout that is empty, rather than lumping it in with other states, which should make status reporting for that situation more accurate.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Session lifecycle events gain a 'detached' outcome

Session lifecycle logging gains a new detached outcome

**Unclear.** The finding does not say what causes a session to become detached or what a user experiences when it happens.

**What**

The list of possible session lifecycle outcomes that Claude Code records now includes `detached`, in addition to the existing `recreated`, `ended`, `cleared`, and `start_failed`.

**Why**

This lets Claude Code distinguish a session becoming detached from the other existing outcomes, giving more precise session lifecycle information.

- Area: Session Lifecycle
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Task output max-length now derived per output host

Task output length limit now depends on the output destination, not one global setting

**Unclear.** The finding does not say what the different output hosts are or how their limits differ from the previous taskOutputMaxChars setting.

**What**

The function that decides how many characters of a background task's output to include now derives that limit from the current output host or target (via `Ou.of(W().host)`), instead of always reading it from a single `taskOutputMaxChars` setting.

**Why**

This means the amount of a background task's output that Claude receives inline can now differ depending on where the output is going, rather than being capped the same way everywhere.

- Area: Background Tasks
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Telemetry failures in request/response logging no longer crash the call

A telemetry failure while logging request or response content no longer crashes the API call

**What**

The code that computes telemetry about a request's prefix and a response's content is now wrapped in try/catch. If this telemetry computation fails, Claude Code now logs "request prefix telemetry failed" or "response content telemetry failed" through its debug logger instead of letting the error propagate and interrupt the API call.

**Why**

Previously, a bug in this telemetry code could break an otherwise-working API request. Now such a failure is just logged, so telemetry problems can't take down a real request or response.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### CCR worker requests can target a custom session URL

CCR worker requests can now target a custom session URL instead of the default endpoint

**Unclear.** The finding does not say what CCR stands for or in what situation a custom ccrSessionUrl would be set.

**What**

The function that sends CCR worker requests to a Claude session now checks for a `ccrSessionUrl()` value from the host's launch options first. If one is set (with any trailing slashes removed), it's used as the base address for the `/worker/...` call; otherwise Claude Code falls back to the default `.../v1/code/sessions/{id}` URL. When a socket is used for the connection, the log now also notes "over ${socket path}" for extra context.

**Why**

This allows worker requests to be redirected to a non-default session endpoint, useful when a session isn't reachable at the standard URL.

- Area: CCR
- Names: `ccrSessionUrl`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### MCP tool calls now register with a foregroundCalls tracker keyed by session

MCP tool calls now register in a per-session foregroundCalls tracker

**What**

When Claude Code makes an MCP (Model Context Protocol) tool call, it now registers that call in a new `foregroundCalls` tracker keyed to the current session, unless the call is an internal ("inner") call.

**Why**

This tracker is what lets Claude Code know which MCP tool calls are still running in the foreground, supporting the new ability to move a call to the background as soon as a new message arrives.

- Area: MCP
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### REPL bridge placeholder sweep now schema-validates entries before acting on them

REPL bridge placeholder cleanup now validates entries against a schema before acting on them

**What**

The periodic sweep that cleans up REPL bridge placeholders (entries expected to have a process ID, optional process-start time, and creation time) now validates each entry against a defined schema before acting on it, rather than assuming the entry has the expected shape. Entries that fail validation are skipped or removed defensively.

**Why**

This prevents the cleanup sweep from crashing or misbehaving if it encounters a malformed or unexpected placeholder entry.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin/skill search error handling refactored into a shared helper

Plugin and skill search error handling was consolidated into one shared internal helper

**What**

The internal logic that decides whether a plugin or skill search request is allowed to run (for example, checking permission scopes) has been pulled out of the search tool and into a shared helper function. That helper is now used both by the existing plugin/skill search tool and by the new plugin-install-suggestion feature's detail-fetch step.

The visible behavior, such as messages explaining a policy denial or silently skipping a search when there's no scope to search in, appears unchanged.

**Why**

This is an internal cleanup that reduces duplicated code, making the permission and error-handling logic easier to maintain consistently across the features that rely on it. It shouldn't change what you see when searching for plugins or skills.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Design login supports manual authorization-code entry even mid-flow, with structured failure reasons

Plugin install failures are now tagged as internal errors for Claude Code's own handling

**What**

When installing a plugin fails, for reasons like a missing marketplace location, a settings file that couldn't be written, a resolution failure, a policy block, a version-range conflict, or no matching tag, the resulting error object now carries a new `errorIsOurs: true` flag alongside its usual error message.

**Why**

This lets Claude Code distinguish its own known, expected install failures from other kinds of errors, so it can handle or display them differently downstream. It doesn't change the error messages you see, but it changes how the system can route or react to them.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### MCP tool calls now track concurrent foreground calls per session for auto-backgrounding decisions

MCP tool calls now track how many foreground calls are running per session, for auto-backgrounding decisions

**Unclear.** What specific effect the foreground-call count has on the auto-backgrounding decision is not stated.

**What**

When Claude Code decides whether an MCP (Model Context Protocol, a standard for connecting external tools) tool call is eligible to be moved to the background automatically, it now also passes along a count of how many other foreground calls are currently outstanding in the same session, unless the call is a nested/inner call, in which case this isn't tracked.

**Why**

This gives the auto-backgrounding logic more information about concurrent activity in a session, which can inform when it's appropriate to move a slow tool call to the background rather than making you wait on it.

- Area: MCP
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### MCP tool-use id now sourced from the tool-use record when available

MCP tool calls now reuse an existing tool-use id instead of deriving one, and add a per-request header

**What**

When Claude Code makes an MCP (Model Context Protocol) tool call, it now prefers to use the tool-use id already attached to the call record, rather than deriving one from request headers as it did before. It also now adds a new per-request metadata header carrying the request id, in addition to the existing `claudecode/toolUseId` metadata.

**Why**

This is an internal correctness and traceability improvement for how MCP tool calls are identified, which can help with matching requests to responses correctly and debugging.

- Area: MCP
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Directory-sync journal comparison now tracks repositoryTrust and localTools

Directory-sync now also detects changes to repository trust and local tools settings

**What**

The logic that detects changes in Claude Code's directory-sync configuration (used to decide when to update related session state) now also compares `repositoryTrust` and `localTools` fields, using a new deep-equality helper, alongside the `whileClosed` field it already checked. New descriptive text such as "served by this machine" and "not serving this session" was added to explain trust and sync status.

**Why**

This means changes to repository trust or local tool settings are now properly detected and reflected by directory sync, where previously they may not have triggered an update, and the added text gives clearer explanations of a device's sync/trust status.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Scratch-folder path phrase gets normalized/obfuscated before display

References to the session's scratch folder are now normalized into a fixed phrase before display

**Unclear.** The finding does not explain why paths would sometimes be shown relative to the scratchpad location.

**What**

Claude Code now recognizes variants of the phrase "in this session's scratch folder" (allowing for different spacing and punctuation) and rewrites them into one fixed, hyphenated form before showing them. A related new function decides whether a file path should be displayed relative to a scratchpad location.

**Why**

Normalizing the wording keeps references to the scratch folder consistent on screen, regardless of small variations in how the phrase was originally generated.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Tool-card description height now depends on a 'roomyDescription' flag

Tool-call cards can now show taller descriptions when a new 'roomyDescription' flag is set

**Unclear.** What determines when roomyDescription is set to true is not stated in the finding.

**What**

The cards Claude Code shows for permission requests and tool calls now compute their maximum description height using a new `roomyDescription` flag. When this flag is true and the terminal window is wide enough, the card is allowed to grow taller (up to a cap) instead of being limited to the previous fixed minimum height.

**Why**

This lets longer tool-call descriptions display more fully on wide terminals instead of being cut off at a fixed short height.

- Area: Terminal Rendering
- Names: `roomyDescription`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Git env-var passthrough now filters out hook-related config overrides

Git environment passthrough now drops hook-related config overrides before spawning git

**What**

When Claude Code builds the environment for a spawned git process, it merges in `GIT_CONFIG_KEY_N`/`GIT_CONFIG_VALUE_N` pairs pulled from `GIT_CONFIG_COUNT`, but now explicitly drops any key that starts with `hook.` before passing the merged environment through.

**Why**

This stops git config overrides from being able to set hook-related configuration when Claude Code runs git commands, closing off one way hook behavior could be redirected via environment variables.

- Area: Git Internals
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin preview cache now prunes old preview trees instead of leaking them

Plugin preview cache now cleans up old preview trees instead of accumulating them

**What**

When Claude Code materializes a preview of a plugin, it now tracks how many previews have been made per source. Once a source passes a cap, the oldest preview trees are moved aside and deleted in the background. The code also guards against a caller trying to read a preview that is being pruned at the same time.

**Why**

This prevents plugin preview files from piling up on disk indefinitely, while avoiding errors if a preview is read at the same moment it's being cleaned up.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin gitCommitSha resolution gains a marketplace-npm fallback

Plugin version tracking gets a fallback for npm-based marketplaces without a git checkout

**What**

When Claude Code figures out which version of a plugin's code is installed (by resolving a git commit hash, used for caching), it now handles the case where the plugin's checkout isn't a git repository but comes from an npm-style plugin marketplace. In that case, it falls back to a separate resolver to find a commit-like identifier. A new `keepStoredCommit` flag also ensures that if neither method can resolve an identifier, a previously stored one isn't discarded.

**Why**

This prevents plugins installed from npm-based marketplaces from losing their version-tracking information just because they weren't installed via a plain git checkout, and avoids erasing a known-good stored version when a fresh lookup comes up empty.

- Area: Plugin Install
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New boot-latency metrics for org/team memory store sync

New timing metrics track how long syncing org/team memory takes at startup

**What**

Claude Code now measures how long it takes to pull the team and user memory store when it starts up, recording this as `memory_store_pull_ms`. It also records `memory_store_pull_boot_spillover_ms`, which measures how much of that pull happened after Claude Code had already reported itself ready for input. These mirror an existing pair of metrics, `memory_context_fetch_ms` and `memory_context_boot_spillover_ms`, that measured similar timing for memory context fetches.

**Why**

These are internal diagnostics that help identify when memory-store syncing is slow enough to spill over into the time a user is already able to start typing, rather than finishing before startup completes.

- Area: Team Memory
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### One MCP-connector tool marked non-backgroundable

An internal MCP connector lookup tool can no longer run in the background

**Unclear.** The finding does not say what would go wrong if the tool ran in the background, only that it is now disallowed.

**What**

An internal tool that resolves MCP (Model Context Protocol, a way of connecting external tools and data sources to Claude) connector payloads by a directory identifier is now marked as never backgroundable. This means it can't be run in a background context, such as inside a subagent (a separate Claude instance spawned to do a sub-task).

**Why**

Restricting this tool to run only in the main session context suggests it depends on state that isn't reliably available, or safe to use, outside that context.

- Area: MCP
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### CCR client-event uploads now record queue-position diagnostics per frame

Client telemetry uploads now record what each event was queued behind before sending

**What**

When Claude Code uploads tracked telemetry events, each upload is now tagged with a timestamp of when it was queued (`enqueuedAtMs`) and a classification of what it was waiting behind before being sent: a hold, a durable post, an ephemeral post, a retry backoff, or nothing.

**Why**

This is a diagnostic addition that lets Claude Code's telemetry pipeline distinguish delays caused by queuing behind other uploads from delays caused by retries or other holds, which helps pinpoint where event-reporting slowdowns come from.

- Area: CCR
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Model family aliasing now recognizes date-suffixed canonical model ids

Model-family matching now recognizes date-suffixed model IDs as canonical for Opus, Sonnet, and Haiku

**What**

Claude Code now has a helper that decides which model ID counts as the 'canonical' representative for each of the Opus, Sonnet, and Haiku model families: an ID qualifies if it starts with `claude-` and either matches the family's base name exactly, or matches the base name plus a date, or the base name plus `@date`. When building the map of canonical IDs per family, this canonical form is now preferred over any other ID seen for that family. The code that builds the model list also now loops over a shared list of the three family names instead of writing them out separately each time.

**Why**

This makes model selection more consistent when multiple IDs for the same model family exist (for example, dated snapshot versions), ensuring the same canonical ID is chosen rather than an arbitrary one.

- Area: Models
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Queued-command attachments from a new 'coordinator' origin are now recognized for filtering/collapsing

Queued commands from a new 'coordinator' source are now foldable in transcript history like other background messages

**Unclear.** The finding does not say what a 'coordinator' origin is or where queued commands from it come from.

**What**

Claude Code already collapses certain transcript entries during history filtering and compaction, such as channel messages, peer messages, Slack pings, and task notifications. A new check now also recognizes 'queued_command' attachments whose origin is a 'coordinator', treating them the same way: as candidates for folding or skipping when trimming transcript history.

**Why**

This keeps transcripts from a coordinator source consistent with other background-origin messages, so they don't clutter the visible history any more than channel or task notifications already don't.

- Area: Transcript
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Dynamic-workflows tips (workflow-size-prompting) gated on settings.enableWorkflows, function renamed

Tips about dynamic workflows now only show when the enableWorkflows setting is on

**What**

The tip messages that introduce dynamic workflows and workflow sizing (`dynamic-workflows`, `workflow-size-prompting`, and `workflow-size-prompting-ambient`) now check the `enableWorkflows` setting before showing. If it's off, either in your own settings or by the account's server-side default, the tips are suppressed.

The `workflow-size-prompting` tips also require that the current session has already used a tracked tool, and that the tip hasn't been dismissed ('snoozed') before.

**Why**

This keeps workflow-related tips from appearing for accounts where dynamic workflows (`enableWorkflows`) are turned off, avoiding advice about a feature you can't use.

- Area: Elsewhere
- Names: `enableWorkflows`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### CLI budget/task-budget argument errors now thrown as a different error class

Errors for invalid --max-budget-usd or --task-budget values now use a different internal error class, same message

**What**

When you pass an invalid value to `--max-budget-usd` or `--task-budget` (for example, a non-positive number), Claude Code still reports the same error text, but now throws it as a different internal error class.

**Why**

This is an internal change to error handling and shouldn't be noticeable in normal use; the error message you see stays the same.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New per-turn timing telemetry fields on result events

Headless turn results now include extra timing details like stream-post queue wait and first-text timestamp

**What**

The result data returned for each turn in headless mode now includes several new timing measurements:

- how long the first streamed output had to wait in a queue before being posted

- whether that first post was queued behind something else

- the timestamp of the first text output

- wall-clock frame timing for "hearth" and "relay" turns

**Why**

These fields give tooling built on top of Claude Code's headless mode finer-grained visibility into turn latency, useful for diagnosing slow responses.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### awaitStagedFiles option added to the pre-turn handoff path

The pre-turn handoff step can now wait for staged files before continuing

**What**

The internal function that handles the handoff at the start of a turn now accepts an `awaitStagedFiles` option. It's supplied only when a turn-handoff has been admitted, in which case the turn waits for files staged during that handoff.

**Why**

This helps ensure that files staged as part of handing off between turns are actually ready before the new turn proceeds, avoiding races where a turn starts before its staged files are in place.

- Area: Turn Handling
- Names: `awaitStagedFiles`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Bridge control requests now logged with duration/deadline telemetry

SDK bridge now logs how long each control request took to handle, plus deadline/timeout info

**What**

The SDK bridge, which relays control requests between a client and Claude Code, now measures and logs how long each `control_request` took to process. The new telemetry event also records whether the request was "detached" and, when a deadline was set on the request, what that deadline was and whether it was exceeded.

**Why**

This gives better visibility into bridge performance and helps diagnose slow or timed-out control requests when building on the SDK.

- Area: SDK
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### set_cwd now checks whether the session is fresh

set_cwd now checks whether the session is still fresh before changing directory

**What**

The handler for the `set_cwd` control request (which changes the working directory) now checks whether the session is "fresh": no messages have been dequeued yet and no assistant message exists in the history. This freshness check is factored into the existing logic around model messages and transcript relocation.

**Why**

This lets `set_cwd` behave differently for a session that hasn't really started yet versus one already underway, likely to avoid unwanted side effects like transcript relocation on a session that has already produced output.

- Area: Directory Change
- Names: `set_cwd`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### stage_file gains a mount-path/output-prefix check and non-filestore concurrency tracking

stage_file now flags outputs-mount paths and tracks concurrency for non-filestore staging

**What**

The `stage_file` control request now checks whether the requested `mount_path` falls under a new `STAGE_FILE_OUTPUTS_MOUNT_PREFIX` path and flags it if so. Separately, requests that don't include a `filestore_path` are now wrapped in a begin/cleanup pair that tracks concurrency and keeps the process alive while staging is in progress, which wasn't done before.

**Why**

The mount-path check lets Claude Code distinguish files staged to a special outputs location. The added concurrency tracking for non-filestore staging helps ensure such staging operations complete properly rather than being cut short.

- Area: File Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Session hint inclusion in error telemetry now has a cooldown/opt-out

Session hints attached to error telemetry now respect a recent opt-out before being sent again

**What**

When a request fails with a 400 error, Claude Code can attach hints (like the entrypoint, session ID, and request ID) to the telemetry it sends about that error. Now, if a session recently indicated it should refuse to include those hints, that refusal is remembered and later checks will skip attaching the hints until the cooldown passes.

**Why**

This avoids repeatedly attaching identifying session hints to error reports after a session has recently declined to include them.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Git helper functions refactored to accept an explicit working directory

Git diff/status helper functions can now target an explicit working directory instead of always using the process's own

**What**

A group of internal git helper functions that compute diffs and status were changed to accept an explicit working directory parameter, rather than always operating on the directory the Claude Code process itself is running in. A new helper picks between the normal environment and an isolated environment (with `extendEnv` turned off) depending on whether a working directory was passed in.

**Why**

This allows git operations to be run correctly against a different folder than the current process directory, which matters for features that need to inspect git state in another location, such as a separate worktree or machine.

- Area: Git Internals
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Remote-control command-unavailability check now distinguishes 'relay' from 'bridge' surface

Claude Code now logs whether a blocked slash command was reached over the 'bridge' or 'relay' remote-control surface

**What**

When you try to run a slash command that isn't available over Remote Control (the feature that lets you drive a Claude Code session from another device), the code that reports this has been split into two paths: one for the 'bridge' surface and one for the 'relay' surface. Both now feed into a shared logging call that records a `tengu_slash_command_unavailable` event tagged with which surface was in use.

**Why**

This doesn't change what you see as a user; a blocked command still tells you it isn't available. It gives Anthropic better visibility into which remote-control path (bridge vs. relay) triggers these blocks, which should help them fix gaps in remote-control support faster.

- Area: Remote Control
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Assistant turn origin now recorded on queued messages

Queued messages now get their assistant-turn origin recorded if it was missing

**What**

After Claude Code builds the result of a query, it now checks the relevant user message and, if it doesn't already have a `turnOrigin` value, fills one in with details like the origin, whether it was a meta message, what woke the session up, the prompt source, and what initiated the host.

**Why**

This is internal bookkeeping that helps Claude Code track where a given turn came from; it isn't expected to change anything visible in day-to-day use.

- Area: Turn Handling
- Names: `turnOrigin`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### takeUserFrameReceivedWallMs is a no-op on the base/local session type, real only on the remote transport

A new session-timing method only does something on the remote transport, not on local sessions

**What**

A new method called `takeUserFrameReceivedWallMs` was added to the base class Claude Code uses to read session data. On a plain local session, it does nothing and always returns nothing. On the remote transport (the connection used for remote sessions), it's overridden with a real implementation that reads and clears a stored wall-clock timestamp, paired with a new hook that gets called when a user frame is received.

**Why**

This lets Claude Code measure timing details, such as when a user's input frame actually arrived, specifically for remote sessions, without affecting how local sessions behave.

- Area: Remote Control
- Names: `takeUserFrameReceivedWallMs`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New tool names added to a shared exclusion/classification set

Five new tool names, including TaskOutput and BashOutput, were added to a shared internal tool-classification list

**What**

A shared internal list used in several places, including how tool results are displayed and cached, gained five new entries: `TaskOutput`, `AgentOutputTool`, `BashOutputTool`, `AgentOutput`, and `BashOutput`.

**Why**

This keeps these newer tools handled consistently with how existing tools are treated internally, for example in rendering and memoization logic, though it isn't something you'd notice directly.

- Area: Tool Results
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New 'checkout_empty' dir-sync origin kind, always non-seeded

A new 'checkout_empty' directory-sync origin kind is always treated as not pre-seeded

**What**

The code that tracks how a synced directory was originally set up (for example, cloned, seeded, or from an existing folder) gained a new kind called `checkout_empty`. Unlike the other kinds, it's always treated as never having been pre-seeded with content.

**Why**

This lets Claude Code's directory-sync feature correctly distinguish an empty checkout from other setup methods, which likely affects what it assumes is already present when syncing starts.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### RemoteSessionManager.sendMessage/send gain an extra threading parameter

RemoteSessionManager's message-sending functions gained an extra parameter threaded through to gate checks

**Unclear.** What the new parameter represents or controls isn't stated, so its practical effect is unclear.

**What**

The internal `sendMessage` and `send` functions used by `RemoteSessionManager` to deliver messages now take an additional parameter, which is passed through to the function that checks gates (settings that control whether a feature is active) before sending. The retry path that resends a prompt withheld earlier now calls `send` directly instead of going through the previous `sendMessageVia` function.

**Why**

This is an internal plumbing change to how messages are routed and gated in remote sessions; the finding doesn't indicate a new user-visible capability, but it changes how the withheld-prompt retry is wired up internally.

- Area: Remote Control
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Removed several optional fields from an internal schema (question/points/summary/next/options/lead/headline)

An internal schema dropped seven optional fields: question, points, summary, next, next_why, options, lead, headline

**Unclear.** Which feature this schema belongs to and what removing these fields changes for the reader is not stated

**What**

An internal schema definition no longer includes seven optional fields it previously had: `question`, `points`, `summary`, `next`, `next_why`, `options`, `lead`, and `headline`.

**Why**

What this schema is used for isn't shown, so it's unclear what feature or output this affects.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Native update cleans up orphaned staging directories on every check

Native updater's orphaned-staging-folder cleanup was refactored into its own function, always run before plugin-lock cleanup

**What**

The cleanup logic that removes leftover staging directories from the native updater has been pulled out into its own dedicated function, and is now always run before the plugin-lock cleanup step, rather than being interleaved inline with it as before.

**Why**

This is a reordering and cleanup of internal update logic; the staging cleanup ran unconditionally before too, so this mainly changes the order and structure of the code rather than adding new behavior.

- Area: Updater
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Git diff-stats helpers gained explicit cwd/git-dir plumbing for worktrees

Git diff-stat helpers now take an explicit working directory instead of assuming the current one

**What**

A group of internal functions that compute git diff statistics now accept an explicit working directory (cwd) parameter, instead of relying on the ambient current directory or environment. This includes a new check for whether a merge is in progress, which now also takes a working directory.

**Why**

This makes these git-stats functions work correctly when operating on a git worktree other than the main one, rather than assuming the process's own current directory.

- Area: Git Internals
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Diagnostics/plan-mode/task-status transcript rendering: minor helper renames, no behavior change spotted

Transcript rendering helpers were renamed internally, with task-status messages using two of the new names

**What**

Several internal helper functions used in rendering diagnostics, plan mode, and task-status entries in the transcript were renamed. Task-status messages now go through two of these renamed helpers instead of their old-named counterparts.

**Why**

This appears to be an internal rename with no observed change in behavior.

- Area: Terminal Rendering
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Bash sandbox execution path — mostly cosmetic variable churn, no clear functional change

Bash sandbox execution code renamed internally, with no functional change found

**What**

The code that runs bash commands, sandboxed or not, has had many of its internal variable names changed around building filesystem allow/deny lists, registering network access lists, and spawning subprocesses with telemetry. The underlying logic, including how write access is denied by default (`keepBaseDenyWrite`) and read access can be dropped (`dropAllowRead`), tracking of the working directory, and telemetry attributes, appears unchanged.

**Why**

This looks like internal cleanup rather than a behavior change, so nothing should look different when running bash commands.

- Area: Sandbox
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Artifact publish flow: mostly variable renaming, no clear behavior change found

Artifact publish code reorganized internally with no behavior change found

**Unclear.** Whether any subtle behavior change is hidden among the renaming was not confirmed either way.

**What**

A large block of the artifact-publish function was restructured, but the changes appear to be variable renaming and reordering from the build process rather than a functional change. The message explaining that the tag always takes precedence over the title, and the file-copy and ownership checks, work the same as before.

**Why**

No user-facing effect was found in this change.

- Area: Artifact Publish
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### A custom-header spread in the API client now includes an inert no-op spread

A no-op false value was added to the API client's custom-header spread, with no apparent effect

**What**

Where the client's default headers previously spread in only one extra source (the `ANTHROPIC_CUSTOM_HEADERS`-derived `anthropic-beta` values), the code now also spreads a literal `false` value immediately before it.

**Why**

Spreading a boolean `false` into an object has no effect, so this appears to be an inert change with no impact on the headers Claude Code sends.

- Area: API Client
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Local/prompt slash-command dispatch: cosmetic-only rename, no behavior change found

Slash-command dispatch code was renamed internally with no behavior change found

**What**

A large section of code handling local and prompt slash-command execution, including deferring commands to the engine, stacked skills, and `UserPromptSubmit` hook handling (which runs when you submit a prompt, before Claude processes it), was restructured under new minified variable names. The underlying `deferSlashToEngine`/`engineDeferredSlash` mechanism it relies on already existed previously.

**Why**

No functional change was found in this code; it appears to be a cosmetic rename from the build process.

- Area: Slash Commands
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### New logger extension with an explicit `level`

A new internal logger extension creates a child logger with an explicit logging level

**Unclear.** The finding doesn't say what triggers this or what `pct` represents, so it's unclear which part of Claude Code gains its own log level.

**What**

A new internal call, `s.extend({ level: pct })`, creates a child logger with a specific logging level set explicitly, rather than inheriting a default one.

**Why**

This is an internal logging change and doesn't directly affect what you see while using Claude Code, but it lets a specific part of the code log at its own chosen verbosity level.

- Area: Internals
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Notification rendering drops its keydown capture handler

Notification popups no longer capture keydown events on their wrapper

**Unclear.** What functionality onKeyDownCapture was providing, and what effect removing it has, is not stated in the finding.

**What**

The container that wraps notification popups in a column layout no longer passes an `onKeyDownCapture` handler, removing a key-capture hook that previously existed on that element.

**Why**

Removing this handler means the notification wrapper no longer intercepts key presses before they reach other parts of the interface, though the finding does not say what behavior this was previously enabling or blocking.

- Area: Terminal UI
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Write tool's dangerous-rm-on-unset-variable check refactored, message likely unchanged

Internal cleanup of the dangerous rm-with-unset-variable safety check, no visible behavior change

**What**

The safety check that warns about bash commands like `rm -rf $UNSET/*` (deleting based on a variable that might be empty or unset) now builds its warning message through a shared helper function instead of assembling the text inline. The check still fires under the same internal event name, `tengu_bash_dangerous_rm_too_complex`.

**Why**

This is an internal refactor; the warning shown to users for this kind of risky command is expected to stay the same.

- Area: Bash Safety
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Pasted-content merging centralized into a helper (uZ)

Pasted-content merging logic consolidated into a shared uZ helper function

**What**

Several places in the code that merge pasted content and images (previously done by copying an old object and adding new entries in a loop) now call a shared helper function, `uZ(...)`, to do this instead.

**Why**

This is an internal cleanup that consolidates duplicated logic into one place; it should not change what a user sees when pasting content.

- Area: Prompt Input
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Auto-mode Sonnet-5 classifier probe retained, log wording unchanged but refactored

Internal refactor of the auto-mode Sonnet 5 classifier fallback, no behavior change

**What**

The internal logic that lets auto mode fall back to using Sonnet 5 as a classifier (and demotes on error) was refactored internally. The log wording stays the same.

**Why**

This is a code cleanup with no effect on what you see or how auto mode behaves.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### AGENTS.md project-instructions doc string replaced by opaque key

The explanation text for using AGENTS.md as project instructions was replaced with an internal key

**Unclear.** Whether this changes any user-visible text or behavior around AGENTS.md is not stated.

**What**

A long, descriptive string that explained when `AGENTS.md` is used as project instructions was replaced with a bare identifier, `agents_md`.

**Why**

This looks like an internal refactor, likely moving the descriptive text to be looked up elsewhere (such as for translation or reuse) rather than a change in when `AGENTS.md` is actually used for project instructions.

- Area: CLAUDE.md Rules
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Thinking-display error detection simplified

Detection of a specific thinking-display API error now uses only a regex match, not an added string check

**What**

Claude Code detects a particular API error (a 400-level error about how 'thinking' output should be displayed) in order to handle it specially. The detection logic now relies only on a regular expression match against the error message, dropping a second string-matching condition that used to also trigger the detection.

**Why**

Simplifying to a single check reduces duplicate logic; the regex alone was apparently sufficient to catch the cases the extra string match was also catching.

- Area: Thinking Display
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Renamed tengu feature flags (bright_ripple → jaunty_ember, cozy_pixel → humble_zephyr)

Two experiment flags renamed: bright_ripple to jaunty_ember, cozy_pixel to humble_zephyr

**What**

Two internal experiment flags were renamed while keeping the same default (off):

- `tengu_bright_ripple` is now `tengu_jaunty_ember`

- `tengu_cozy_pixel` is now `tengu_humble_zephyr`

The `tengu_cozy_pixel` flag was previously associated with a remote-control conversation-fork feature (`fork_conversation`) that lets a remote client branch a running session mid-conversation from a specific point.

**Why**

Nothing has been read yet about how either renamed gate, `tengu_jaunty_ember` or `tengu_humble_zephyr`, is currently configured, so it's not yet known whether the underlying features they control are active.

- Flag `tengu_jaunty_ember`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Flag `tengu_humble_zephyr`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: off) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Flag `tengu_bright_ripple`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Flag `tengu_cozy_pixel`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Feature Gates
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Cookie/query field turn_origin added to log scrubbing

Logs now also scrub a cc_turn_origin field alongside existing sensitive query/cookie fields

**What**

The regular expression Claude Code uses to strip sensitive fields out of logged query strings and cookies, which already covered `cc_prev_req`, `cc_prompt_id`, and `cc_workload`, now also scrubs `cc_turn_origin`.

**Why**

This keeps a field that tracks where a turn originated from out of logs, consistent with how the other related fields are already protected.

- Area: Internals
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### SDK schema-violation telemetry now samples from a variable rate constant

SDK's outbound message schema-check sampling now uses a renamed rate variable

**Unclear.** Whether the sampling rate value itself changed, or only the variable's name, isn't stated; the gate `tengu_sdk_schema_violation` hasn't been read for this site's account.

**What**

The SDK's internal check that occasionally validates outbound messages against a schema (and reports mismatches via the `tengu_sdk_schema_violation` telemetry event) still decides randomly whether to run, but now reads its sampling rate from a renamed internal variable, and some of its supporting schema/parsing helper functions were renamed.

**Why**

This looks like an internal refactor rather than a behavior change readers would notice.

- Area: SDK
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Peer/freshness tracking caches reworked from WeakMap to an id-keyed store, with an offered-set added

Internal peer and session-freshness tracking was rewritten from identity-based caches to id-based ones with a new offered set

**Unclear.** What user-visible effect this internal rework has, if any, is not stated.

**What**

Two internal tracking mechanisms, one for tracking peers in a shared ledger and one for tracking remote sessions, were rewritten. They previously used WeakMap-based storage keyed by object identity, with a per-entry invalidation flag; they now use an id-keyed store built around an incrementing global counter (an "era"). The remote session tracker also gained a new `offered` set, which is cleared whenever a session registers.

**Why**

This is an internal rework of how Claude Code tracks freshness and offers for peers and remote sessions. The finding doesn't specify what user-visible problem it fixes, but it changes the underlying bookkeeping these features rely on.

- Area: Remote Control
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Version-config minimum-version check refactored into a separate function

Startup version-check logic was refactored into its own function, no behavior change

**What**

The startup check that fetches the `tengu_version_config` setting and warns when your CLI version is too old has been reorganized: the logic that issues the warning and reports it now lives in its own separate function, instead of being written inline inside the same routine that fetches the config.

**Why**

This is an internal code cleanup with no described change in behavior; it should not change what you see when your CLI is out of date.

- Flag `tengu_version_config`: Not enough to say (read for one account on one subscription tier against v2.1.277; this account: no value returned, anonymous baseline: no value returned, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Area: Updater
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Directory-sync (git-based cloud file sync) upload/retry engine internally reworked

Directory sync's upload and retry engine was rewritten internally with no apparent behavior change

**What**

A large portion of the directory-sync engine, the system that keeps files synced between your local folders and the cloud via git, was restructured and renamed internally. This includes push/pull scheduling, the retry backoff used for a file's first upload, the "uncovered" result notices, and the status text shown while an upload is in progress.

**Why**

The rework appears to be internal cleanup rather than a behavior change, so directory sync should work the same as before from a user's perspective.

- Area: Directory Sync
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Remote Control / live-session messaging helpers renamed and reshuffled (agent-stopped handoff)

Internal renaming and rework of the Remote Control cross-machine messaging and agent-stopped handoff code

**Unclear.** The finding does not say whether this rework changes any observable behavior beyond the internal code structure.

**What**

The code behind sending a message to a session on another machine via Remote Control, and the handoff logic that runs when an agent stops, has been renamed and reorganized internally. The agent-stopped case now passes a live transcript and a parent prompt ID computed through new helper functions, replacing the previous versions of those same computations.

**Why**

This is an internal refactor of existing Remote Control messaging code; the finding does not indicate any change to what Remote Control does from a user's perspective.

- Area: Remote Control
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### loop-command-nudge tip: renamed gating helpers, command referenced is /loop

The /loop command's nudge tip had its internal gating checks renamed, no behavior change noted

**What**

The tip that nudges you toward the `/loop` command (which runs any prompt on a recurring schedule, useful for monitoring deploys, babysitting PRs, or polling status) now runs its eligibility checks through renamed internal functions. The tip's text and the `/loop` command itself are unchanged.

**Why**

This is an internal rename with no described effect on behavior; it doesn't change what `/loop` does or when the tip appears.

- Area: Elsewhere
- Names: `/loop`
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Hooks-module re-entry warnings now name the module by label, not name, and swap origin computation

Hooks re-entry log messages now show a module's label instead of its name

**What**

When Claude Code detects a plugin or hooks module trying to re-enter its own code (re-entry), the warning message logged now identifies the module by its `label` field instead of its `name` field, and computes the origin information differently internally.

**Why**

This is a diagnostic-message change: developers debugging plugin or hook re-entry issues will see a differently-sourced identifier and origin string in the log output.

- Area: Plugin Hooks
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Synced project memory write-permission checks refactored (rename only, same logic)

Internal rename in the synced project memory write-permission check, no logic change

**What**

The code that checks whether writes to synced project memory should be local-only or full read-write (`rw`) now calls renamed internal helper functions. The decision logic itself is unchanged.

**Why**

This is an internal cleanup with no effect on how project memory syncing behaves.

- Area: Team Memory
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Command-queue module: internal renaming only

Internal rename of command-queue functions, no behavior change

**What**

The functions that manage Claude Code's internal command queue (removing items, consuming them, filtering, clearing, resetting, and popping editable entries) were renamed internally. Their behavior is unchanged.

**Why**

This is a code-organization change with no user-visible effect.

- Area: Prompt Queue
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Version bump to 2.1.277

Claude Code version bumped to 2.1.277

**What**

This release updates the build's version number, build time, and git commit identifier to mark Claude Code 2.1.277.

**Why**

This is a routine version marker for the release.

- Area: Elsewhere
- Names: `2.1.277`
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### cancel_async_message logic unified between host and remote-control paths

cancel_async_message handling is now shared between host and remote-control sessions

**What**

The logic for handling a `cancel_async_message` request (finding the in-flight message, removing matching queued messages, and marking a cancel as pending) used to be written separately inline. It's now a single shared helper that takes a source, either `host` or `remote_client`.

The remote-control bridge session uses this shared helper with the `remote_client` source, which only cancels messages that originated from the bridge itself. If nothing has been queued yet for such a message, the helper now withdraws it from being ingested instead of just marking the cancellation as pending.

**Why**

This makes cancellation behave consistently regardless of whether a message came from the local host or a remote-control client, and closes a gap where a remote-originated message that hadn't yet been queued could not be properly withdrawn.

- Area: Remote Control
- Names: `cancel_async_message`
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Extensive variable/memo-slot renumbering in the Footer/model-picker component

Internal renumbering of memoization slots in the Footer/model-picker component, no visible behavior change

**Unclear.** Whether this renumbering accompanies any functional change is not established by the evidence.

**What**

The internal component that manages the footer, model switching, thinking-mode toggle, fast mode, and related dialogs (workflow panel, bash panel, model picker) had its internal memoization indexing renumbered. The visible logic and behavior appear the same as before.

**Why**

This looks like internal bookkeeping with no user-facing effect.

- Area: Elsewhere
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Cosmetic-looking diff in a deeply nested JSX conditional (symbol La)

A tiny internal diff in icon-rendering code with no apparent visible effect

**Unclear.** Whether this diff has any functional effect is not established by the evidence.

**What**

A small piece of internal rendering code for icon markup was rewritten, but the visible text and structure appear identical before and after.

**Why**

No user-facing effect is evident from this change.

- Area: Terminal Rendering
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### MCP task watcher module now lazily loaded via bun chunk

The MCP task watcher is now loaded lazily as its own bundled module

**What**

A helper function that needed the MCP (Model Context Protocol) task watcher now loads it lazily from its own bundled chunk, via an `mcpTaskWatcherModule()` export, alongside similar lazy-loaded modules already used for MCP client, auth, and SDK error classification.

**Why**

This is an internal loading-strategy change; loading the task watcher only when it's actually needed can help keep startup lighter, without changing what the watcher does.

- Area: MCP
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Curious no-op-looking .then() inserted into worktree detection telemetry chain

An extra pass-through step was added to the internal chain that reports git worktree detection timing

**Unclear.** The extra step returns its input unchanged, so it's unclear what purpose it serves or whether it has any visible effect.

**What**

The internal code path that measures how long git worktree detection takes (worktrees let you check out multiple branches of a repo at once) now runs one extra step before reporting the `tengu_worktree_detection` timing telemetry. This step reads the length of a list of results and then passes the list along unchanged.

**Why**

The step doesn't appear to alter the data, so this looks like an internal adjustment to how the timing is measured or logged rather than a change to worktree detection itself. It's not clear yet what purpose the extra step serves.

- Area: Git Internals
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

## Removed

### TaskOutput's output-length config knob is deprecated (tool removed)

TaskOutput tool removed; background task output is now read via the Read tool

**What**

The `TaskOutput` tool has been removed. A related configuration setting that used to control how much of a background task's output was returned inline is now marked deprecated and has no effect. To see a background task's output, use the `Read` tool on its output file instead.

**Why**

This consolidates how you inspect background task output: rather than a dedicated tool with its own length limit, you now read the output file directly with the general-purpose `Read` tool.

- Area: Background Tasks
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### TASK_MAX_OUTPUT_LENGTH removed from recognized settings list

The TASK_MAX_OUTPUT_LENGTH environment variable is no longer a recognized setting

**What**

`TASK_MAX_OUTPUT_LENGTH`, an environment variable that used to be recognized alongside other MCP and slash-command output-budget variables, was removed from that recognized list.

**Why**

`TASK_MAX_OUTPUT_LENGTH` had already been superseded by the `taskOutputMaxChars` setting in `settings.json`, which controls how much Task tool output Claude sees before it's truncated to a file; removing it from the recognized list means it's no longer treated as a valid way to configure that limit.

- Area: Background Tasks
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### TaskOutput removed from an internal tool set

The TaskOutput tool was pulled from an internal set of tools available to a Claude Code feature

**Unclear.** The finding does not say what effect losing access to TaskOutput from this specific tool set has for a user in practice.

**What**

An internal list of tools (the one used by Claude Code's task-management machinery, alongside Read, Glob, Grep, NotebookRead, Skill, AskUserQuestion, TaskCreate, TaskGet, TaskList, TaskUpdate, TaskStop, Agent and TodoWrite) no longer includes `TaskOutput`, the tool used to fetch a background task's output.

**Why**

This changes which tools are reachable from that internal set; it does not mean `TaskOutput` was removed from Claude Code, only that this particular list no longer grants access to it.

- Area: Background Tasks
- Names: `TaskOutput`
- Tier: You'll notice
- Useful: 2/5
- Signal: 1/5

### Background thread classifier drops "turn brief" summarization

Background thread classifier no longer produces its experimental "turn brief" summaries

**What**

The background classifier that generates recaps of project threads has had its "turn brief" summarization removed. It no longer computes this summary, no longer logs a `turnBrief` field on the `tengu_bg_classify` event, and no longer emits the separate `turn_brief` telemetry event.

**Why**

This rolls back a feature that had been added but was not yet fully wired up, cleaning up code and telemetry that were not being put to use.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Removed 'todo-list' onboarding tip

Removed the onboarding tip suggesting users ask Claude to make a todo list for complex tasks

**What**

Claude Code shows contextual tips and nudges to users. The tip suggesting that users ask Claude to create a todo list when working on complex tasks, to track progress and stay on track, has been removed from the list of tips shown.

**Why**

This tip will no longer appear as a suggestion, meaning one fewer onboarding hint about using todo lists surfaces to users.

- Area: Terminal UI
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5
