# Claude Code v2.1.267

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

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

This build carries 36 dormant additions, none of them switched on yet. The largest thread is around artifacts: a new asset store for uploading, listing, reading and deleting stored files, an "open" action to display an artifact without publishing it, and an "assets" capability now gated behind a cached per-account roster pulled from the server, alongside a rename of the artifact type catalog's override variable and internal flag. Subagents running in "auto" mode get a new SubagentHandback protocol for reporting back to their parent, but it stays behind an unread flag. Also waiting in the wings: a memory-context prefetch path gated by tengu_misty_anchor, a stable-address scheme for session IDs behind tengu_session_stable_address, a classifier check for plan-mode permissions, and an MCP passthrough-tool pipeline behind adoptMcpOverChannelSwitchOn.

Of 112 shipped changes, a few land as usable features today. The SubagentHandback tool referenced above is now live for delivering a subagent's final report to its parent, and hooks and plugins gain direct access to session usage stats plus the ability to read and write environment variables. A new scripting API, $.session.usage, exposes context, rate-limit and cost data, and the plugin API adds settings.read, env.get and env.set alongside renamed file actions. CLAUDE_CODE_MODEL_CAPABILITIES now lets you manually force model capability flags on or off, and the maxEffortLevel policy setting is enforced client-side, combining a global cap with per-model overrides across settings files.

Among 45 fixes, sending a message to a renamed session now correctly reports the rename instead of silently failing, and the availableModels setting validator no longer checks the wrong internal variables. Live-edit artifacts no longer automatically grant "version" permission alongside "sync," and artifact publish failures now surface directly in the publish panel with a reason. Policy checks for spawning agents and calling tools now restore fields a hook altered rather than just flagging them, and hook path-traversal validation now also covers a hook's "surface" file, not just its module file.

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

### New process.env read/write primitive for tools

New internal helpers let Claude read and set process environment variables

**Unclear.** Whether this is already exposed as a usable tool, or is unreleased backing code, is not stated.

**What**

New internal functions read a `process.env` variable by name, validate a name/value pair before writing (rejecting names containing `=` or NUL bytes, and rejecting non-string values), and set or delete a `process.env` entry (deleting it when the value given is undefined). This looks like the backing implementation for a capability that lets Claude get or set environment variables for the current process.

**Why**

If exposed as a tool, this would let Claude inspect or change environment variables directly rather than only through shell commands, with basic validation to reject malformed names or values.

- Area: SDK
- Names: `process.env`
- Tier: Use it now
- Useful: 5/5
- Signal: 5/5

### New SubagentHandback tool for subagent-to-parent reporting

New SubagentHandback tool lets a subagent deliver its final report to its parent, once

**What**

A new tool called SubagentHandback lets a subagent deliver its final report directly to the agent that spawned it. It can only be used once, as the subagent's very last tool call, and it is explicitly not a channel for progress updates along the way. The message must not be empty, and the tool only works if the agent has an active "handback contract" with a recorded recipient for the handback. Calling it a second time after a report was already delivered is refused.

Reports that are too long get compacted or summarized before delivery, and each report gets security-review framing, marked as blocked, refused, or unavailable as appropriate, before reaching the calling agent (whether that's the main conversation thread or a parent task).

**Why**

This gives subagents a formal, one-shot way to hand their finished work back to whoever spawned them, with safeguards so it can't be used for ongoing chatter and so oversized or risky reports are handled before they reach the caller.

- Area: Subagents
- Names: `SubagentHandback`
- Tier: Use it now
- Useful: 5/5
- Signal: 4/5

### Artifacts gain an asset store (upload/list/read/delete)

Artifacts with an assets capability now support uploading, listing, reading, and deleting stored files

**What**

The Artifact tool now documents four new actions for artifacts whose page declares an `assets` capability:

- `upload_asset` — push a local file into the artifact's asset store

- `list_assets` — enumerate what's stored

- `read_asset` — pull a stored file back down to disk

- `delete_asset` — remove a stored file

**Why**

This gives an artifact its own persistent file storage that Claude can manage directly, useful for artifacts that need to keep data, uploads, or generated files around between sessions rather than only living in the page itself.

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

### Async sub-agents gain a 'handback' mechanism for returning control to the parent

Async sub-agents can now explicitly hand control back to the agent that owns them

**What**

When Claude Code spawns an async sub-agent (a helper agent that runs in the background instead of blocking the conversation), it can now be given a `handbackOptIn`/`handbackTool` pair. This lets the sub-agent explicitly return control to its owning parent agent partway through, instead of only ever running to completion or being polled for status. The task registry that tracks these agents now also records a `handbackRecipient`, the agent that ownership is being transferred to.

**Why**

This is internal plumbing for coordinating async sub-agents. It means a sub-agent's lifecycle no longer has to end only in completion or polling, which opens the door to more flexible handoffs of control between an async worker and the agent that started it.

- Area: Subagents
- Names: `handbackOptIn`, `handbackTool`
- Tier: Use it now
- Useful: 4/5
- Signal: 4/5

### Hooks engine gains session.compact, session.receive, ui.resolve event contracts

The plugin hooks system adds validated event types for session compaction, session receive, and UI resolution

**Unclear.** What a session.receive or ui.resolve hook actually lets a plugin do isn't detailed beyond the validation rules.

**What**

Claude Code's plugin hooks engine now validates three new kinds of hook events:

- `session.compact`, for hooking into conversation compaction (summarizing older context to free up space)

- `session.receive`

- `ui.resolve`

A hook for `session.compact` must now return either `{ messages }` (a replacement set of messages) or `{ skip: reason }` to opt out, and the shape of `messages` is checked. Separately, a `provider` field on the arguments passed to `tool.describe`, `command.describe` and `agent.offer` hooks is now fixed and can no longer be overridden by a hook.

**Why**

These changes give plugins defined, checked contracts for reacting to compaction and other events, and stop a hook from spoofing which provider a tool or command claims to come from.

- Area: Hooks
- Names: `session.compact`, `session.receive`, `ui.resolve`
- Tier: Use it now
- Useful: 4/5
- Signal: 4/5

### New in-process plugin UI "surface" runtime (Box/Text/Button/Input/Select/Link/Code)

Plugins get a sandboxed UI toolkit with Box, Text, Button, Input, Select, Link, and Code elements

**What**

A new system lets plugins build interactive UI "surfaces" that run inside an isolated Node.js sandbox (a vm context, meaning the plugin's code runs separately from the main app for safety). It provides a fixed set of building blocks: `Box`, `Text`, `Button`, `Input`, `Select`, `Link`, and `Code`, along with state management, timers, and handlers for pointer and keyboard events. Whatever UI tree the plugin builds gets converted to plain JSON before it's sent to the host application, and is limited by strict budgets on node count, nesting depth, character length, and value size.

**Why**

This gives plugin developers a safe, constrained way to build rich interactive interfaces without letting plugin code run unchecked in the main application or send oversized data back to it.

- Area: Plugin UI
- Names: `Box`, `Text`, `Button`, `Input`, `Select`
- Tier: Use it now
- Useful: 4/5
- Signal: 4/5

### New plugin "surface" UI system for terminal-rendered plugin components ("Clients")

Plugins can now draw their own interactive UI elements ('Clients') directly in the terminal

**What**

Claude Code adds a new system that lets plugins mount custom terminal user-interface elements, called "Clients," declared through a `surface` field in the plugin's `hooks.json` file (hooks are scripts a plugin registers to run at certain points). This includes:

- A per-plugin rendering environment that handles mounting, unmounting, and resizing

- Mouse (pointer) and keyboard input handling

- Hover and focus tracking for UI elements

- A row-budget system that can refuse to render a dialog if it would take up too many terminal rows

- An asynchronous `ui.message` system for dispatching messages to a plugin's UI

**Why**

This gives plugin authors a real toolkit for building interactive terminal interfaces instead of plain text output, building on the earlier work that let plugins import configuration like `hooks.json` from other tools.

- Area: Plugin UI
- Names: `surface`
- Tier: Use it now
- Useful: 4/5
- Signal: 4/5

### New plugin execution environment kind: "native"

Plugins gain a new "native" execution environment alongside the existing same-thread one

**Unclear.** The finding doesn't say what kinds of plugins or use cases the native environment is meant to support.

**What**

Claude Code plugins run inside an execution environment. Previously there was one kind, running on the same thread as the app. Now there's a second kind called `native`, which runs on a native host process instead. Alongside it, a new `ui.resolve` remote call lets code wait for an environment's UI element tables to finish resolving, with a timeout so it doesn't hang forever.

**Why**

This expands where and how plugin code can execute, likely to support plugins that need to run outside the main app thread. The `ui.resolve` addition builds on the existing `ui.resolve` hook point, which was previously noted as one of the events a plugin module may hook into.

- Area: Plugins
- Names: `native`, `ui.resolve`
- Tier: Use it now
- Useful: 4/5
- Signal: 4/5

### Plugin/hook capability namespace gains session and env access

Hooks and plugins can now access session usage stats and read/write environment variables

**What**

The set of privileged operations available to hooks and plugins (extensions that can run custom code at certain points, or add new tools) has grown by four entries:

- `session.usage` — read session usage statistics

- `settings.read` — read settings

- `env.get` — read an environment variable

- `env.set` — set an environment variable

**Why**

This expands what hooks and plugins are permitted to do, letting them read settings and session usage data and manipulate environment variables, which previously were not accessible through this capability system.

- Area: Hooks
- Names: `session`, `env`
- Tier: Use it now
- Useful: 4/5
- Signal: 4/5

### SubagentHandback protocol for auto-mode subagents, gated off by default

Subagents running in 'auto' mode may need to report back via a new SubagentHandback tool instead of plain text, gated by an unread flag

**Unclear.** Nothing has been read yet about whether the `tengu_lively_waffle` flag that controls this is on or off by default.

**What**

A new mechanism called SubagentHandback can require a subagent running in "auto" mode to deliver its final report by calling a `SubagentHandback({message: ...})` tool, rather than simply ending its turn with plain text. When this is active, plain trailing text from the subagent is not delivered back to whatever called it. There's also reminder text shown when this requirement is turned on or off partway through a session.

This behavior only takes effect when the subagent is in "auto" mode and a second condition is also true. That second condition can be forced on or off with the environment variable `CLAUDE_CODE_SENDMESSAGE_HANDBACK`; if that variable isn't set, it falls back to a feature flag.

**Why**

Requiring a structured handback call instead of freeform trailing text makes it less likely that a subagent's final answer gets lost or garbled when passed back to its caller.

- Flag `tengu_lively_waffle`: Not enough to say (read for one account on one subscription tier against v2.1.267; this account: no value returned, anonymous baseline: no value returned, compiled default: on)
- Area: Subagents
- Names: `SubagentHandback`
- Tier: Nothing to try yet
- Useful: 4/5
- Signal: 4/5
- Present in the build but not switched on

### fable_5_mitigations gate can now explicitly turn off mitigations for claude-mythos-5

The fable_5_mitigations flag can now explicitly disable mitigations for claude-mythos-5, not just enable them

**What**

A model-safety helper used to always apply extra mitigations for the model id `claude-mythos-5`, no matter what the `fable_5_mitigations` feature flag said. Now, if that flag has any defined value from the server, including an explicit "off", that value is used instead. The old hardcoded behavior for `claude-mythos-5` only kicks in when the flag has no value at all.

**Why**

This lets the server turn mitigations off for `claude-mythos-5` when needed, instead of them always being forced on regardless of configuration.

- Area: Model Safety
- Names: `fable_5_mitigations`
- Tier: Under the hood
- Useful: 4/5
- Signal: 4/5

### New /insights (or similar) command gated by allow_insights policy

New /insights command, gated by an allow_insights policy, generates a report on your Claude Code usage

**What**

A new `/insights` command generates an HTML report analyzing your recent Claude Code sessions on this machine: which projects you work in, how you use Claude Code, where things go wrong, and features to try. It's controlled by a policy called `allow_insights` and is not available in cloud sessions.

**Why**

This gives users a way to review their own usage patterns and discover underused features, while administrators can control access to it via the `allow_insights` policy.

- Area: Insights
- Names: `/insights`, `allow_insights`
- Tier: Use it now
- Useful: 5/5
- Signal: 3/5

### New CLAUDE_CODE_MODEL_CAPABILITIES env var to override model capability flags

A new CLAUDE_CODE_MODEL_CAPABILITIES env var lets you manually force model capability flags on or off

**What**

A new environment variable, `CLAUDE_CODE_MODEL_CAPABILITIES`, lets you override which capabilities Claude Code thinks a given model supports. It takes a semicolon-separated list of rules in the form `modelPattern=flag1,-flag2,...`, where the model pattern can end with a trailing `*` to match multiple model IDs at once, and each flag is turned on by name or turned off by prefixing it with `-`.

**Why**

This gives advanced users and testers a way to manually correct or experiment with a model's detected capabilities without waiting for Claude Code to update its built-in capability data for that model.

- Area: Model Capabilities
- Tier: Use it now
- Useful: 5/5
- Signal: 3/5

### New scriptable session-usage API ($.session.usage)

A new scripting API, $.session.usage, exposes context, rate-limit, and cost data to plugins and scripts

**What**

A new function called `$.session.usage` is now available for scripting and plugin code. It returns details about the current session, including:

- context-window usage (how many tokens are used, the size of the window, and the percentage full)

- rate-limit windows (`five_hour`, `seven_day`, and `spend_limit`), each with a percent used and when it resets

- the current session's cost in US dollars

**Why**

This lets plugins and other scripts built on top of Claude Code read the same usage and cost figures Claude Code itself tracks, instead of guessing or parsing them from elsewhere. That makes it possible to build custom status lines, dashboards, or automations that react to how close a session is to its context or rate limits.

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

### Artifact 'assets' capability gated by cached org roster + a remote flag

Whether the artifact tool's 'assets' action is available is now decided by a cached per-account roster fetched from the server

**What**

Claude Code now fetches and caches, per account and organization, a "capabilities" roster from the server, and uses it to decide whether the artifact tool's schema includes the `assets` action. The order it checks is:

- the `CLAUDE_CODE_ARTIFACT_ASSETS` environment variable, if set, overrides everything

- otherwise, an internal flag, which defaults to off, is checked

- otherwise, it falls back to the cached or freshly-fetched roster from the server

Refreshing the roster fires an `artifact_roster_refresh` telemetry event.

**Why**

This lets the artifact 'assets' action be turned on for specific accounts from the server side, while still letting you force it on or off yourself with `CLAUDE_CODE_ARTIFACT_ASSETS`.

- Flag `tengu_cobalt_plinth_fennel`: Off in both readings (read for one account on one subscription tier against v2.1.267; this account: off, anonymous baseline: off, compiled default: on)
- Area: Artifacts
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 4/5
- Present in the build but not switched on

### Artifact feature: env var and gate renamed (artifact DB -> artifact type catalog)

The artifact type catalog's override variable and internal flag were renamed

**What**

An internal feature related to Artifacts (browsing published artifact types) had its override environment variable and internal feature flag renamed: `CLAUDE_CODE_ARTIFACT_DB` became `CLAUDE_CODE_ARTIFACT_TYPE_CATALOG`, and the underlying flag went from `tengu_umber_lattice` to `tengu_cobalt_plinth_larch`. Both still default to off unless a value is supplied.

**Why**

This is a naming cleanup for a feature that lets Claude browse and describe published artifact types to start new work from; the rename doesn't change whether the feature is on, only what it's called internally.

- Flag `tengu_cobalt_plinth_larch`: Off in both readings (read for one account on one subscription tier against v2.1.267; this account: off, anonymous baseline: off, compiled default: not a boolean we can read)
- Flag `tengu_umber_lattice`: On for this account, and not off by default (read for one account on one subscription tier against v2.1.267; this account: on, anonymous baseline: on, compiled default: not a boolean we can read)
- Area: Artifacts
- Names: `CLAUDE_CODE_ARTIFACT_TYPE_CATALOG`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 4/5
- Present in the build but not switched on

### Memory-context prefetch built but gated off by tengu_misty_anchor

A new memory-context prefetch path exists in code but stays off behind the tengu_misty_anchor flag

**What**

Claude Code now has code for a "memory context" prefetch step that runs early and records timing under `memory_context_fetch_ms` and `memory_context_boot_spillover_ms`. It only runs when several conditions all line up: the session was started from a remote cowork entrypoint (or the `SYSTEM_REMINDER_MEMORY_CONTEXT` environment variable is set), an account/session check passes, and the `tengu_misty_anchor` feature flag is on.

**Why**

The feature is built but not yet broadly active, so most users won't notice any difference until the flag is turned on for their account.

- Flag `tengu_misty_anchor`: Off in both readings (read for one account on one subscription tier against v2.1.267; this account: off, anonymous baseline: off, compiled default: on)
- Area: Memory
- Names: `SYSTEM_REMINDER_MEMORY_CONTEXT`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 4/5
- Present in the build but not switched on

### Hooks runtime dispatch generalized beyond same-thread execution

Hooks runtime dispatch reworked to support more than same-thread execution

**Unclear.** The finding shows the dispatch mechanism was generalized but does not say what new execution context or use case it now supports.

**What**

The internal function that builds the runtime interface for hook modules (custom code that runs at points in Claude Code) was changed from a single implementation built only for running in the same thread into a generic one. It now takes parameters for the kind of dispatch, how to copy and answer data, and how to create an environment, plus a new lookup surface and tracking of in-flight dispatches including their working directory and whether a turn is held.

**Why**

This generalizes how hooks are dispatched, laying groundwork for hooks to run in contexts other than the same thread, though the finding does not specify what new execution mode this enables.

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

### Artifact republish 'deadline' field — force older open viewers to stop

Artifacts can now set a deadline forcing older open copies to stop working

**What**

When republishing an Artifact (a generated file or app Claude Code produces, like a document or a small web app), you can now set a `deadline` value: `now`, `15m`, `1h`, `24h`, `7d`, or a specific timestamp. This tells any copies of the artifact that are already open in an older version when they must stop working.

Ordinary edits don't need this since updates already reach open viewers automatically. It's meant only for forcing old versions off. If more than one deadline gets set, the earliest one wins.

**Why**

This lets someone republishing an artifact cut off outdated, already-open versions on a schedule, which matters if an old version has a bug or should no longer be usable.

- Area: Artifacts
- Names: `deadline`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### Artifact republish gains a client-deadline mechanism and reserved preflight.js hook

Republishing an Artifact now supports a deadline for old copies and a reserved preflight.js hook that can block a bad publish

**What**

Republishing an Artifact now supports an optional `deadline` field, telling old, still-open copies of the artifact when to stop working. It accepts `now`, `15m`, `1h`, `24h`, `7d`, or a specific ISO UTC time. Deadline declarations accumulate across republishes, and the earliest one set always wins. This applies only to republishes, not first-time publishes.

Separately, a file named `preflight.js` at the root of an artifact is now reserved for a special purpose: when updates are published, it runs against pages of the artifact that are currently open. It must be an ES module (a small, self-contained piece of JavaScript) no larger than 8 KiB, with a function as its default export, or the publish is refused.

**Why**

The deadline gives control over how long old copies of an artifact stay usable after an update, useful for phasing out a version cleanly. The `preflight.js` hook lets an artifact run a check against its own open pages before an update goes live, catching problems before they reach users, but its strict size and format limits mean it needs to be written carefully or the publish will simply be rejected.

- Area: Artifacts
- Names: `deadline`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### Compaction can now be intercepted and rewritten by a session.compact plugin hook

A new `session.compact` plugin hook can intercept and rewrite conversation compaction

**What**

Both of Claude Code's compaction paths, live (reactive) compaction and precomputed background compaction, now route through a shared step that first runs a `session.compact` plugin hook before falling back to the built-in compactor. If a hook supplies replacement messages, those are used directly; if a hook rewrites content after a background precompute has already run, the stale precomputed result is discarded and logged.

This comes alongside two other new hookable points:

- `session.receive`, which lets a hook intercept and rewrite incoming text before it's queued to the session, including fully consuming a message so it's never queued

- `skill.prompt`, a newly defined hook point

**Why**

This gives plugins real control over how and what gets compacted, instead of only observing it, and the discard-and-log behavior keeps stale precomputed summaries from silently overriding a hook's intent.

- Area: Compaction
- Names: `session.compact`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### Function-hook execution now supports a per-hook .catch handler and 'fail closed' recovery

Hooks can now supply a .catch handler to recover instead of failing closed

**What**

When a hook (custom code that runs at specific points in Claude Code) throws an error or times out, the dispatch system now checks whether the hook supplied its own `.catch` handler. If it did, a new recovery path runs that handler and can use the answer it returns as the hook's final result, rather than simply failing. This is logged as "hook failed closed: ... (its .catch answered)" and reported through telemetry with a reason and a flag for whether the hook overran its time limit. A new "caught" outcome is now recorded for hooks handled this way.

**Why**

This lets hook authors define custom recovery behavior for failures or timeouts instead of the hook simply failing closed, giving more control over how errors in custom hooks are handled.

- Area: Hooks
- Names: `.catch`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### Hooks plugin API gains a 'to' messaging primitive, 'surface' concept, and table resolution

Hooks/plugin runtime gains a 'to' messaging function, a 'surface' concept, and table-resolution requests

**Unclear.** What concrete new plugin/hook capabilities this enables, and what a 'surface' or 'table' represents here, isn't explained.

**What**

Claude Code's hooks and plugin runtime API has been expanded in several related ways:

- Hook manifests can now declare a `surface`, carried alongside each module's specification

- The internal hook-call wrapper gains a `to` function and a `caught` handler, in addition to its existing call/signal/event/origin/trace parts

- A new `resolveTables`/`resolve` message type lets a hooks worker request table resolution and get back a `resolved` or `resolve_error` response

- Internal environment-state tracking gained new `framing` and `resolving` maps

- Error text shown to plugin authors now references `next.to always next.to(e, "<tier>")`

**Why**

This extends what a hook or plugin can do at runtime, including sending messages via `to` and resolving tables, though the finding does not describe the specific new capabilities these enable for plugin authors.

- Area: Hooks
- Names: `to`, `surface`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### MCP tool declarations gain hints and richer annotation limits (search_hint, always_load, max_result_size_chars, requires_user_interaction)

MCP tools can now declare hints like search_hint, always_load, and a maximum result size, alongside existing annotations

**Unclear.** What Claude Code does with each hint once declared isn't shown, only that the schema now accepts them.

**What**

Tools provided through MCP (Model Context Protocol, the standard Claude Code uses to talk to external tool servers) can now include a `hints` object when they declare themselves, with the fields:

- `search_hint`

- `always_load`

- `max_result_size_chars`

- `requires_user_interaction`

These sit alongside the existing annotations like `title`, `readOnlyHint`, `destructiveHint` and `openWorldHint`. Tool names must still contain a double underscore (`__`) and pass a name-validity check.

**Why**

These hints give an MCP server more ways to tell Claude Code how a tool should be surfaced and used, such as whether it should always be loaded or how large a result it's allowed to return.

- Area: MCP
- Names: `search_hint`, `always_load`, `max_result_size_chars`, `requires_user_interaction`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### New --use-anthropic-git-proxy runner opt-in

New `--use-anthropic-git-proxy` flag lets self-hosted runners opt into Anthropic-managed git

**What**

Self-hosted runner registration now accepts a `--use-anthropic-git-proxy` flag. When set, the runner logs that it's opting into Anthropic-managed git and passes that choice to the server as part of registration. If the server can't provide governed git for the session even though the flag was set, Claude Code now warns and falls back to the older, deprecated clone-URL proxy.

**Why**

This gives runner operators an explicit opt-in to the newer, server-managed git handling, while making the fallback behavior visible instead of silently reverting to the deprecated proxy. It builds on the earlier `--use-anthropic-git-proxy` flag, which routed clones through Anthropic's git proxy using a repo-local credential helper.

- Area: Self-Hosted Runner
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### New CCR_AGENT_PROXY_NO_PROXY_LOCAL_ONLY env var for the agent proxy

New CCR_AGENT_PROXY_NO_PROXY_LOCAL_ONLY environment variable narrows the agent proxy's no-proxy list to local addresses

**What**

A new environment variable, `CCR_AGENT_PROXY_NO_PROXY_LOCAL_ONLY`, can be set to make the agent proxy (which routes network requests, potentially through a corporate proxy) bypass the proxy only for local addresses, instead of using its broader default lists of addresses to exclude. It also affects whether the proxy's certificate bundle is treated as covering every host.

**Why**

This gives more precise control over which traffic skips the configured proxy, useful in environments where only local traffic should bypass it.

- Area: Internals
- Names: `CCR_AGENT_PROXY_NO_PROXY_LOCAL_ONLY`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### New agent.list-style listing of local agents and in-process teammates

Internal listing of local agents and in-process teammates gains richer detail

**What**

A new internal function enumerates every entry in the task registry (the internal bookkeeping list of running agents) and classifies each one as either a `local_agent` (with its id, type, and parent agent id) or an `in_process_teammate` (with its id and name). The resulting list also includes each entry's status, which agent spawned it, and a resolved display name. This appears to be the implementation behind an `agent.list`-style listing.

**Why**

This gives a more complete and structured view of what agents and teammates are currently active, which matters for anything that needs to inspect or manage multiple running agents at once.

- Area: SDK
- Names: `agent.list`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### New hover styling support for plugin-rendered Box/Text/Button UI

Plugin-drawn boxes, text and buttons can now define hover styles, and a new Client element renders client-side modules

**What**

Plugins that draw their own UI using Box, Text and Button elements can now specify a `hover` style that swaps in different colors or layout while the element is hovered, restricted to an allow-list of properties specific to each element type (for example `borderStyle` and `backgroundColor` for a Box). Separately, a new `Client` element type lets a plugin render a client-side module with its own export name, props, width, height and flex-grow behavior.

**Why**

These give plugin authors more expressive, interactive UI, letting elements react to hovering and letting more complex client-rendered components appear inside a plugin's interface.

- Area: Plugin UI
- Names: `hover`, `Client`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### New plugin/hook capability scopes: session.usage, settings.read, env.get, env.set

Plugins and hooks gain new permission scopes: session.usage, settings.read, env.get, env.set

**What**

The list of permission scopes available to plugins and hooks has grown four new entries:

- `session.usage`

- `settings.read` — read settings by their source

- `env.get` — read environment variables

- `env.set` — write environment variables

All four are fully implemented with working check and run logic, not just declared.

**Why**

This gives plugins and hooks documented, permission-gated ways to read session usage data, read settings, and read or write environment variables, capabilities that previously weren't available as distinct, controllable scopes.

- Area: Hooks
- Names: `session.usage`, `settings.read`, `env.get`, `env.set`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### New policy setting: maxEffortLevel

New managed-settings keys maxEffortLevel and secDefault added as policy-restrictive settings

**Unclear.** What secDefault itself configures is not stated in the finding.

**What**

Two new keys were added to the list of managed settings that organizations can restrict:

- `maxEffortLevel`, which caps the effort level for models and uses the effort-level enum as its set of restrictive values

- `secDefault`, marked as a security-restrictive setting

**Why**

`maxEffortLevel` lets an organization cap the effort level used for every model, or per model, across every provider, rather than leaving it fully open to whatever a person chooses. `secDefault` being added to the restrictive-settings list means it can now be locked down by organization policy as well.

- Area: Effort
- Names: `maxEffortLevel`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### Per-model "maxEffortLevel" cap now enforced client-side across settings

maxEffortLevel now combines a global cap with per-model overrides across all settings files and clamps any explicit effort request

**What**

`maxEffortLevel` caps the reasoning [effort level](/docs/en/model-config#adjust-effort-level) Claude Code can use. Claude Code now computes the effective cap by combining a top-level `maxEffortLevel` with per-model overrides set under `modelSettings.<model>.maxEffortLevel`, taking the lowest applicable value across all loaded settings files. Any explicit request for an effort level, whether from `/effort`, `/model`, `--effort`, the `CLAUDE_CODE_EFFORT_LEVEL` environment variable, or a model's default, is clamped to this computed cap.

**Why**

This ensures an effort cap set anywhere, globally or for a specific model, and in any settings file, is consistently enforced no matter how the effort level is requested, closing gaps where a per-model or lower-priority cap could previously be bypassed.

- Area: Effort
- Names: `maxEffortLevel`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### Plugin API gains fs.read/write/list rename plus new settings.read, env.get, env.set

Claude Code's plugin API renames its file actions and adds settings.read, env.get and env.set

**What**

The API that plugins use to interact with Claude Code has been updated:

- `fs.readFile` is renamed to `fs.read`

- `fs.writeFile` is renamed to `fs.write`

- `fs.listDir` is renamed to `fs.list`

- `settings.read` is added, returning merged settings from a named source

- `env.get` and `env.set` are added

**Why**

The shorter file-action names make the plugin API more consistent, and the new settings and environment-variable actions give plugins direct ways to read configuration and manage environment variables without workarounds.

- Area: Plugins
- Names: `fs.read`, `fs.write`, `fs.list`, `settings.read`, `env.get`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### Plugins can now trigger manual conversation compaction

Plugins can now trigger manual conversation compaction with custom instructions

**What**

A new `compactConversation` method lets a plugin ask Claude Code to compact (summarize and shrink) the current conversation, supplying its own custom instructions for how to do it. It's blocked for thin-client and remote sessions and while a turn is already in progress, and requests made this way are tagged with `trigger: "plugin"` for telemetry.

**Why**

This gives plugin authors a way to proactively manage conversation length instead of waiting for automatic compaction, while the guardrails and tagging keep it from interfering with active turns or unsupported session types.

- Area: Compaction
- Names: `compactConversation`
- Tier: Use it now
- Useful: 4/5
- Signal: 3/5

### 'Security default' (secDefault) plugin: isolates classic hooks/settings from user-installed plugins

New built-in 'Security default' plugin shields org hooks and settings from user-installed plugins

**What**

Claude Code now includes a new built-in, policy-only plugin called 'Security default'. On managed machines belonging to Team or Enterprise organizations, it's automatically seated outermost wherever hooks (custom scripts that run at certain points) modules can load, unless the managed `secDefault` setting is explicitly set to `false`. It keeps the organization's classic hooks, prompt content, settings, and tool policy out of reach of user-installed plugins, without adding any policy of its own. Plugin enablement more generally now supports an `enabledFromPolicyOnly` mode, read only from `policySettings`.

**Why**

This stops a user-installed plugin from being able to interfere with or override an organization's own hooks, settings, and tool policy, strengthening the isolation between organization-managed configuration and plugins a user adds themselves.

- Area: Plugins Security
- Names: `secDefault`, `enabledFromPolicyOnly`
- Tier: You'll notice
- Useful: 4/5
- Signal: 3/5

### New auto-detected PostToolUse hook offers to connect GitHub after a push or PR create

Claude Code can now offer to connect GitHub to claude.ai right after you push or open a pull request

**Unclear.** Which accounts see this offer, and whether it's currently switched on for any of them, isn't known since the related settings haven't been read yet.

**What**

After a `git push` or a pull request is created through Claude Code, a new internal hook (a handler that runs after a tool call, here after `Bash`-style commands) checks the result and, when conditions are met, shows a prompt: "Pushed to GitHub. Connect GitHub to claude.ai so you can work on this repo even when this machine is offline?"

**Why**

This offers a quick way to link your GitHub account to claude.ai so you can keep working on the same repository from the web even when your own machine is off, right at the moment it would be useful.

- Area: GitHub Integration
- Tier: You'll notice
- Useful: 4/5
- Signal: 3/5

### New artifact tool action: "open"

Artifacts tool gains an "open" action to display an existing artifact without publishing it

**What**

The artifacts tool now supports an `action: "open"`, which shows the user an existing artifact by its url without creating or publishing anything new. This is gated behind a schema flag, and the tool's prompt now includes a paragraph explaining how to use it: pass `action: "open"` along with the artifact's `url`.

**Why**

This gives Claude a way to surface an existing artifact to the user on its own, separate from the act of publishing or editing one.

- Area: Artifacts
- Names: `action: "open"`
- Tier: Nothing to try yet
- Useful: 4/5
- Signal: 3/5
- Present in the build but not switched on

### Agent tool completion gains a 'handback' delivery mechanism

Agent tool completion adds a 'handback' mechanism to deliver results to the calling agent

**What**

When an agent tool (a subagent spawned to do a task) finishes, the code that finalizes its result now supports a "handback": a way of delivering the subagent's outcome back to whoever spawned it. It works out whether the handback should be sent, flagged, or withheld, appends a message describing the outcome to the returned content, and logs a new telemetry event (`lively_waffle`) noting whether delivery happened or was flagged. The final result now includes a `handback` field when one applies.

Relatedly, the code that spawns synchronous and asynchronous agent tools now threads new `handback`, `handbackOptIn`, and `handbackTool` concepts through the agent's metadata and results, and the tool sets resolved for sub-agents now include a `machineMcpTools` list alongside the normal MCP tool list.

**Why**

This builds a formal path for a subagent to report its outcome back to its parent agent, with explicit control over whether that report is delivered, flagged for review, or withheld.

- Area: Subagents
- Names: `handback`
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### Hooks engine: async hook handlers can now register a .catch(handler)

Async hook handlers can now attach a .catch(handler) to react to a failed downstream call

**What**

The system plugins use to hook into Claude Code's behavior now lets an asynchronous hook registration chain a `.catch(handler)` onto itself, giving hook authors a way to respond when a downstream call times out or errors, instead of the failure simply being thrown.

**Why**

This gives plugin developers a way to gracefully handle a failure in their hook rather than crashing the operation it's attached to. Hooks created with `engine.create` are the exception: they have no grace budget, and `.catch` doesn't apply to them, since their failure always fails the load.

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

### Inbound message ingestion (bridge and CLI stdin) now runs through a session.receive plugin hook

Incoming messages from both Remote Control and the CLI now pass through a `session.receive` plugin hook before being queued

**What**

Both the Remote Control bridge's inbound-message path and the main CLI's stdin/user-message loop now run incoming messages through the `session.receive` plugin hook before turning them into a queued prompt. If the hook reports the message as consumed, it's dropped before being enqueued instead of being added to the conversation.

**Why**

This lets plugins intercept and act on incoming messages from either entry point, consistently, before they ever reach the conversation queue.

- Area: Hooks
- Names: `session.receive`
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### Managed-settings-only `secDefault` flag controls seating of the bundled sec-default plugin

A new managed-settings-only flag lets organizations put their bundled sec-default plugin ahead of user-installed plugin hooks

**What**

A new settings field, honored only when set in managed settings (not user, project, local, or `--settings`), controls whether the organization's bundled "sec-default" plugin takes the outermost seat in the chain of plugin hooks, ahead of any plugins listed in `prependPlugins`.

**Why**

This keeps things like classic hooks, prompt content, managed settings, and tool policy protected from being overridden by plugins that users install themselves, since only an administrator setting managed settings can control this placement.

- Area: Plugins Security
- Names: `secDefault`
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### New "ui.message" event added to a second, larger capability/event list

A broader UI/agent event list now includes a ui.message event

**Unclear.** The finding does not say what consumes this event list or what user-visible behavior, if any, depends on it.

**What**

A second, larger internal list of UI and agent events that Claude Code tracks now includes `ui.message`, joining `ui.render`, `ui.resolve`, `ui.press`, `ui.input`, and `ui.select`.

**Why**

This is internal plumbing that expands the set of events the app can recognize and react to. It does not by itself change what you see, but it lays groundwork for features that need to respond to message-related UI activity.

- Area: Plugin UI
- Names: `ui.message`
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### New workflow keyword-trigger setting tracked via a settings change-log abstraction

Settings toggles like verbose mode and a new keyword-trigger option now go through a unified change-log system

**Unclear.** The finding doesn't say what `ultracodeKeywordTrigger` does or how a user would use it.

**What**

Several settings toggles, including `verbose`, `permissionMode`, Fast mode, Default view, and a new `ultracodeKeywordTrigger` setting, are now updated through one shared change-log object with `record`, `toggle`, and `clear` methods, instead of each being updated with its own separate code.

**Why**

This is mainly an internal cleanup that makes settings changes more consistent and easier to track, and it surfaces a new `ultracodeKeywordTrigger` setting related to triggering workflows by keyword.

- Area: Settings
- Names: `ultracodeKeywordTrigger`
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### Plugin hook modules gain a resolved 'tier' controlling next.to() ordering

Plugin hooks can now be assigned a resolved ordering tier that next.to() calls are validated against

**What**

When a plugin's hooks module (code that runs at defined points in Claude Code's workflow) is loaded, it's now assigned a resolved "tier" of `prepend`, `builtin`, `user`, or `append`, based on the plugin's storage id and whether it's in the managed prepend or append lists. Any `next.to("<tier>")` call inside the hooks module, used to route to the next hook in a specific tier, is now validated against this: it throws an error if the plugin isn't managed, or if the named tier doesn't actually come next in the chain.

**Why**

This catches misconfigured or invalid hook ordering at load time rather than letting a plugin's `next.to()` call silently do the wrong thing, building on the recent handling of conflicting managed-plugin ordering.

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

### hooks.json can now declare a `surface` module

hooks.json can now declare a separate 'surface' module for drawing a hook module's UI elements

**What**

A plugin's `hooks.json` configuration file can now include an optional `surface` field, naming a module (a code file separate from the main hooks module) whose job is to render the hooks module's `Client` UI elements onto a display surface. This field requires the `modules` field to also be present, and its format is checked by a new validation rule: it must be a path relative to the `hooks.json` file and cannot start with `$`.

**Why**

This gives plugin authors a way to separate the code that renders UI elements from the main hooks logic, which is useful for plugins that need to show their own interface elements.

- Area: Plugins
- Names: `surface`
- Tier: Use it now
- Useful: 3/5
- Signal: 3/5

### New '/web-setup' prompt banner tied to input-band state

A new banner in the prompt area can launch the /web-setup command

**What**

A new banner element has been added above the input prompt, alongside the existing survey and feedback banners. It can run the `/web-setup` slash command, which connects your GitHub account to Claude Code on the web using your local `gh` CLI credentials, and submits it with a mode override that puts the input in prompt mode. The banner also tracks a combined "held" state so it coordinates with the survey banner and other above-prompt elements to avoid showing at the same time.

**Why**

This surfaces the GitHub connection setup for Claude Code on the web directly in the terminal prompt area, making it easier to discover and start without hunting for the command.

- Area: Slash Commands
- Names: `/web-setup`
- Tier: Use it now
- Useful: 4/5
- Signal: 2/5

### Artifact database write_db batches now support per-entry version pins

Artifact database batch writes support version pins per individual entry

**What**

Batched writes to an artifact's database (the `write_db` tool with a batch operation) can now pin an expected version (`ifVersion`) on each individual entry in the batch, not just one pin for the whole batch. A new check throws an error, "this batch no longer lists the writes that were approved (entries were added or removed)," if the number of entries in the batch changed after it was approved.

Relatedly, the write-permission gate now also triggers whenever any entry in the batch carries an `ifVersion`, and the internal audit record for a batch write now includes the list of per-entry pins alongside the previous single overall pin.

**Why**

This prevents a batch write from silently going through if its contents changed after approval, and lets version checks be enforced per-entry rather than only across the whole batch.

- Area: Artifacts
- Names: `ifVersion`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### Connector suggestion (search/lookup) gated behind org policy

Connector search and lookup suggestions now require an org policy to allow them

**What**

A new guard function blocks 'Connector search' and 'Connector lookup' operations (suggesting connectors, i.e. integrations with external services) unless an organization's `allow_connector_suggest` policy setting permits it. When blocked, it reports one of several specific denial reasons: `policy_denied`, `policy_mirror_unregistered`, `policy_route_missing`, or `policy_cache_miss`.

**Why**

This lets organizations control whether Claude Code is allowed to suggest connectors to users, with specific error reasons to help diagnose why a suggestion was blocked.

- Area: Connectors
- Names: `allow_connector_suggest`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### MCP tools can now declare a per-tool result-size cap via _meta

MCP tools can now declare their own result-size cap and other behavior via metadata

**What**

An MCP (Model Context Protocol, the standard Claude Code uses to connect external tools) tool's manifest can now set several behaviors through `_meta` fields:

- `anthropic/maxResultSizeChars` overrides the tool's default maximum result size, up to an internal ceiling

- `anthropic/requiresUserInteraction` forces a permission prompt before the tool runs

- `anthropic/alwaysLoad` forces the tool to always be loaded

- `anthropic/searchHint` (or `promptOverrides.search_hints`) supplies a searchable hint string for the tool

**Why**

This gives MCP tool authors finer control over how their tools behave in Claude Code, such as allowing larger results when needed, requiring explicit confirmation, or improving discoverability, without relying only on Claude Code's built-in defaults.

- Area: MCP
- Names: `_meta`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### New compliance policy: allow_stats_transcript_scan

A new policy can block the Usage stats view for HIPAA-regulated organizations

**What**

A new compliance policy, `allow_stats_transcript_scan`, controls whether the "Usage stats" breakdown is shown. This view is built by scanning session transcripts (records of your conversations) saved locally. The policy joins two existing ones, `allow_usage_transcript_scan` and `allow_skill_doctor_transcript_scan`, and is blocked by default for organizations under HIPAA (healthcare privacy regulation).

**Why**

Scanning local transcripts to build usage statistics could expose sensitive information, so organizations subject to healthcare privacy rules now have this specific view disabled rather than left on by default.

- Area: Compliance
- Names: `allow_stats_transcript_scan`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### New generic pointer-event API for alt-screen UI components (hover/drag/press/release)

Full-screen terminal panes gain a generic pointer API for hover, drag, press and release

**What**

Claude Code's full-screen ('alt-screen') terminal components can now respond to mouse pointer events directly: hovering, dragging, pressing, and releasing, in addition to the selection and click handling that already existed. A new internal mechanism walks the interface's component tree to find and call the right component's own pointer handler.

**Why**

This is groundwork that lets interactive full-screen panes handle mouse interactions themselves, rather than relying only on click and selection events, opening the door to richer mouse-driven UI elements.

- Area: Plugin UI
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### New pointer/mouse press event class for plugin UI

Internal plugin UI code gained a class for tracking mouse/pointer press details

**What**

A new internal class captures details of a pointer or mouse press for use by plugin user-interface code: the press type, column and row position (both global and local to the element), which button was pressed, and whether shift, alt, or ctrl were held.

**Why**

This is internal plumbing that supports building interactive plugin UI elements that respond to mouse clicks; it isn't something a reader configures directly.

- Area: Plugin UI
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### Plugin event schema gains a `usage` field on turn.step and turn.complete

Plugin turn.step and turn.complete events now include token usage details

**What**

The event data Claude Code sends to plugins and hooks for `turn.step` and `turn.complete` now includes a `usage` field with token counts: input, output, cache-read, and cache-creation tokens, plus the model used. This is pulled from the assistant's message.

**Why**

Plugins and hooks listening for these events can now see token usage per turn without having to compute it themselves, useful for anything that tracks or reports on cost or usage.

- Area: Hooks
- Names: `usage`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### Self-hosted runner CLI gains git-routing and drain-wait flags

Self-hosted runner adds git URL-rewriting flags and an Anthropic-managed git auth option, plus a documented drain-wait timeout

**What**

The self-hosted runner's command-line help now documents several new options:

- `--git-ssh-rewrite <host>` rewrites git remote URLs for hosts that only support SSH access

- `--git-host-rewrite <f>=<t>` rewrites git remote URLs for split-horizon DNS setups (where internal and external names for the same host differ)

- `--use-anthropic-git-proxy` lets Anthropic manage git authentication on the server side, using the session creator's GitHub OAuth token or, for bot and agent sessions, the organization's GitHub App token, instead of the runner needing its own git auth configuration

- `SELF_HOSTED_RUNNER_DRAIN_WAIT_MS` is now documented, controlling how long the runner waits before sending SIGTERM during shutdown (default 0, meaning immediate; maximum 86400 milliseconds), with `--drain-wait-bg-tasks-sec` kept as a deprecated alias

**Why**

The new git-rewrite flags make it easier to run the runner against hosts with unusual networking or access setups, and `--use-anthropic-git-proxy` removes the need to configure git credentials on the runner itself. The documented drain-wait setting gives operators explicit control over shutdown timing.

- Area: Self-Hosted Runner
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### session.compact implementation gated by DISABLE_COMPACT

session.compact now blocks itself while DISABLE_COMPACT is set or a turn is still running

**What**

The underlying implementation behind `session.compact` (used by `/compact` and by plugins) now explicitly refuses to run in two cases: when compaction has been switched off for the session via `DISABLE_COMPACT`, or when a turn is currently in progress, since compaction is only allowed to happen between turns.

**Why**

This prevents `/compact` and plugin-triggered compaction from running at an unsafe time or when it's been deliberately disabled, giving a clear error instead of unexpected behavior.

- Area: Compaction
- Names: `DISABLE_COMPACT`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### write_db batch entries can now pin an individual document version

write_db batch writes can now require specific documents to be at an exact version before committing

**What**

Each entry in a `write_db` batch operation (which commits several document writes together under one approval) can now include an `if_version` value. This tells Claude Code the entry should only be written if the target document is still at that exact version. If any pinned document has changed since it was last read, the entire batch is rejected and no writes happen, and the error names which entry failed and what version the document is actually at.

**Why**

This protects against overwriting changes made by someone or something else in between reading a document and writing it back, by making the batch fail cleanly instead of silently clobbering newer data.

- Area: Artifacts
- Names: `if_version`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### write_db batch writes now support `if_version` optimistic-concurrency checks

Document-store batch writes now support if_version checks per entry, with a permission check when used

**What**

The document-store's batch write path now accepts an `if_version` value on each individual write within a batch (previously this was rejected outside of batches and not passed through at all). Passing `if_version` (the document's last-read version) on a write means the write does nothing if the document has changed since it was read. If any write in a batch specifies `if_version`, Claude Code now runs an extra approval check before sending the batch. The tool's description was also expanded so every write type, `set`, `update`, `str_replace`, and `delete`, as well as each batch entry, documents that it can carry `if_version`.

**Why**

This lets Claude safely avoid overwriting a document that changed since it was last read, across all write types and within batched writes, rather than only on single `update`/`str_replace` calls as before.

- Area: Artifacts
- Names: `if_version`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### write_db now supports a 'delete' db_op with if_version

The write_db tool can now delete database entries, and set/delete support an ifVersion check

**What**

The `write_db` tool's `db_op` parameter now accepts 'delete' in addition to the existing 'set', 'update', and 'str_replace' operations. The 'delete' and 'set' operations can also pass through an `ifVersion` constraint when one is provided.

**Why**

This lets database writes remove entries outright, not just create or modify them, and the `ifVersion` constraint allows a set or delete to be made conditional on the entry still being at an expected version, guarding against overwriting or deleting data that changed since it was last read.

- Area: Artifacts
- Names: `delete`, `ifVersion`
- Tier: Use it now
- Useful: 3/5
- Signal: 2/5

### Confirm-clear message cache markers option added to compaction

Conversation compaction gained a skipMessageCacheMarkers option

**Unclear.** It's unclear what a cache marker on a message does or when skipping it would matter to a user.

**What**

The core function that compacts and summarizes long conversations now accepts a new option, `skipMessageCacheMarkers`, which defaults to off and is passed through to the underlying compaction logic.

**Why**

This gives internal callers finer control over compaction behavior, specifically whether cache markers on messages are skipped, though the finding doesn't say which situations use this option or what visible effect it has.

- Area: Compaction
- Names: `skipMessageCacheMarkers`
- Tier: Use it now
- Useful: 2/5
- Signal: 2/5

### MCP passthrough tool allowlist raised from 256 to 1024 entries; entries can carry annotations/hints

MCP passthrough tool lists can now hold up to 1024 tools instead of 256, and can carry annotations/hints

**What**

Claude Code forwards its MCP (Model Context Protocol) tools to worker processes using an internal "passthrough" list. That list's limit was raised from 256 entries to 1024, so setups with a very large number of MCP tools no longer hit the old cap. Each entry in the list can also now carry optional `annotations` and `hints` fields.

**Why**

Users connecting many MCP servers with lots of tools were previously capped at 256 forwarded tools; the higher limit removes that ceiling for larger tool setups.

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

### New pane-resize keybindings: ctrl+x + arrows

New ctrl+x+arrow keybindings grow or shrink plugin panes in the terminal UI

**What**

Four new keyboard shortcuts were added to the terminal keymap:

- `ctrl+x left` and `ctrl+x up` trigger `pane:grow`, widening or heightening a plugin pane

- `ctrl+x right` and `ctrl+x down` trigger `pane:shrink`, narrowing or shortening a plugin pane

These map to two new pane commands, `pane:grow` and `pane:shrink`.

**Why**

This gives keyboard control over resizing plugin panes directly, without needing another way to adjust their size.

- Area: Terminal UI
- Tier: Use it now
- Useful: 3/5
- Signal: 1/5

### New pane resize keybinding actions: pane:grow / pane:shrink

Two new keybinding actions added for resizing panes: pane:grow and pane:shrink

**What**

The list of recognized keyboard shortcut actions now includes `pane:grow` and `pane:shrink`, alongside the existing pane navigation actions like `pane:pageDown`, `pane:top`, and `pane:bottom`.

**Why**

This makes it possible to bind keys to resize panes, in addition to the existing ability to navigate between them.

- Area: Terminal UI
- Names: `pane:grow`, `pane:shrink`
- Tier: Use it now
- Useful: 2/5
- Signal: 1/5

## Improvements

### HIPAA compliance taint now 'latches' and permanently disables Artifacts/Remote Control for the session

Once a HIPAA-regulated organization signs in during a session, Artifacts and Remote Control now stay disabled for the rest of that session

**What**

Claude Code now permanently records, for the rest of a session, the fact that a HIPAA-regulated organization was signed into at any point during it, even if the server's current policy check later stops reporting that restriction. With this recorded, both Artifacts and Remote Control show a message explaining they're disabled and that you need to restart Claude Code to have the restriction re-evaluated.

**Why**

This stops a session from re-enabling HIPAA-restricted features like Artifacts or Remote Control mid-session just because a later status check happened to miss the restriction, keeping it consistently enforced.

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

### Effort level can now be set per-turn, not just per-session

Effort level can now be overridden for a single turn instead of only for the whole session

**What**

The internal logic that determines the effort level (how much reasoning effort a model applies) now accepts a `turnEffort` value that, when the current model supports it, takes priority over the session-wide setting for that turn. This also feeds into the status line text that shows "with X effort."

**Why**

This allows effort level to be adjusted for an individual turn rather than only being set once for the whole session, giving finer control over how much reasoning effort is applied at any given moment.

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

### Session can now run with built-in tools entirely disabled, and plugins are blocked from adding tools in that mode

Sessions can now run with all built-in tools disabled, and plugins are blocked from adding tools back in that mode

**What**

When `--allowedTools` is given but doesn't match any known built-in tool, Claude Code now recognizes this as a session with built-in tools entirely disabled, and passes that state through its permission logic. Plugins are explicitly blocked from registering any of their own tools in that case.

**Why**

This closes a gap where a session set up to disable all built-in tools (via `--tools ""`) could still end up with tools available if a plugin added its own, ensuring the restriction is fully enforced.

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

### New 'latched' transient-denial state for HIPAA-gated policies

A new 'latched' policy state marks a lingering HIPAA restriction from a prior organization

**What**

Remote Control, the org-policy check, and the general settings-restriction check now recognize a new policy status called 'latched', separate from the existing `org_denied`, `unregistered`, and `route_missing` statuses. It's described as a transient HIPAA (a healthcare data privacy regulation) restriction left over from an earlier organization, which gets re-evaluated when the session respawns.

**Why**

This lets Claude Code correctly distinguish a temporary leftover restriction from an earlier organization from a genuine, ongoing policy denial, so the two aren't confused when a session switches organizations.

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

### HIPAA org policy 'latch': once a HIPAA-regulated org has signed in, restricted features stay disabled for the rest of the session even after switching accounts

Once a HIPAA-regulated org signs in, restricted features stay off for the rest of the session even after switching accounts

**What**

Claude Code now enforces a session-wide 'latch' for HIPAA-regulated organizations: once you've signed in to a HIPAA-regulated organization, certain restricted features become disabled and stay disabled for the rest of that session, even if you later switch to a different, non-HIPAA account. The only way to re-enable them is to restart Claude Code.

**Why**

This prevents a session from carrying over HIPAA-restricted access after switching accounts, closing a gap where switching organizations mid-session might otherwise leave restricted features still available.

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

### Artifact publish gained expanded, per-reason-code error messages

Artifact publish failures now show specific, tailored error messages for many more failure reasons

**What**

Artifact publishing (deploying) failures now come with much more specific error messages. A large new table of reason codes, covering cases like `audience_conflict`, `capability_refused`, `contract_refused`, `not_owner`, `read_timeout`, `deadline_invalid`, and `live_path_cap`, drives custom explanatory text instead of a small set of generic hardcoded checks. A new `deadline_invalid` case automatically retries the request with its `deadline` field removed, and errors about specific declared capabilities now get their own tailored messages.

**Why**

This makes it much clearer why a publish attempt failed, rather than showing a generic error for many different underlying problems.

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

### Multi-store memory sync now recognizes tombstones and won't silently resurrect deleted shared memory

Shared memory sync now detects intentional deletions and stops silently recreating deleted files

**What**

When Claude Code syncs shared memory (memory shared across an organization) between local and remote copies, it can now tell when a remote file was deliberately deleted rather than just missing, using a marker called a 'tombstone'. If your local copy of that file predates the deletion and is old enough, it gets quietly deleted to match. If not, you now get a one-time warning per file (rather than the file being endlessly re-pushed back or silently recreated).

**Why**

Previously a deleted shared-memory file could keep coming back because a stale local copy kept re-pushing it. Recognizing deletions properly means a file someone intentionally removed stays removed, and you're told about it once instead of the sync silently fighting itself.

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

### Artifact republish now says it hot-updates open viewers

Republishing an artifact now automatically updates any copies already open, keeping page state where possible

**What**

Artifacts (the standalone documents, apps, or games Claude can create and show alongside a conversation) can now be republished with updates that reach any viewers already open, without the reader having to reopen or refresh them.

Where possible, the update carries over the current state of the page, such as a game in progress, a queued action, or a reply that has been half-typed but not sent.

**Why**

This means updating an artifact no longer risks losing what someone was doing in it, so iterating on an open artifact is safer and less disruptive.

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

### File-encoding problem reporting for reads (UTF-16LE/UTF-8 detection + replacement-char and undecodable diagnostics)

File reads now detect encoding problems and report exactly where a broken or undecodable character occurs

**What**

When Claude Code reads a file, new internal logic detects the file's text encoding (distinguishing UTF-16LE from UTF-8 by checking for a byte-order mark), then scans for the first replacement character (the symbol that appears when a byte sequence can't be properly decoded as text) or the first byte that can't be decoded at all. If either is found, the read now returns a structured result identifying the problem kind, the encoding, and the exact line and column where it occurs, instead of just returning garbled text.

**Why**

This gives clearer diagnostics when a file has encoding issues, pinpointing exactly where the problem is rather than leaving Claude (or the user) to guess why a file's contents look corrupted.

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

### Artifact comment forwarding now includes team-member comments, not just the owner's

Artifact auto-react now forwards teammates' comments, not just the artifact owner's

**Unclear.** What the flag controlling this behavior is called or how it's enabled isn't stated.

**What**

When Claude Code builds the list of comments to forward for an artifact's automatic reaction feature, it now also includes comments from team members (not just the artifact's owner), when a related setting is enabled. These team-member comments are tagged with `source: "unattributed"` and get a `projectsRow` marker plus extra fields. Owner comments are also now cross-checked against a lookup of earlier comments to reuse an earlier authored version and timestamp when appropriate.

**Why**

Previously only the artifact owner's comments were considered, so Claude could miss feedback left by other team members on a shared artifact; now it can react to comments from the whole team.

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

### Artifact write_db permission prompts now describe file provenance and version-pinned edits to others' artifacts

Permission prompts for writing to artifacts now explain whose file it is and flag version-pinned edits

**What**

When Claude Code asks permission to write to an artifact's underlying storage (`write_db`), it now classifies the write as one of four cases: `cowritten`, `from_type`, `someone_else`, or `unknown`, based on who owns the file. The permission prompt can now be prepended with a description of the file, such as saving a file as a given name or saving a named file to a given location.

It also separately calls out a version-pinned write to someone else's artifact (an edit that targets a specific saved version rather than the latest one): this kind of write always asks for permission on its own, and approving it only covers that one write, until the current conversation has read that artifact's data.

**Why**

This makes permission prompts for artifact writes more informative about whose file is being changed, and adds an extra safeguard around version-pinned edits to other people's artifacts so approval doesn't inadvertently cover more than intended.

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

### Context/checkpoint diffing extended to cover file writes, not just artifacts

Claude Code's checkpoint diffing now tracks file writes and edits, not just artifacts

**What**

The internal system that tracks changes across a conversation's checkpoints used to only follow artifact tool calls. It now also follows file write and edit tool calls, and reports a `kind` of either 'artifact' or 'file' for each tracked change. It also counts failed edits (an edit that tried to replace text that didn't match) in a new `editsFailed` counter, and returns a `kept` list showing which artifacts are still the final version at the point in the conversation being examined.

**Why**

This extends the diffing and checkpoint machinery so it can account for direct file edits alongside artifact publishing, which should make version tracking and rollback more accurate when a session mixes both kinds of changes.

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

### Rate-limit tracking gains a locally-remembered-window fallback, on by default

Claude Code can now show a rate-limit status from recently-remembered windows when a fresh server reading isn't available

**Unclear.** The `tengu_sharded_moonbeam` gate controlling this hasn't been read for this site's account, so whether it's active here is unknown.

**What**

Claude Code tracks how close you are to hitting rate limits (caps on how much you can use the service in a given period). It now also keeps a rolling local record of recently-seen rate-limit windows, and can use that record to fill in the displayed status when a fresh reading from the server isn't available at that moment.

**Why**

This should make the rate-limit indicator more reliable, avoiding gaps or blank states when a fresh server reading is momentarily missing.

- Flag `tengu_sharded_moonbeam`: Not enough to say (read for one account on one subscription tier against v2.1.267; this account: no value returned, anonymous baseline: no value returned, compiled default: off)
- Area: Rate Limits
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Sub-agent tool resolution now includes machine-level MCP tools

Spawned subagents can now use machine-level MCP tools, not just app-state and agent-declared ones

**What**

When Claude Code figures out which tools a spawned subagent is allowed to use, it now also includes machine-level MCP (Model Context Protocol, a standard for connecting external tools) tools, in addition to the app-state MCP tools and the tools an agent explicitly declares. This applies both to subagent spawning generally and to the workflow SDK's agent tool-set resolution, and the machine-level tool list is now merged in when building skill tool sets as well.

**Why**

This broadens what tools a subagent can reach, so machine-wide MCP tool configurations are no longer left out when a subagent's tool set is computed.

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

### Forwarded-user-turns classifier prompt adds a new author category for messages written on a Claude Code Project's timeline

A new message type lets a Claude Code Project owner speak as the session user on the project's timeline

**Unclear.** The finding notes this is gated behind a parameter that defaults to false, so it's unclear whether or when it is actually active.

**What**

The internal prompt that interprets forwarded or human-authored messages for background and cloud agents now recognizes a new category: a message written by the owner of the Claude Code Project a session belongs to, posted on that project's timeline. When present, this message is treated as if the session's own user wrote it, and it can clear a SOFT BLOCK rule for the exact action it names.

This new behavior comes with limits:

- it cannot answer a pending permission prompt

- it cannot authorize changes to permission settings or to CLAUDE.md

- a bare "yes" or "ok" clears nothing unless the block was already visible when the owner wrote the message

**Why**

This lets a project owner unblock a specific stuck action from the project's timeline without being logged in to the session directly, while still preventing that channel from being used to approve permissions or rewrite instructions it shouldn't be able to touch.

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

### Artifact publish requests can now be dropped for exceeding a deadline

Artifact publish requests can now be marked as dropped for exceeding a deadline

**What**

When an artifact publish request takes too long, the response now includes a `deadlineDropped` flag marking that the request's deadline was exceeded and it was dropped. The logic deciding which fields to include in the response now also factors in whether a deadline was set on the request.

**Why**

This makes it possible to tell, from the response itself, when a publish was dropped for taking too long rather than failing for another reason.

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

### Artifact publish responses can now report deadlineDropped

Publishing an Artifact can now report that a previously set deadline was dropped

**Unclear.** The finding does not say what causes a deadline to be dropped during publish, or what a caller is expected to do in response.

**What**

When an Artifact is deployed or published, the response can now include `deadlineDropped: true` if a deadline that was previously set on that artifact gets dropped as part of the publish. The publish path also now passes a `sent` flag through to its error-classification logic.

**Why**

This gives whoever (or whatever) triggers a publish a clear signal when a deadline they'd set no longer applies, instead of it silently disappearing.

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

### User-writable settings files can no longer set secDefault/prependPlugins/appendPlugins or enable plugins via enabledPlugins

User-writable settings files can no longer set secDefault, prependPlugins, appendPlugins, or enable plugins

**What**

Settings loaded from files a user can edit directly (as opposed to administrator-managed settings) can no longer set `secDefault`, `prependPlugins`, or `appendPlugins`; these are now stripped out with a warning if found there. Similarly, any `enabledPlugins` entries in user-writable settings that would turn on a plugin, or name a built-in plugin, are stripped too.

**Why**

These settings are meant to be controlled only by an administrator through managed settings. Stripping them out of user-writable files (with a warning) prevents a user from enabling plugins or changing these defaults on their own, closing a gap where such settings might previously have been honored from the wrong place.

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

### Memory store refuses silent resurrection of recently-deleted (tombstoned) content

Memory store now refuses to silently re-create content that was just deleted

**What**

Claude Code's shared memory store can refuse a write if it conflicts with something else. Now, if the target was recently deleted (left as a "tombstone", a marker that something used to exist there), the store returns a distinct `tombstone_conflict` reason, with a message telling the caller not to silently re-create identical content at a different path instead.

**Why**

This prevents deleted memory content from quietly reappearing under a new location, which could otherwise undo an intentional deletion without anyone noticing.

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

### Plugin repository must be recognized as trusted-org to get 'org' scope

Plugin commands only get 'org' scope if their repository is in a trusted-org list

**What**

For commands and prompts that come from plugins, Claude Code now only labels them with 'org' scope when the plugin's source repository is found in a specific trusted set provided by the caller. Previously, plugin-sourced items were always mapped to 'org' scope, the same way items from 'managed' or 'synced' sources are. Now, if the repository isn't in that trusted set, the scope comes back undefined instead.

**Why**

This tightens how plugin commands get classified as organization-wide, preventing plugins from arbitrary or untrusted repositories from automatically being treated as coming from the organization.

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

### New session-identity contest/impersonation warnings for send_message

send_message now warns about possible impersonation or a restarted session before sending

**What**

Two new warnings appear when resolving a saved session reference for `send_message`:

- another live session on the same machine currently claims the same identity as the target, which could mean impersonation or a duplicate open conversation

- the target session has restarted since it was last reached (same session, but a new process)

Both warnings advise checking with the user before sending anything sensitive.

**Why**

These guard against sending a message to the wrong session when identities have become ambiguous, such as after a restart or when two sessions could plausibly claim the same identity, prompting extra caution before sharing sensitive content.

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

### Non-blocking stdout can now be enabled by a remote flag, not just an env var

Non-blocking stdout writes can now be turned on remotely, not just via an environment variable

**What**

`CLAUDE_CODE_NONBLOCKING_STDOUT` makes Claude Code write terminal output through a second, non-blocking channel so a stalled terminal (like a paused tmux pane or a frozen SSH connection) can't freeze the session. Previously this only applied when the environment variable was explicitly set. Now, if the environment variable isn't set, Claude Code also checks a remote server-controlled setting, `tengu_event_loop_stall`, as well as an internal first-party check, to decide whether to enable it.

**Why**

This lets Anthropic roll out the non-blocking stdout behavior to more users gradually via a remote setting, without requiring everyone to manually set the environment variable themselves.

- Flag `tengu_event_loop_stall`: Off in both readings (read for one account on one subscription tier against v2.1.267; this account: off, anonymous baseline: off, compiled default: on)
- Area: Terminal UI
- Names: `CLAUDE_CODE_NONBLOCKING_STDOUT`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Host/API-URL reporting now recognizes local SSH-tunnel sessions

Status displays now recognize local SSH-tunnel sessions and report a local endpoint instead of the real host

**What**

When Claude Code reports which host or API URL it's connected to (for example in `/status`), it now checks a new setting first. If that check passes, it reports that it is connected to the "local machine (via claude ssh tunnel)" and builds any related URL against `http://localhost`, instead of showing the actual configured API host.

**Why**

This makes the connection status accurate for sessions running over a local SSH tunnel, where the real API host isn't the meaningful thing to display.

- Area: Internals
- Names: `claude ssh tunnel`
- Tier: You'll notice
- Useful: 2/5
- Signal: 2/5

### Sandbox system prompt now tells Claude to use /copy when a clipboard tool fails inside the sandbox

Claude is now told to suggest running /copy when clipboard commands fail inside the sandbox

**What**

When Claude Code runs commands in a sandbox (a restricted environment that limits what a command can access), clipboard tools like `pbcopy`, `xclip`, or `wl-copy` don't work because they can't reach the system clipboard from inside it. Claude's instructions now tell it that when this happens, it should put the text in a fenced code block and tell the user to run `/copy` themselves, rather than writing the text to a file for the user to copy manually.

The `/copy` command copies the last assistant response to the clipboard from outside the sandbox; when code blocks are present it shows an interactive picker so the user can select just the block they want, or press `w` to write the selection to a file instead, which is useful over SSH.

**Why**

This avoids Claude falling back to writing scratch files just to work around a clipboard command that can't run inside the sandbox, pointing the user instead to the built-in `/copy` workflow that already handles this case.

- Area: Sandbox
- Names: `/copy`
- Tier: You'll notice
- Useful: 3/5
- Signal: 1/5

### Plugin panel ('AbovePrompt') gains a mouse-draggable resize grip and hold/scroll UI

The plugin panel above the prompt now has a mouse-draggable resize grip and scroll indicators

**What**

The plugin panel that appears above the prompt ("AbovePrompt") gains a resize grip you can click and drag with the mouse to change its size. When the panel's content is too tall to fit, it now also shows "N more above/below" indicators so you know there's more to scroll to.

**Why**

This makes it easier to control how much space the plugin panel takes up and to notice when content is hidden above or below the visible area, instead of guessing.

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

### Artifact comment context truncation reworked to preserve indentation and header lines

Artifact comment truncation now preserves indentation and header lines instead of cutting text mid-line

**What**

When an artifact's comment thread is too large to include in full, Claude Code trims it down. Previously this was a flat character cutoff across the whole rendered comment. Now each comment's header line is kept separate from its body when trimming, and any trailing partial line that matches the quoted-line prefix is removed entirely rather than left cut off mid-line.

**Why**

This produces cleaner, more readable truncated comment threads, avoiding jagged cutoffs in the middle of a quoted line or a header.

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

### Plugin hooks.json now warned on unknown/malformed keys

Claude Code now warns about unknown or malformed keys in a plugin's hooks.json

**What**

A plugin's `hooks.json` file (which defines hooks — scripts that run automatically at certain points, like before a tool runs) is now checked against an allow-list of valid keys. If it contains keys that aren't recognized, or if a hook entry is missing its required `matcher` or `hooks` fields, Claude Code now emits a warning listing the offending keys, summarizing with "... and N more" if there are many.

**Why**

This helps plugin authors catch typos or malformed configuration in their `hooks.json` files early, instead of having the mistake silently ignored.

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

### New error guidance for unsupported batch writes with version pins

Batch writes to the artifact database get clearer errors for unsupported version pins and stale writes

**What**

The artifact database's batch-write feature (writing several changes to an artifact's data at once) now gives more specific error messages:

- a new `batch_pinned_unsupported` error for servers that don't support batch writes that are pinned to a specific version (`if_version`) at all

- a refined `version_mismatch` error that names which specific write in the batch was stale, and tells the caller to re-read the data before resending

**Why**

These clearer errors make it easier to figure out why a batch write failed and what to do about it, instead of getting a generic mismatch error with no indication of which write caused it.

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

### Rate/credit limit messaging distinguishes channel-level spend caps

Hitting a channel's own spend cap now shows a distinct message from hitting the general monthly limit

**What**

The message shown when a spend cap is hit now distinguishes a channel-scoped cap from the general one. Hitting a channel's own monthly limit now shows "You've hit your channel's monthly spend limit," separate from the existing "You've hit your monthly spend limit" message.

**Why**

This makes it clear whether the limit that was hit applies to a specific channel or to the account as a whole, which matters for knowing who to ask about raising it.

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

### Managed-policy plugin seating warnings for prepend/append conflicts

New warnings flag when a managed plugin's ordering or a settings key gets silently overridden by managed policy

**What**

A new check now warns in two more situations involving managed plugin configuration:

- when a plugin is listed in both `prependPlugins` and `appendPlugins`, it warns that the conflict is resolved by prepending the plugin

- when a `secDefault`/user-settings key is overridden by managed policy on a machine with managed settings in place, it now warns that the value is being shadowed

**Why**

These warnings make it clearer when managed policy is silently overriding a setting or plugin placement, so administrators and users are less likely to be confused about why a configuration isn't taking effect as written.

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

### Plugin hook hot-reload now also fires on user-settings tier changes

Plugin hooks now hot-reload when settings move between managed and user tiers, not just on managed-policy changes

**What**

Claude Code can reload a plugin's hooks (scripts that run automatically at certain points, like before a tool call) without restarting. Previously this hot-reload only triggered when the managed policy settings changed. It now also triggers when user settings change, if doing so moves a setting between the managed and user configuration tiers.

**Why**

This closes a gap where changing where a setting lives (for example, moving it from user-level to managed-level) could leave plugin hooks out of sync until a restart. Now that kind of change reloads the hooks automatically.

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

### Clearer error messages when a pinned-version document write conflicts

Artifact write-conflict errors now explain whether the document's current version is known or the document may be gone

**What**

When an artifact write fails because the document was changed since you last read it (`version_mismatch`), the error message is now more specific:

- If the document's current version is known, it tells you the new version number so you can re-plan your edit against it.

- If the current version is unknown or the document was deleted, it tells you to check whether the document still exists.

- For a delete operation in that case, it says a delete has nothing left to do.

- For other operations in that case, it suggests re-creating the document with a plain `set`.

**Why**

This replaces a generic version-conflict error with guidance tailored to what actually happened, making it easier to recover from a conflicting edit instead of guessing at the next step.

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

### Hooks-worker heartbeat watchdog now tolerates multiple missed beats

The hooks worker watchdog now waits for several missed heartbeats before declaring it stuck, not just one

**What**

Claude Code runs hooks (custom scripts that run at certain points, like before or after a tool call) in a separate worker process. A background daemon checks that this worker is still alive by sending it periodic heartbeat pings and waiting for a response. Previously, a single unanswered ping (based on how much time had passed) was enough to declare the worker wedged. Now the daemon counts consecutive missed heartbeats and only declares the worker stuck once that count crosses a threshold.

**Why**

A hook that briefly spins without yielding could previously trip the watchdog on one slow beat and get flagged as wedged even though it was still working. Tolerating multiple missed beats reduces false positives while still catching a genuinely stuck hooks worker.

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

### AbovePrompt panel gets dedicated scroll keys instead of overloading up/down

The panel above the prompt now uses dedicated scroll keys instead of sharing up/down with other navigation

**What**

The panel that appears above the prompt box had its keyboard shortcuts changed. Previously, the up and down arrow keys doubled as aliases for moving to the next or previous item in that panel. Now up, down, page up, page down, home, and end are bound instead to dedicated scrolling actions: scroll up, scroll down, page up, page down, jump to top, and jump to bottom. The description of this keybinding scope was also updated to refer to a 'panel' above the prompt rather than just a button.

**Why**

Giving the above-prompt panel its own dedicated scroll keys, instead of overloading up/down for item navigation, makes it possible to scroll through the panel's content directly rather than only jumping between items.

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

### Batch-write messaging refined for version-pinned writes

Error message for version-pinned batch writes now says the whole batch is refused, not applied piecemeal

**What**

When Claude Code explains why an unsupported batch write can't proceed, it now takes into account whether the batch is version-pinned. For a version-pinned batch, the message says it will only be applied all-or-nothing if the server supports batch writes; otherwise it's refused entirely, since 'a version-pinned batch is never applied one at a time'. This replaces the previous message, which described a one-at-a-time fallback.

**Why**

This corrects the explanation given to accurately reflect that a version-pinned batch can't be split apart and applied piece by piece, avoiding a misleading description of what happens when the write fails.

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

### New responsive-design system guidance for Artifact page generation

Artifact generation now gets more detailed instructions for making responsive web pages

**What**

When Claude Code builds web-page Artifacts, the prompt guiding the model now includes more detailed responsive-design instructions:

- Keep the page usable at widths as small as roughly 400px

- Keep 16px side margins using `padding-block` (never a padding shorthand that zeroes it out)

- Use relative units instead of fixed pixel sizes

- Let grids wrap or stack on narrow screens

- Cap the width of images and elements with a fixed aspect ratio

- Confine any horizontal scrolling to tables, diagrams, or code blocks, each in its own scrolling container, so the page body itself never scrolls sideways

**Why**

This should produce Artifacts that look right and stay usable on narrow screens and mobile-sized viewports, instead of overflowing or requiring awkward horizontal scrolling.

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

### Usage stats now hidden for HIPAA-regulated orgs

Usage stats are now explicitly hidden for HIPAA-regulated organizations, with an explanation why

**What**

The 'Usage stats' feature now carries an explicit note that it is not shown for organizations under HIPAA regulation. The reason given is that these stats are built by scanning session transcripts saved locally on the machine.

**Why**

HIPAA-regulated organizations have restrictions on handling data drawn from stored conversation content, so this stops usage stats, which are computed from locally saved transcripts, from being shown to those organizations.

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

### New restricted-tools decline messaging: memory tombstone conflicts

Recreating a just-deleted shared memory file with identical content is now explicitly refused

**What**

If a memory file was recently deleted from shared memory and something then tries to write that same path back with identical content, Claude Code now refuses the write with a dedicated error message explaining that the file was recently deleted and re-creating it with the same content isn't allowed. Previously this situation would have been handled by generic conflict-handling logic.

**Why**

This gives a clearer, more specific explanation when a memory write is blocked because it looks like an attempt to silently restore something that was just deleted, instead of a vague conflict error.

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

### Button plugin UI component now supports hover state

Plugin UI Button elements can now carry a hover state through to press handling

**Unclear.** The finding doesn't say what visible effect the hover prop has once it reaches press handling.

**What**

The Button element type used in plugin user-interface code now conditionally passes along a `hover` property when handling a press, if one is set.

**Why**

This is internal plumbing for plugin UI buttons; it suggests buttons can now track and act on hover state, not just clicks, but the finding doesn't describe a specific visible effect.

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

### New MCP-unavailable error message variant

A new error message explains when an MCP server's tools can't be used this session

**What**

Claude Code now shows a distinct error message when a tool from an MCP server (a connector that lets Claude use external tools and data) isn't available for the current session: "[server]'s MCP tools are not available in this session right now; [tool] did not run." This is separate from the existing message that suggests the server may have disconnected.

**Why**

This gives a clearer, more specific explanation for a case where MCP tools simply aren't usable right now, rather than lumping it in with a message that implies a connection problem.

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

### Plugin sync scope-check now treats a 'non_interactive' auth failure as lacking scope

Plugin sync now recognizes a specific auth failure as a missing permission rather than a generic error

**What**

The internal function that checks scope (permission) before a plugin sync request now returns a result of `"send"` or `"skip_no_scope"` instead of nothing. When the underlying request fails specifically because it's non-interactive, it returns `"skip_no_scope"`, and callers such as plugin or marketplace sync now short-circuit with a clear error: "claude.ai login lacks the user:plugins scope in this session."

**Why**

This turns a previously generic failure into a specific, understandable error when a non-interactive session lacks the permission scope needed to sync plugins, making it clearer what went wrong and why.

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

### Headless served-model-catalog fetch now backs off exponentially after failures

Headless mode now backs off from re-fetching the model catalog after a recent failure instead of retrying every time

**What**

When Claude Code starts in headless (non-interactive, scripted) mode, it fetches a catalog of available models over the network. Now, before doing that fetch, it checks a saved marker recording whether a recent headless fetch failed. If a failure was recorded recently, it skips the network call entirely and falls back to the built-in model list, recording the reason as `headless_held_off`.

Success and failure are tracked in a new `.headless-failed.json` marker file, and repeated failures make Claude Code wait longer before trying again (exponential backoff).

**Why**

This avoids repeatedly hitting a failing network endpoint on every headless run, which previously could slow down or delay each invocation. If the model catalog can't be reached, headless runs now fail fast and fall back to a known-good default list instead of retrying every time.

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

### Peer-session send error now suggests the session's new name if it was renamed

Sending a message to a renamed peer session now suggests its new name in the error

**What**

When Claude Code tries to send a message to another peer or agent session by name and can't find that name, the error message now checks whether that session was renamed, and if so, tells you its current name.

**Why**

This makes it easier to recover from a "session not found" error caused by a rename, since the message now points directly to the name to use instead.

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

### New 'channel' scope for usage/spend-limit messaging

Usage limit messages can now show a 'channel' scope, distinct from the whole organization

**What**

When Claude Code hits a rate limit or spend/usage cap, the message shown can now be scoped to a 'channel' rather than the whole organization. This is signaled by a new `anthropic-ratelimit-unified-overage-scope` response header set to `channel`, and the usage-limit text then reads "channel's monthly spend limit" or "channel's monthly usage limit" instead of the organization-wide wording.

**Why**

This lets usage and spend limits be communicated at a more specific level than the whole organization, so the message a user sees can better match where the actual limit was set.

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

### Stats dialog now requires an "allowed" permission check

The stats dialog now checks a permission flag before loading usage stats

**Unclear.** The finding does not say under what conditions `allowed` would be false or what reasons might be shown.

**What**

The dialog that shows usage statistics (similar to the `/stats` command) now first checks whether it is allowed to load, using an `allowed`/`reason` pair from a store. If it isn't allowed, it shows the given reason text instead of fetching and displaying all-time and active-time usage figures.

**Why**

This lets Claude Code hold back the stats dialog for certain accounts or situations and show an explanation instead, rather than always loading usage data.

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

### New fine-grained error messages for artifact publish source-approval mismatches

Artifact publishing gains many specific error messages for approval and source-integrity mismatches

**What**

Artifact publishing now has a large set of new, specific error messages covering ways a publish's approval can fail to match its source, including:

- a stale approval from an older Claude Code version (`source_pin_stale_build`)

- a missing or unreadable approval (`source_pin_missing`/unreadable)

- a replayed approval that was already used (`approval_replayed`)

- an approval that expired from storage (`source_pin_evicted`)

- a permission check that was never observed (`source_pin_unobserved`)

- an internal check failure (`source_check_failed`)

- a source file changed via a symlink or hardlink by another process while resuming (`source_redirected_on_resume`)

- a source path that changed after approval (`source_path_mismatch`)

- invalid text encoding or replacement characters in the source content

Each error comes with guidance on what to do next.

**Why**

This replaces what were likely vaguer or generic failures with precise diagnostics, making it clearer why an artifact publish was rejected and what to do to retry successfully, especially in cases involving tampering, staleness, or file changes between approval and publish.

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

### Session export/import now round-trips file-write tool calls

Exporting and re-importing a session now preserves file-write tool calls, not just text

**What**

When a Claude Code session is exported and later imported back in, the importer now reconstructs file-write tool calls (the tool actions that write a file's path and content) as part of an assistant message, in addition to the plain text it already handled.

**Why**

Previously, importing a session could lose the record of file writes an assistant made, so re-imported conversations look incomplete compared to what actually happened. Round-tripping file writes keeps exported and re-imported sessions faithful to the original.

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

### Artifact publish source-verification errors split into specific reasons

Artifact publishing now reports specific reasons when it can't verify a source file, instead of one generic error

**What**

When Claude Code publishes an artifact (a generated file or output shared outside the normal chat), it checks a "pin" recorded during an earlier permission check to make sure the source file hasn't changed. Previously, if that check failed for any reason, it just reported a generic `source_unverified` error. Now it reports the specific cause:

- the pin was evicted from session state

- the permission check never recorded a pin at all

- the permission check crashed before it could record the file

- the source was redirected, for example via a symlink or hardlink, during a resumed approval

**Why**

More specific error messages make it easier to understand why an artifact publish was blocked, rather than just seeing an unhelpful generic failure.

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

### Visual connector for consecutive labelled-reply messages

Consecutive replies from the same labelled speaker now show a connecting line instead of repeating the label

**What**

In message lists where replies are shown under a speaker label (such as in bridged or teammate sessions), consecutive messages from the same labelled speaker are now tracked as "continuing" that reply. Instead of repeating the label for each one, Claude Code now draws a connector line down the left edge to visually link them.

**Why**

This makes a run of messages from the same speaker easier to read at a glance, without the label repeating unnecessarily.

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

### Org-policy beta-block message reworded

The message shown when an org policy blocks experimental beta headers was reworded

**What**

When an organization's compliance policy strips beta headers from `ANTHROPIC_CUSTOM_HEADERS` or `ANTHROPIC_BETAS` (environment variables used to opt into experimental Anthropic API features), the debug log message changed from "disabled by org compliance policy" to "disabled by your organization's policy."

**Why**

This is a wording change only, making the message read more directly to the person seeing it, with no change to the underlying blocking behavior.

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

### Org-policy denial text genericized, dropping explicit HIPAA callout

The message shown when Projects is disabled by org policy no longer names HIPAA specifically

**What**

When an organization's policy disables Projects (uploading or reading project files to claude.ai), the message shown now just says the feature is 'disabled by your organization's policy.' Previously the message specifically called out 'compliance policy (e.g. HIPAA)' as an example reason.

**Why**

The underlying behavior (Projects being blocked) is unchanged; only the wording is more generic now, so the message applies cleanly to any policy reason, not just HIPAA-style compliance ones.

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

### New scrolling UI hint text for 'band' and 'scrollingButton' widgets

New footer hint text explains keyboard controls for two scrolling UI widgets

**What**

Two new footer hint strings were added to the terminal UI:

- a 'band' widget hint: arrows, page up, and page down scroll, tab moves, and escape returns to the prompt

- a 'scrollingButton' widget hint: enter presses the button, and arrows scroll

**Why**

These hints tell the reader which keys control these scrolling UI elements, making them easier to use without guessing.

- Area: Terminal UI
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Wording change: plugin entry helper consent message

Reworded error message for unapproved plugin entry helpers from remote-managed settings

**Unclear.** The exact before/after wording isn't given, so the extent of the change is unclear.

**What**

The error message shown when a plugin entry helper, declared through remote-managed settings, hasn't yet been approved for the current session was reworded.

**Why**

This is a wording change only; it doesn't alter when the message appears or what approval is required.

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

### Rate-limit banner drops short labels

Rate-limit config drops the short "5h"/"7d" labels for the five-hour/seven-day thresholds

**Unclear.** It's unclear what, if anything, in the visible interface actually used claimAbbrev, so the practical effect on what a user sees is not established.

**What**

The configuration for the five-hour and seven-day rate-limit thresholds no longer includes a `claimAbbrev` field, which previously held short labels like "5h" and "7d".

**Why**

Any part of the interface that relied on these short labels to display rate-limit information loses that source, which could mean a shortened label disappears or changes elsewhere in the product.

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

### "Compliance policy" wording replaced with "organization's policy" across several messages

Messages that mentioned "compliance policy" now say "organization's policy" instead

**What**

Several messages shown to users or written to logs have been reworded to replace references to "compliance" or "org compliance policy" with "organization's policy". This includes the message shown when model-chosen URL access is blocked, the message logged when `CLAUDE_CODE_EXTRA_BODY` content is dropped, and the message logged when SDK betas are dropped.

**Why**

This is a wording change only, making the messages more consistent and describing the source of the restriction as the organization's policy rather than a specific compliance mechanism.

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

### Effort-cap message now credits local settings, not just org

Effort-cap message now says your own settings can lower the cap, not just your organization

**What**

When a requested effort level (a setting that controls how much reasoning Claude puts into a task) exceeds the allowed maximum, the warning message now says the cap can come from "your settings or organization", rather than blaming the organization alone.

**Why**

This makes the message more accurate: if you've capped effort yourself through your own settings, the message no longer wrongly points to your organization as the cause.

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

### Effort-level restriction message reworded

The message about capped reasoning-effort levels was reworded to be more accurate

**What**

When a higher reasoning-effort level (how much the model "thinks" before answering) isn't available to you, Claude Code now says "Higher effort levels are capped by your settings or organization" instead of a version that placed the blame solely on your organization.

**Why**

The cap can come from your own settings as well as an organization-wide policy, so the new wording avoids incorrectly pointing the finger at your organization when the restriction is actually something you set yourself.

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

### Artifact comment handling adds a stale-handoff sweep unconditional of auto-reply settings

Artifact comment reads now always sweep away stale handoff entries, regardless of auto-reply settings

**What**

When handling artifact comments and related database reads, Claude Code now always runs a cleanup step that clears out stale "summon handoff" entries for a slug that no longer matches any current agent. Previously this only happened when auto-react or auto-reply was enabled.

**Why**

This keeps stale handoff state from lingering and potentially causing confusion, even for artifacts where automatic replies are turned off.

- Area: Artifacts
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Artifact tool: 'label' hint text simplified

Artifact tool's error message for an overlong 'label' field dropped the word 'version'

**What**

When the artifact tool rejects a `label` field that is too long, the message it shows now just says `label` is a short name (max 60 characters), instead of describing it as a short version name.

**Why**

It's a small wording tweak to the guidance shown when a label is too long, telling you to move any longer text into the page content instead.

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

## Bug Fixes

### Bug fix: availableModels validator was reading from the wrong variables

Fixed a bug where the availableModels setting validator checked the wrong internal variables

**What**

The validation logic for the `availableModels` setting, which restricts which models people can pick, had a bug: it was reading from and writing to internal variables that didn't match its own inputs, so it wasn't actually validating the list it was given. This has been fixed so it correctly checks the input array and only keeps valid string entries.

**Why**

This fixes a case where `availableModels` validation could behave incorrectly, for example failing to catch or properly report a non-string entry in the list. Anyone using this setting to restrict model selection should see it validated correctly now.

- Area: Model Settings
- Names: `availableModels`
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Session pin/rename detection: sending to a renamed session no longer silently fails

Sending a message to a session that was renamed now reports the rename instead of just failing

**What**

When one agent session sends a message to another (`send_message`) using a saved reference (a "pin") that points to a session which has since been renamed on the same machine, Claude Code now detects the rename and surfaces it. The previous "not reachable" error now appends a note like "A session now named '' reports it as a former name (renamed)." Pin resolution can also follow the rename automatically to reconcile the reference.

**Why**

Previously, sending to a session that had since been renamed would just fail with no explanation. Now the error tells you the session still exists under a new name, and the pin can be updated to track it, so a rename no longer silently breaks messaging between sessions.

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

### Bridge (Remote Control) now surfaces a distinct fatal error when credential renewal fails after repeated attempts

Remote Control now gives a clearer fatal error when it can't renew its connection credential

**Unclear.** Whether either of the two related gates, `tengu_bridge_env_reregister` and `tengu_bridge_fatal_error`, is active has not been read for this account.

**What**

Remote Control lets you continue a local Claude Code session from another device. When its background connection ('bridge') repeatedly fails to authenticate and can't renew its credential, Claude Code now logs a specific, distinct error message depending on the cause: either the server issued a completely new environment instead of renewing the old one, or renewal failed after repeated attempts. Either way, the message tells you to restart `claude remote-control` to start fresh.

**Why**

Instead of a vague or silent failure, you now get a clear signal that Remote Control has broken down and needs a manual restart, along with the specific reason why.

- Area: Remote Control
- Names: `claude remote-control`
- Tier: You'll notice
- Useful: 3/5
- Signal: 2/5

### Sync/live-edit artifact permission "version" no longer auto-granted with liveEditOn

Live-edit artifacts no longer automatically get "version" permission alongside "sync"

**What**

When computing which actions are allowed for an artifact with live editing turned on (`liveEditOn`), Claude Code now only grants the "sync" action. It previously also granted "version" automatically in this case.

**Why**

This narrows the automatic permissions given to live-editing artifacts, meaning "version" is no longer assumed to be allowed just because live editing is on.

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

### Policy checks for agent.spawn and tool.call gain argument restoration

Policy checks for spawning agents and calling tools now restore pinned fields a hook altered, not just flag them

**What**

The policy checks that run on `agent.spawn` and `tool.call` events now actively restore certain pinned fields if a hook rewrite changed them: the parent agent ID and related fields for `agent.spawn`, and the agent ID for `tool.call`. Previously these checks only flagged a mismatch rather than fixing it.

**Why**

This stops a hook from being able to alter security-relevant identifiers like the parent agent ID, restoring them to their correct values automatically rather than merely reporting that they were changed.

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

### Artifact publish failures now surfaced directly in the publish UI

Artifact publish failures are now shown directly in the publish panel with the reason

**What**

When publishing an artifact's files fails, Claude Code's publish status panel now shows a red "Couldn't publish its files" message along with the specific reason, instead of failing silently or less visibly. Session state also now tracks `crashedPublishChecks` and `frozenHotUpdate`.

**Why**

This makes publish failures visible where you're already looking, so you know immediately that publishing didn't succeed and why, rather than only discovering it later.

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

### Hooks path-traversal validation extended to a hook's 'surface' file

Hook path-traversal checks now also cover a hook's 'surface' file, not just its module file

**What**

When Claude Code validates a plugin's hook configuration, it already checked the hook's module path for path traversal (an attempt to reference files outside the intended directory, e.g. using `../`) and existence. It now performs the same checks on the hook's `surfacePath` as well, returning a `path-traversal` or `path-not-found` error if it fails.

**Why**

This closes a gap where a hook's surface file could point outside its intended directory without being caught, tightening the security checks around plugin hooks.

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

### Artifact publish retries once on a fresh connection after a mid-upload connection death

Artifact publishing now automatically retries once if the upload connection dies mid-transfer

**What**

When publishing or deploying an artifact and the upload connection drops partway through sending the request body, Claude Code now detects this using byte-tracking data and automatically resends the request once over a fresh connection. It logs a warning when this happens, along with a `deploy_resent` telemetry event recording the outcome of the retry.

**Why**

This makes publishing more resilient to flaky network connections, recovering automatically from a dropped connection instead of failing the whole publish attempt.

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

### New diagnostics for malformed plugin hook matchers and hook re-entry

New warnings catch malformed plugin hook matchers and hook re-entry

**What**

Claude Code now detects when a plugin's hook matcher (the `on()` condition that decides when a hook runs) is structurally wrong, such as using an object matcher against a value that can only be a scalar, and logs a one-time warning per file path explaining the mismatch, capped at 32 warnings per module and event to avoid log spam.

It also now logs when a hooks module's own hook is skipped, or has some of its registrations left out, because that module is already being dispatched (re-entry protection), naming the chain of nested hook calls that led there.

**Why**

These diagnostics help plugin authors notice when a hook matcher is written incorrectly and will never fire, and understand why a hook was skipped due to re-entry, instead of the failure passing silently.

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

### Artifact file uploads now reject replacement-character/unpaired-surrogate text

Artifact text file uploads are now rejected if they contain the Unicode replacement character or an unpaired surrogate

**What**

When a text-type file is validated for publishing to an Artifact, content containing the Unicode replacement character (U+FFFD, the symbol that appears when text can't be decoded properly) or an unpaired surrogate (a broken piece of a multi-part character) is now rejected with a specific error. For HTML files, the error also explains that the character should be escaped as `&#xFFFD;` instead.

**Why**

This catches text corruption before it's published, rather than letting broken or unreadable characters make it into a live artifact.

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

### New MCP tool wrapper explicitly refuses cross-machine session-channel tools

Trying to call another machine's session-owned MCP tool locally now fails with a clear error instead of silently misbehaving

**What**

When multiple machines are connected in a shared session and one machine owns a particular MCP tool (a tool exposed by a Model Context Protocol server), a new wrapper now catches attempts to run that tool from a different machine and throws a clear error explaining that the tool belongs to that other session and can't run locally.

**Why**

Previously such a call could fail silently or behave unpredictably; now the failure is explicit, making it obvious what went wrong instead of leaving the cause a mystery.

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

### Exported/imported session transcripts can now carry stop_reason 'tool_use'

Exported and re-imported session transcripts can now mark a message's stop reason as 'tool_use' instead of always 'end_turn'

**What**

When a session transcript is exported and later reimported, Claude Code rebuilds a synthetic version of each assistant message. The `stop_reason` field on that rebuilt message, which records why the model stopped generating, used to always be set to `end_turn`. It's now set to `tool_use` when the message includes a tool call, and `end_turn` otherwise.

**Why**

This makes reimported transcripts more accurate to what actually happened in the original session, since a message that ended because the model wanted to use a tool is now labeled as such rather than being misrepresented as a normal end of turn.

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

### Plugin install fails clearly when claude.ai login lacks plugin-access scope

Plugin install now gives a clear error when a claude.ai login lacks plugin-access permission

**What**

When installing a plugin from an archive, Claude Code now checks for a `skip_no_scope` credential result. If found, it raises a clear error: 'The plugin archive was not downloaded: this claude.ai login has not been granted plugin access yet. Start Claude Code interactively once, then try again.'

**Why**

This replaces a presumably more confusing failure with a specific explanation and a concrete fix, telling the user to start Claude Code interactively first so their claude.ai login can be granted plugin access.

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

### Bug fix: variable mismatch in remote-control policy check

Bug fix: remote-control permission check was reading the wrong variable

**What**

The check for the `allow_remote_control` policy was rewritten as a switch statement over the correct, properly-scoped variable, replacing a reference to a different, apparently mistakenly-named variable that looks like it was a leftover typo or scoping bug.

**Why**

This fixes a bug that could have caused the remote-control permission check to evaluate against the wrong value, potentially misjudging whether remote control should be allowed.

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

### Plugin/marketplace host checks can now report "no plugins scope" instead of throwing

Plugin and marketplace lookups can now report "no plugins scope" instead of erroring out

**What**

Two places that fetch plugin or marketplace metadata now check for a "skip, no scope" condition first. When it applies, they return a result marked `{status: "skipped", code: "no-plugins-scope"}` instead of proceeding as before, rather than throwing an error.

**Why**

This avoids failures when plugin access isn't scoped for the current context, giving a clear, handled outcome instead of an error.

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

### Retry logic now treats stream_idle_timeout like other transient errors

Retries now treat stream_idle_timeout the same as other transient network errors

**What**

The logic that decides whether to log and retry an error after a failed request used to recognize `connection_error`, `server_overload`, `api_timeout`, and `rate_limit`. It now also recognizes `stream_idle_timeout`, logging "API {type} after retries" and treating it the same way as those other transient errors.

**Why**

A connection that goes idle mid-stream is now handled like other temporary network hiccups, so it can be retried instead of surfacing immediately as a failure.

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

### Artifact title label distinguishes 'File' vs 'Artifact'

Artifact headers now correctly say 'File' for files and 'Artifact' for artifacts

**What**

The label shown above an artifact now reads "**File: **" when the item is a file, and "**Artifact: **" otherwise. Previously it always said "Artifact" regardless of kind, and the underlying code referenced an undefined variable, meaning the distinction never actually worked.

**Why**

This fixes a bug so that files and artifacts are now labeled correctly and distinguishably in their headers.

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

### Revoked-credentials cleanup now degrades gracefully on failure instead of dropping results

Revoked-credentials cleanup now returns a fallback result instead of nothing when it fails

**What**

When the cleanup process for revoked credentials fails, it used to return nothing at all, leaving callers with no information. Now, on failure, it returns a synthesized result that marks every credential name as revoked with a fixed cause code, giving callers something usable instead of an empty result.

**Why**

This means that if the cleanup process errors out, the rest of the system still gets a sensible, if pessimistic, answer to work with, rather than crashing or silently getting nothing back.

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

### Artifact preview now validates text encoding before rendering

Artifact preview now checks text encoding before trying to render a file

**What**

When previewing an artifact (an HTML or text file), Claude Code now runs the underlying bytes through a decoder that detects encoding problems before rendering. If the bytes can't be decoded, or decoding required inserting replacement characters, the preview now fails with a specific error (`preview_source_encoding` or `preview_source_replacement_char`) instead of blindly converting the bytes to text and possibly rendering garbled or misleading content.

**Why**

This prevents artifact previews from silently showing corrupted or mangled text when a file isn't valid UTF-8, surfacing a clear error instead.

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

### Diff-viewer 'show more files' toggle actually toggles now

The diff viewer's 'show more files' toggle is fixed so it can now be collapsed again, not just expanded

**What**

In the diff/checkpoint viewer, the toggle that expands a collapsed list of changed files to "show more" previously always forced the list open no matter its current state, because the underlying handler always returned `true`. It now correctly returns the opposite of the current state, so clicking it again collapses the list back.

**Why**

This fixes a bug where the file list could only ever be expanded, never collapsed back down, once you'd clicked "show more."

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

### Turn-interruption handling now recognizes 'caveat' messages to avoid duplicate placeholders

Interrupted-turn handling now recognizes trailing 'caveat' messages to avoid duplicate placeholders

**What**

When Claude Code detects that a turn was interrupted, it used to insert a placeholder marking the turn as incomplete. New logic now checks for a run of trailing "caveat" user messages, and if one is present, it either skips inserting that placeholder or treats the turn as already complete.

**Why**

This avoids showing a redundant or incorrect "interrupted" marker in the conversation when a caveat message already indicates how the turn ended.

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

### Bridge/remote-control session poller now recovers from 401s, not just 404s

Remote Control's background session poller now also recovers from expired credentials, not just missing environments

**What**

The background loop that polls for bridge/Remote Control sessions used to treat only a "not found" (404) response as a sign that it should re-register the environment. It now also treats an "unauthorized" (401) response the same way, using a separate backoff timer (`reregister401BackoffFloorMs`) for that case, and logs a different message about a renewed Remote Control credential rather than a re-registered environment.

**Why**

This lets a session recover automatically when its Remote Control credential expires or is rejected, instead of only recovering when the environment itself goes missing.

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

### Artifact publish preflight now recognizes a distinct "content_pending" refusal and auto-retries

Artifact publishing now auto-retries on a specific 'content_pending' server refusal, not just unrecognized errors

**What**

When publishing an artifact (a generated file or document Claude Code creates and sends to a server), the server can reject the request with an HTTP 422 error. The retry logic that double-checks and resends after such a rejection now specifically recognizes a `content_pending` error code from the server, using a new step that extracts the status code from the response. Previously it only had a generic fallback for 422 responses it didn't recognize.

**Why**

This makes automatic retries more reliable when the server reports the artifact's content simply isn't ready yet, rather than treating that case as just another unrecognized failure.

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

### Session-channel MCP tools now stub-error instead of silently misrouting

Calling a remote session's own MCP tools directly now fails with a clear error instead of misrouting

**What**

When working in a remote session, tools that belong to that session's own MCP servers (external tool connections tied to a specific machine) are now represented by a placeholder. If something tries to call one of these tools directly instead of properly routing the call to the right machine, it now throws a specific error instead of silently running incorrectly on the wrong machine.

**Why**

This turns a silent misrouting problem into a clear, catchable error, making it easier to notice and fix cases where a remote session's tools were being called the wrong way.

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

### CLAUDE_CODE_EXTRA_BODY can no longer inject the 'afk-mode' anthropic-beta

CLAUDE_CODE_EXTRA_BODY can no longer be used to inject the afk-mode beta header; only auto mode itself can send it

**What**

Claude Code now strips any `afk-mode` value out of the beta-feature list in a custom `CLAUDE_CODE_EXTRA_BODY` (an environment variable that merges extra fields into every API request). If you had set that beta yourself, it's now removed automatically with a warning, because only Claude Code's own auto mode is allowed to send it.

**Why**

This stops a custom request body from turning on behavior meant only for auto mode, which sends its own `afk-mode` beta header through the normal request path rather than through `CLAUDE_CODE_EXTRA_BODY`.

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

### Plugin symlink materialization now verifies link identity via stat, not just realpath

Plugin symlink handling now verifies file identity with a stat check, not just a path check

**What**

When Claude Code sets up a plugin's symlinks (shortcuts that point to another file), it now checks that the symlink and its resolved target are actually the same file, by comparing their inode and device numbers (low-level filesystem identifiers). A symlink is now rejected if it points somewhere different than it appears to resolve to, or if this identity can't be verified at all.

**Why**

This closes a gap where a symlink could pass an earlier path-based check while actually opening a different file than expected, tightening protection against symlink-based tricks in plugin packages.

- Area: Plugins Security
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Marketplace directory entries walked with lstat when realpath is unreliable, instead of being refused outright

Marketplace plugin directories with unresolvable paths can now still be scanned safely, instead of being rejected

**What**

If a plugin marketplace directory's path can't be reliably resolved to its real location (for example, because it contains a backslash on a non-Windows system), Claude Code no longer simply refuses to read it. Instead, it walks the directory tree one component at a time, checking each step to make sure it's a plain directory and not a symlink. Where the path can be resolved normally, entries are still checked by comparing their filesystem identity against the marketplace root, as before.

**Why**

This lets marketplaces with unusual but legitimate paths still work, while keeping the same protection against symlinks being used to escape the marketplace directory.

- Area: Plugins Security
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Plugin hooks module hot-reload now confirms the environment host survived before swapping in

Plugin hook hot-reload now checks the environment host survived before applying the new modules

**What**

When Claude Code hot-reloads plugin hook modules (updating them without a full restart), it now waits for the reload to finish and then checks whether the environment host process died partway through. If it did, the reload is aborted with an error instead of being committed.

**Why**

This prevents Claude Code from swapping in a set of reloaded hook modules against an environment that no longer exists, which could otherwise leave plugins in a broken or inconsistent state after a crash during reload.

- Area: Plugins
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Artifact-comment prompt tightened so a head marker can never carry trailing text on its own line

Artifact comment prompt now requires a head marker to stand alone on its own line, with no trailing text

**What

- Area: Artifacts
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Artifact tool_result files_error no longer marked is_error

Artifact files_error results no longer flagged as errors

**Unclear.** It is not stated what, if anything, now signals this failure to the model instead of `is_error`.

**What**

When an artifact operation fails with a files_error, the tool result returned to the model no longer carries the `is_error` flag that previously marked it as an error result.

**Why**

This changes how the model perceives a files_error case; without the flag, it may no longer be treated as a hard failure in the same way, though the finding does not say what replaces that signal.

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

### Artifact create-from-type now also rejects a `deadline` field

Creating an Artifact from a type_url now also rejects a stray deadline field

**What**

When an Artifact is created from a `type_url` (a type-based template), Claude Code already stripped out several fields that don't belong on that kind of creation, such as `url`, `pr_review`, `capabilities`, `contract`, `lang`, and `force`. Now `deadline` is rejected the same way.

**Why**

A type-based Artifact always gets its settings from its type, so a `deadline` value supplied alongside it would be meaningless or conflicting. Rejecting it keeps creation requests consistent and catches a mistake early instead of silently ignoring it.

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

### New auto-mode verdict message for tool calls truncated by the server

Auto-mode now explains when a tool permission check is missing because the model's reply was cut off

**What**

When Claude Code's automatic permission system (which decides whether a tool call needs to ask you first) can't get a verdict, it now shows a specific message when the cause was the model's response being truncated (cut off) mid tool-call, rather than a generic error. Several other distinct "no verdict" error codes were also merged into one shared code, `server_unavailable_error`.

**Why**

This gives a clearer explanation when a permission decision couldn't be made because the response was cut short, instead of a vague or misleading error.

- Area: Auto Mode
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Demo builds no longer show ant-only (internal) announcement banners

Demo builds of Claude Code no longer show Anthropic-internal-only announcement banners

**What**

Claude Code can show announcement banners in its status area, some of which are marked internal-only ('ant-only') and meant only for Anthropic staff. Demo builds of the app now always get an empty list for those internal-only announcements, so they're never shown.

**Why**

This prevents internal-only banners meant for Anthropic employees from leaking into demo instances shown to others.

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

### Marketplace entry-path validation now flags backslash-containing paths

Marketplace path validation now also rejects paths containing backslashes

**What**

When a plugin marketplace entry's file path fails Claude Code's containment check, the explanation now also flags paths containing backslashes as invalid, in addition to the previously flagged absolute paths, paths that climb out of their directory, network-shaped paths, and paths that traverse symlinks.

**Why**

This closes a gap where a backslash-containing path could otherwise slip past validation meant to keep marketplace entries confined to their intended directory.

- Area: Plugins Security
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Tool-call argument spoofing guard for internal artifact keys

Tool calls carrying a spoofed internal '__artifact' argument key are now denied

**What**

Claude Code now denies any tool call whose arguments include a key starting with `__artifact`, unless that particular tool is one known to legitimately set such keys itself. The denial message reads: 'Nothing was done. The arguments carry a key that only Claude Code sets.'

**Why**

`__artifact` keys are meant to be set internally by Claude Code itself, not supplied by a tool call's arguments. Blocking spoofed values for these keys prevents a tool call from impersonating internal state it shouldn't have access to.

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

### Pointer capture released when alt-screen is torn down or handed off

Mouse click capture is now cleaned up when the terminal's alternate screen is torn down or handed off

**What**

Claude Code's terminal renderer uses an "alt screen" (a separate full-screen display terminals use for interactive apps). When that alt screen is handed off (`handoffAltScreen()`) or deactivated, Claude Code now calls `endPointerCapture()` and `tellPressedNowhere()` before resetting terminal modes and repainting.

**Why**

This cleans up any stuck mouse-press or pointer-capture state left over from the alt screen, preventing leftover mouse interaction state from carrying over incorrectly after the screen is torn down or handed off.

- Area: Terminal UI
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

### Bug fix: SIGINT cleanup guard flag was setting the wrong variable

Fixed a bug where Ctrl-C cleanup for MCP servers checked one variable but set a different one

**What**

When Claude Code handles Ctrl-C (SIGINT) to shut down MCP servers, the cleanup code used a guard flag to prevent the cleanup from running twice. Due to a bug, it checked one variable but set a different, unrelated one, so the guard never actually took effect. It now correctly sets the same flag it checks.

**Why**

This fixes a bug that could have allowed MCP server cleanup on Ctrl-C to run more than once instead of being properly guarded against double execution.

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

### Skill verification bug fix: correct variable used in has() check

Bug fix: skill verification was checking the wrong variable's set

**What**

A short-circuit check used during skill verification now checks the set that was actually just built for that check, instead of mistakenly checking a different, out-of-scope variable.

**Why**

This fixes a bug where the verification step could have skipped or misjudged skills incorrectly because it was looking at the wrong data.

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

### Speaker-label merging now walks back over multiple consecutive labelled replies

Speaker-label grouping in transcripts now walks back over several consecutive labelled replies, not just one

**What**

When Claude Code figures out where a block of speaker-labelled messages begins in the transcript, it now keeps stepping backward through as many consecutive 'labelled reply' messages as there are, using a new helper. Before, it would only ever step back a single position.

**Why**

This fixes grouping so that a run of several consecutive labelled replies is treated as one connected block instead of only the last two being linked, giving more accurate speaker-label boundaries in longer transcripts.

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

### Windows-style backslash path segments now flagged as suspicious on non-Windows platforms

Paths containing backslashes are now flagged as suspicious on non-Windows systems

**What**

A path-safety check now also treats a path as unsafe if it contains a backslash (`\`) while running on an operating system other than Windows, in addition to its existing checks.

**Why**

Backslashes are normal path separators on Windows but not on other systems, so seeing one outside Windows can indicate a path is being spoofed or manipulated; flagging it helps catch that kind of attack.

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

### File-read permission pre-check for bash-tool args now aggregates all failures instead of stopping at first mismatch

Bash command permission checks now report every problematic file argument, not just the first one found

**What**

When Claude Code checks whether a bash command's file arguments are covered by your allowed read paths, it used to stop and report as soon as it hit the first argument that failed the check. It now keeps checking every argument and reports the first problem found only after examining them all. It also now skips paths that already match an allowed pattern before falling back to checking whether the file actually exists on disk.

**Why**

This makes the permission check more thorough and consistent, so it doesn't miss other problematic arguments in the same command just because it stopped early, while still avoiding unnecessary filesystem checks for paths already known to be allowed.

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

### Relaunch/spawn paths now explicitly uninstall a stdout write hook before exec/kill

Relaunch and suspend/resume paths now explicitly remove a stdout write hook first

**What**

Before relaunching the CLI as a child process, and before resuming after the process is suspended and continued (`SIGTSTP`/`SIGCONT`), Claude Code now explicitly calls a helper to uninstall a previously-installed hook that intercepts writes to standard output. Previously these paths either skipped this step or used a different, non-equivalent function.

**Why**

This avoids leaving the stdout interceptor installed across a relaunch or a suspend/resume cycle, which could otherwise interfere with output in the new process or after resuming.

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

### tengu_sdk_session_crash telemetry now logs the actual caught error

SDK session crash telemetry now logs the actual error that caused the crash

**What**

The `tengu_sdk_session_crash` telemetry event now serializes and logs the exception that was actually caught, instead of an apparently unrelated variable that was being logged before.

**Why**

This fixes the crash telemetry so it captures the real error, making it more useful for diagnosing why an SDK session crashed.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Connector registry errors no longer double-wrapped

Connector registry errors are no longer stripped of their original message when re-thrown

**What**

When looking up or searching connectors (integrations Claude Code can use, such as external tools registered with it) fails, the error handling now checks whether the error is already the registry's own error type. If it is, that original error is passed through as-is. Previously, it would always be caught and wrapped in a brand-new generic error, which lost the original error's message and type. The classes and logger involved were also renamed internally.

**Why**

This means that when something goes wrong with connector lookups, the actual underlying error message is preserved instead of being replaced with a generic "Connector registry is unavailable right now" message, making the real cause easier to see.

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

### refresh() now always clears the on-disk cache, even when ineligible

Policy-limits cache file is now deleted on every refresh, even for accounts not eligible for limits

**What**

When Claude Code refreshes its internal policy-limits data, it now always clears the on-disk cache file and drops any unconfirmed session cache, no matter whether the account currently qualifies for policy limits. Previously, if the eligibility check failed, the whole refresh step was skipped and the old cache file was left in place. Now only the reload-and-log step that follows is skipped for ineligible accounts; the cache deletion always happens.

**Why**

This prevents a stale cache file from lingering on disk when an account's eligibility status changes, so a later refresh cannot accidentally read outdated policy-limits data.

- Area: Policy Limits
- Tier: You'll notice
- Useful: 1/5
- Signal: 1/5

## In Development

### SDK/headless sessions get an explicit rejection for compact()

Calling compact() in headless SDK sessions now returns a clear rejection instead of silently doing nothing

**What**

Headless sessions, meaning ones run with `-p` or through the SDK without the interactive terminal interface, now expose a `compact()` method, but calling it currently always fails with an explanatory error. That's because compaction in headless mode currently only happens inside a turn, triggered by a `/compact` prompt, not through a separate method call.

**Why**

This gives headless and SDK users a clear, catchable error explaining that `compact()` isn't available yet in that mode, instead of it failing silently or behaving unpredictably, so they know to work around it for now.

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

### Session ID derivation can now use a stable address scheme, behind tengu_session_stable_address

A new stable-address scheme for session IDs is gated behind tengu_session_stable_address

**Unclear.** The finding doesn't say what a stable address scheme changes about session behavior for users, and the tengu_session_stable_address gate is unread so its default/rollout state can't be reported.

**What**

A new internal check reads the `tengu_session_stable_address` setting and uses it in several places that determine session IDs and derived secrets, such as choosing whether to hash a value or generate random bytes, and whether a 'derived' source should still be treated as valid.

**Why**

This lays groundwork for an alternate, more stable way of deriving session identifiers, without yet describing what changes for users when it's active.

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

### New MCP passthrough-tool adoption pipeline behind adoptMcpOverChannelSwitchOn

New pipeline decides whether MCP tools are 'adopted' as passthrough tools

**What**

The setup logic for remote tools has been reworked to add a pipeline that decides whether tools from an MCP (Model Context Protocol) server get "adopted" as passthrough tools, meaning forwarded through directly rather than wrapped. It computes a `machineMcpToolsPolicy` of allowed, denied, pending, or unavailable, based on whether the MCP server was blocked at connect time. Adoption only happens when remote tool forwarding is enabled, a new switch called `adoptMcpOverChannelSwitchOn` is on, the policy is "allowed", and the tool isn't otherwise disabled.

**Why**

This adds a more careful, multi-condition check before letting an MCP server's tools bypass normal wrapping, which affects how such tools are permissioned and surfaced.

- Area: MCP
- Names: `adoptMcpOverChannelSwitchOn`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### New 'plan mode classifier' gate controls whether plan mode is eligible for classifier-based permission checks

A new flag will control whether plan mode gets classifier-based permission checks

**Unclear.** Nothing has been read yet about whether the `tengu_violin_plan_classifier` flag that controls this is on or off by default.

**What**

A new internal check now decides whether plan mode is eligible for a permission path that uses a classifier (an automatic decision step) to determine whether a tool call is allowed. By default this check returns false for plan mode, meaning plan mode is excluded from that path unless a specific feature flag is enabled.

**Why**

This lets Claude Code control, per account, whether plan mode uses the newer classifier-based permission logic or the existing path, without requiring a full release to change the behavior.

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

### Plan-mode permission mode gated behind a classifier flag

Selecting plan mode now runs through a new classifier check

**Unclear.** Nothing has been read yet about the `tengu_violin_plan_classifier` or `tengu_violin_mute` gates, so it's unclear what governs this check or its practical effect on using plan mode.

**What**

When Claude Code decides whether "plan" is a valid permission mode to switch into, it now first checks a new gate before allowing it, in addition to the existing validation logic.

**Why**

This adds an extra decision point specifically for plan mode, though what conditions the classifier evaluates isn't described.

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

### Remote-control 'safeguards' verification channel is built but its checklist is empty

A new 'safeguards' remote-control security channel exists but its rule list is empty, so it currently blocks nothing

**What**

Claude Code's remote-control feature, which lets a paired bridge client send control commands, gains a new 'safeguards' category alongside the existing remoteTools, hooks, and plugins categories. It has its own machinery meant to flag `apply_flag_settings` requests that try to weaken specific protected settings.

However, the actual list of settings this category checks is hardcoded to be empty, and the feature is hardcoded to be off regardless of any remote flag.

**Why**

The scaffolding for this protection exists in this build but has no effect yet: it currently guards nothing. It's worth knowing this exists in case it's activated in a future release, but it should not be relied on today.

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

### Artifact publish gains a `deadline` field, gated by schema capability

Artifact publishing can now include a deadline, gated behind a capability check

**Unclear.** The finding does not say what the deadline value controls in practice or when `deadlineDropped` would be set.

**What**

When publishing an artifact, requests can now include a `deadline` value, which is passed through to the create, update, and live-document publish operations. The publish response can echo the `deadline` back, along with a `deadlineDropped` flag if it wasn't honored, and two new fields, `seq` and `unchanged`. The `deadline` field itself (accepting a value like "now", a named value, or a date string) only appears in the artifact tool's schema when a gate is turned on.

**Why**

This lets artifact publishing express a time constraint on when a publish should take effect or expire, with the response able to confirm whether that deadline was actually applied.

- Area: Artifacts
- Names: `deadline`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### New "heli" artifact template kind

Artifacts gain a new 'heli' template kind alongside existing ones like pr_review and whiteboard

**Unclear.** What 'Heli' is and what the 'heli' template kind produces or is used for isn't explained in the finding.

**What**

When publishing an artifact, Claude Code can now resolve a template kind called `heli`, joining the existing kinds `pr_review`, `workshop`, `whiteboard`, `prototype`, and `plain`. A new capability object checks whether the page or slug being published is bound to Heli, and if so, a `noteHeliPublish` call records the publish event.

**Why**

This adds support for a new artifact template type, though the finding doesn't explain what Heli is or what this template kind is used for.

- Area: Artifacts
- Names: `heli`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5

### GitHub-connect push offer, dark-launched behind tengu_reflective_bee

A new dialog can offer to connect GitHub to claude.ai after a git push, not yet confirmed live

**Unclear.** Whether this dialog is actually shown to any users yet is unknown, since the feature flag tengu_reflective_bee has not been read.

**What**

Claude Code now has the machinery for a new prompt that can appear after you push to git: a dialog asking "Connect GitHub to claude.ai so you can work on this repo even when this machine is offline?" It keeps track of whether you've dismissed it permanently, how many times it's been shown, and when it last appeared, so it doesn't nag repeatedly.

**Why**

This would let you pick up work on a repository from claude.ai even when your own machine is off, by linking GitHub access ahead of time. The underlying feature flag for this has not been read yet, so it isn't known whether it's active for any given account.

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

### Live-doc read schema gains seq/unchanged/deadline fields, gated off by default

Live document reads gain new fields for tracking update sequence and a gated deadline option

**What**

The response format for reading a live artifact (a document that can update in place) now includes `seq` and `unchanged` fields, which appear to support a 'hot update' style read where the client can tell whether the content has changed since it last checked. A `deadline` field (with a related `deadlineDropped` field) is also part of the format, but only appears when a setting called `tengu_copper_hinge_wren` is turned on.

**Why**

These fields let Claude Code check for updates to a live document more efficiently, without necessarily re-fetching or re-rendering the whole thing when nothing has changed.

- Flag `tengu_copper_hinge_wren`: Not enough to say (read for one account on one subscription tier against v2.1.267; this account: no value returned, anonymous baseline: no value returned, compiled default: on)
- Area: Artifacts
- Names: `tengu_copper_hinge_wren`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 3/5
- Present in the build but not switched on

### MCP tool 'passthrough adoption' telemetry and policy gating added to remote-tools announce handling

Remote MCP tool announcements now report whether a worker adopted the machine's tools directly or declined them

**What**

When a worker machine announces its remote tools (tools from an MCP server, a way of plugging external tools into Claude), the handling code now works out whether the worker adopted those Model Context Protocol tools directly instead of routing them through the device bridge. The outcome is recorded as either `passthrough_adopted` or `passthrough_declined`, with a reason of `policy`, `pending`, or `unavailable` for the declined case. This outcome is now included in the acknowledgement sent back for the announcement.

**Why**

This gives better visibility into how a worker's tools ended up being routed, which matters for diagnosing why a given MCP tool is or isn't available through a particular connection.

- Flag `tengu_violin_wood`: Off in both readings (read for one account on one subscription tier against v2.1.267; this account: off, anonymous baseline: off, compiled default: on)
- Area: MCP
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### projectsOwnerRowsForwarding: owner-row credit forwarding gated behind NPt()/vsr()

A new owner-row credit-forwarding feature for auto mode is gated behind conditions and disabled in nested or teammate sessions

**Unclear.** The finding does not say what the forwarded credit is used for or who receives it.

**What**

A new internal feature, referred to as "projects owner rows forwarding," forwards credit for rows that come from queued commands or attachments authored by an "owner," tagged with the telemetry label `auto_mode_projects_owner_rows`. It only runs when two internal conditions are both true, and it's automatically disabled when the session has an agent ID, a teammate context, a certain session-state result, or the `CLAUDE_CODE_CHILD_SESSION` environment variable set (which marks a session as a subprocess Claude Code itself spawned).

**Why**

Disabling this forwarding in nested, teammate, or child sessions keeps credit attribution from being duplicated or misapplied when a command runs somewhere other than the top-level session that queued it.

- Area: Telemetry
- Names: `CLAUDE_CODE_CHILD_SESSION`
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### Own-endpoint-shadowed detection for /list-agents, gated by tengu_session_stable_address

/list-agents can now detect when another process is already using this session's own address

**Unclear.** Nothing has been read yet about whether the `tengu_session_stable_address` flag that controls this is on or off by default.

**What**

A new check detects when another live process on the same machine is already listening on the socket that represents this session's "stable address" (its identity), even though it's a different process. When that happens, the `/list-agents` (also `/peers`) output changes which address token it displays for this session's own entry, to reflect that its usual address is shadowed by the other process.

**Why**

Without this, a session could display an address for itself that's actually claimed by a different, unrelated process, making it confusing or unreliable for another session to message it correctly.

- Area: Sessions
- Names: `/list-agents`, `/peers`
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### Agent-intent forwarding gains owner-crediting and can be fully disabled

Agent-intent forwarding for queued commands now supports crediting an owner and is off by default unless explicitly configured

**Unclear.** It's not clear what user-facing feature or workflow this owner-crediting configuration is meant to support.

**What**

The internal mechanism that forwards queued commands as "agent intent" now accepts a configuration object with `credited`, `readResults`, `ownerOnly`, and `creditOwner` options. By default, unless a configuration is explicitly passed in, this forwarding is disabled. When active, forwarded turns are now tagged in telemetry with `ownerTurns` and `ownerOnly` information.

**Why**

This appears to be groundwork for attributing forwarded agent actions to a specific owner and controlling whether only the owner's commands are forwarded, though the finding doesn't specify a user-facing feature this enables yet.

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

### Model-catalog shadow-compare fetch: network access hardcoded on, feature gated off by default

A background model-catalog comparison check now always has network access, though the feature stays off by default

**Unclear.** Whether this gate is enabled for any given account isn't known; nothing has been read yet about the tengu_delegated_quail or tengu_model_catalog_compare gates.

**What**

A startup routine that fetches and compares a "served" model catalog now always allows network access for that specific call, where previously network access depended on whether Claude Code was running in headless mode. A separate, sibling network call keeps the old headless-aware behavior unchanged. The comparison call itself still only runs if a related setting isn't turned off, and that setting is off by default unless a number of other conditions (such as environment overrides, non-first-party or non-claude.ai accounts, missing organization, or policy) also allow it.

**Why**

This is an internal check Anthropic uses to compare model catalog data; for most users the feature remains gated off, but when active it can now always reach the network, regardless of headless mode.

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

### Symlinked settings-path writes get a fallback, currently disabled

A fallback for writing settings through symlinked paths exists in code but is currently inactive

**What**

A new internal helper for writing settings files now catches a specific symlink-related failure and, in that case, checks a condition before retrying the write with symlinks allowed. However, that check currently always returns false, so the retry path never actually runs.

**Why**

This has no effect for users yet: writing settings through a symlinked path still fails the same way it did before, since the fallback is inactive.

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

### New gate tengu_fizzy_bonbon in fast-mode permission path

A new gate affects how fast-mode tool permissions are resolved

**Unclear.** Nothing has been read about the `tengu_fizzy_bonbon` gate, so what the alternate permission-resolution logic actually changes is unclear.

**What**

A new feature gate, `tengu_fizzy_bonbon`, now guards an alternate branch of logic in the fast-mode tool-permission path, defaulting to off.

**Why**

This is internal permission-handling logic; the finding doesn't specify what the alternate logic does differently when enabled.

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

### New env var forwarded for memory-context system reminders

New SYSTEM_REMINDER_MEMORY_CONTEXT environment variable can force-enable background memory fetches

**Unclear.** Whether this variable is meant for general use or is an internal/testing override is not stated.

**What**

A new environment variable, `SYSTEM_REMINDER_MEMORY_CONTEXT`, is now included in two lists of environment variables that Claude Code passes through or preserves. Setting this variable can also force a background feature that fetches memory context (information carried over between sessions) to run, even in cases where it would normally be turned off.

**Why**

This gives a way to force on the memory-context fetch behavior for testing or specific setups, bypassing the normal gating for it.

- Flag `tengu_misty_anchor`: Off in both readings (read for one account on one subscription tier against v2.1.267; this account: off, anonymous baseline: off, compiled default: on)
- Area: Memory
- Names: `SYSTEM_REMINDER_MEMORY_CONTEXT`
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### Forwarded agent intents can be restricted to owner-only turns with credit tracking

Forwarded agent context can now be restricted to the owner's own turns, with credit tracking

**What**

The mechanism that forwards recent conversation context to a spawned subagent can now be configured to mark which forwarded turns came specifically from the "owner," and to restrict forwarding to owner-only turns. This is off by default. When turned on, it tracks which turns have already been credited and adds `ownerTurns` and `ownerOnly` fields to the telemetry and to the attached forwarded content.

**Why**

This gives finer control over whose conversation turns get shared as background context with a subagent, which matters in settings where turns come from multiple sources and only the owner's input should be passed along.

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

### Compaction can skip message cache markers, gated by tengu_groovy_eclipse

Compaction can now skip cache markers on messages, controlled by a feature flag

**What**

When Claude Code compacts (summarizes older parts of) a conversation, it can now skip attaching cache markers to messages under certain conditions. This is controlled by the `tengu_groovy_eclipse` feature flag together with another internal condition.

**Why**

Cache markers normally help avoid recomputing parts of a conversation, so skipping them in some compaction requests is likely a tuning change to how compaction interacts with caching, though the practical effect for a user isn't detailed.

For this site's account, and for the anonymous baseline, `tengu_groovy_eclipse` is reading on, though that reading was not taken under this release.

- Flag `tengu_groovy_eclipse`: On for this account, and not off by default (read for one account on one subscription tier against v2.1.267; this account: on, anonymous baseline: on, compiled default: on)
- Area: Compaction
- Names: `tengu_groovy_eclipse`
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### New tengu_fizzy_bonbon gate branches the auto-mode tool-permission-context flow

A new feature flag branches how auto-mode establishes tool permission consent

**Unclear.** What behavioral difference exists between the two permission-context paths, and whether tengu_fizzy_bonbon is active anywhere, is not known.

**What**

In the streaming path used by Claude Code's auto mode, a new feature flag, `tengu_fizzy_bonbon`, now decides between two different ways of establishing tool permission context, the mechanism that determines whether Claude Code has consent to run a given tool.

**Why**

This looks like an internal restructuring of how permission consent is established during auto mode, but nothing is known yet about which path is active or what changes for the user in practice.

- Area: Auto Mode
- Names: `tengu_fizzy_bonbon`
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### Session-served ('bridge') MCP tool routing gains a 'not yet presentable' refusal path

MCP tools served through a session bridge can now be refused as 'not yet presentable' instead of silently falling through

**What**

When Claude Code routes a call to an MCP tool (a tool provided by an external MCP server) served through a session bridge, it now checks a per-session record of that tool's state. If the tool is registered but its provider reports it isn't ready to be shown yet, the call now returns a `not_served` error directly, rather than falling through to try local or remote dispatch as it did before.

**Why**

This should prevent Claude Code from attempting to use a bridge-served tool before it's actually ready, giving a clearer error instead of an unpredictable fallback attempt.

- Flag `tengu_violin_wood`: Off in both readings (read for one account on one subscription tier against v2.1.267; this account: off, anonymous baseline: off, compiled default: on)
- Area: MCP
- Tier: Nothing to try yet
- Useful: 2/5
- Signal: 3/5
- Present in the build but not switched on

### New "deadline" parameter for artifact republishes (hot mode)

Artifact republishes can now set a "deadline" to force older running copies to stop

**What**

When republishing an artifact (an update to something already published, sometimes called "hot" mode), the artifact tool's prompt now documents an optional `deadline` field. It accepts values like `"now"`, `"15m"`, `"1h"`, `"24h"`, `"7d"`, or a specific ISO timestamp, and forces older running copies of the artifact to stop by that time. This is gated behind a schema flag (`hotOn`), and the field only applies to republishes, not ordinary edits, where it should be omitted.

**Why**

This gives control over how long an outdated running copy of a republished artifact is allowed to keep running before it's shut down, rather than leaving that unbounded.

- Area: Artifacts
- Names: `deadline`
- Tier: Nothing to try yet
- Useful: 3/5
- Signal: 2/5
- Present in the build but not switched on

### New feature gates: tengu_groovy_eclipse and tengu_lucky_quill

Two new internal feature gates were added: tengu_groovy_eclipse and tengu_lucky_quill

**What

- Flag `tengu_groovy_eclipse`: On for this account, and not off by default (read for one account on one subscription tier against v2.1.267; this account: on, anonymous baseline: on, compiled default: on)
- Flag `tengu_lucky_quill`: Not enough to say (read for one account on one subscription tier against v2.1.267; this account: no value returned, anonymous baseline: no value returned, compiled default: off)
- Area: Elsewhere
- Names: `tengu_groovy_eclipse`, `tengu_lucky_quill`
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5
- Present in the build but not switched on

### Diff panel visibility gains a currently-dead build flag

Diff panel visibility check gains a new condition that currently has no effect

**What**

The logic deciding whether to show the diff panel in the terminal's status/footer area now also checks a new function, but that function is hardcoded to always return `false`, so the new condition is always satisfied and changes nothing yet.

**Why**

This appears to be groundwork for a future change to diff panel visibility that isn't active in this build.

- Area: Diff Viewer
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5
- Present in the build but not switched on

### New CCR telemetry gate: upload hold marker

New telemetry gate can add upload-hold details to Claude Code Remote's upload data

**What**

A new setting controls whether CCR (Claude Code Remote, the cloud runner) upload requests include an `upload_hold` block of extra details: whether the upload is being held, why it would be flushed, how many times it has been held, how long it has been held, how many retries are in flight, which hold rule applied, and its position in the post sequence. When this is on, a new `ccr_upload_drain` telemetry event is also emitted; when off, none of this happens.

**Why**

This gives more visibility into how CCR queues and holds uploads before sending them, which can help diagnose delayed or stuck uploads.

- Flag `tengu_ccr_upload_hold_marker`: Not enough to say (read for one account on one subscription tier against v2.1.267; this account: no value returned, anonymous baseline: no value returned, compiled default: on)
- Area: Telemetry
- Tier: Nothing to try yet
- Useful: 1/5
- Signal: 2/5
- Present in the build but not switched on

### CLAUDE_CODE_REMOTE_TOOLS_SERVE env var read but the function reading it has no in-bundle caller

An unused function still reads the CLAUDE_CODE_REMOTE_TOOLS_SERVE environment variable

**Unclear.** Whether this is dead leftover code or a function awaiting a caller that will be added later is not stated.

**What**

A function that checks the environment variable `CLAUDE_CODE_REMOTE_TOOLS_SERVE` (treating it as true if it's unset) exists in the code, but nothing else in the current build actually calls that function.

**Why**

This has no visible effect right now since the function is never invoked. It may be leftover from removed functionality or preparation for something not yet wired up.

- Area: Remote Tools
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5
- Present in the build but not switched on

### New no-proxy host list defined but not selected anywhere nearby

A new no-proxy host list was added but nothing currently selects it

**Unclear.** Whether `$o` is unfinished groundwork for a future option or simply unused isn't stated.

**What**

Three lists of hosts that should bypass a proxy were added to the code that governs when Claude Code's agent proxy activates: one for bare localhost-type addresses, one adding private network ranges, and a third, `$o`, covering only link-local and cluster-local addresses. The logic that picks which list to use references the first two but never picks the third.

**Why**

Since nothing currently selects the new `$o` list, it has no effect yet. It may be groundwork for a proxy-bypass option that isn't wired up in this build.

- Area: Internals
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5
- Present in the build but not switched on

### Symlinked-settings-write fallback is permanently dead code

A fallback for writing settings through a symlinked path can never actually run

**What**

A new helper function for writing settings files is meant to retry the write in a special way when the settings path is a symlink (a file that points to another location) and a permission error occurs. But the check it relies on to detect that case always returns false, so this retry path, along with its log message "Writing settings through symlinked path," can never execute. Any write that hits this permission error just fails with the original error instead.

**Why**

Anyone whose settings file is a symlink and who hits this specific permission error will simply see the write fail, since the intended fallback never gets a chance to run.

- Area: Settings
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5
- Present in the build but not switched on

### New event-filter no-op hook `oe(i)` added on every bridge session frame

A new but currently empty hook now runs on every frame of a bridge session's event stream

**Unclear.** What this hook is intended to do once implemented is not stated in the finding.

**What**

Every incoming frame on a bridge session's communication channel now passes through a new function before the existing verification logic runs. In this build, that function does nothing (it has an empty body).

**Why**

Since the function is currently a no-op, there is no visible effect on behavior yet. It appears to be scaffolding for a filtering or inspection step that isn't active in this release.

- Area: Remote Control
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5
- Present in the build but not switched on

## Internal Changes

### New "sec-default" hooks module locks plugins out of classic hooks/prompt/settings/tool policy for managed orgs

A new sec-default hooks module blocks plugins from bypassing policy settings and MCP server allowlists on managed and Team/Enterprise accounts

**What**

On machines with managed settings, or in Team and Enterprise organizations, Claude Code now loads a built-in hooks module called `sec-default` that sits outermost in the chain of hooks (small handlers that run at specific points during a session) that plugins can register. It watches plugin actions like registering or listing tools, offering or spawning subagents, and describing tools or commands, and blocks non-core plugins from:

- reading policy settings they shouldn't have access to

- adding MCP servers (external tool providers) outside what your `allowedMcpServers` or `managedMcpServers` policy allows

Organizations can turn this off with a managed `secDefault: false` policy setting.

**Why**

This closes a path where a plugin could work around your organization's tool and MCP server policy. If you're on a managed or Team/Enterprise account, this module runs automatically, and a blocked attempt shows a message like "allowedMcpServers (managed): plugins outside policy may not add tools" unless the policy has explicitly disabled it.

- Area: Plugins Security
- Tier: Under the hood
- Useful: 3/5
- Signal: 3/5

### New sandboxed renderer lets plugin UI components (Button/Input/Select) safely rewire closures, plus a reworked hook-chaining framework with call-count throttling

Plugin UI components like Button, Input and Select now run in a sandboxed renderer that safely reattaches event handlers

**What**

Plugins that render their own UI (using components like `Button`, `Input` and `Select`) now go through a new sandboxed renderer. When a plugin's UI tree is built, its event handlers (like `onPress` on a `Button`, or `onInput`/`onSubmit` on an `Input`) get frozen and passed across a sandbox boundary, then safely reattached ("rewired") afterward so they still work.

Alongside this, the underlying system that lets plugins chain together hooks (functions that run in response to events, using an `on(event).catch()` style registration) was reworked. Each hook now has a call-count limit, and once a hook is called too many times it is throttled, with a one-time warning logged.

**Why**

This lets plugin-authored UI safely run in a restricted sandbox without losing the ability to respond to clicks, typing, and submissions, while the call-count throttling guards against a misbehaving hook being invoked in a runaway loop.

- Area: Plugin UI
- Tier: Under the hood
- Useful: 3/5
- Signal: 3/5

### New session type: hermetic remote sessions

A new 'hermetic remote sessions' session type can restrict certain features, like sandboxed or unpinned-gateway sessions already do

**Unclear.** The finding doesn't describe what a hermetic remote session is or which features it restricts.

**What**

Claude Code now recognizes 'hermetic remote sessions' as a session type that some features can be unavailable in, joining existing restriction reasons like `sandboxed_entrypoint` and `unpinned_gateway`.

**Why**

This means that when running in a hermetic remote session, a reader may see certain features reported as unavailable specifically because of that session type, similar to existing restrictions in sandboxed or unpinned-gateway sessions.

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

### New "safeguards" permission-context capability

Permission settings gained a new 'safeguards' flag alongside remote tools, hooks, and plugins

**What**

The internal record that tracks which capabilities are permitted in a given context (previously covering `remoteTools`, `hooks`, and `plugins`) now also tracks a fourth setting called `safeguards`. It is wired into the same on/off machinery, meaning both the "everything enabled" default and the "everything disabled" fallback now account for it.

**Why**

The `safeguards` flag controls whether the model's safety/safeguards classification data gets attached to a request. Having it as its own toggle means this data can be turned on or off independently of remote tools, hooks, and plugins, rather than being bundled with them.

- Area: Permissions
- Names: `safeguards`
- Tier: Under the hood
- Useful: 3/5
- Signal: 3/5

### Remote control now filters/strips forwarded plugin and safeguard settings per capability

Remote control now strips plugin and safeguard settings from forwarded requests unless explicitly permitted

**What**

A new capability-filtering layer governs `apply_flag_settings` requests arriving over a remote-control (bridge) connection. It can strip out a forwarded plugin marketplace key and any 'safeguard' settings from the request unless the connection's capabilities explicitly allow them. A new default-capabilities object turns off `remoteTools`, `hooks`, `plugins`, and `safeguards` by default. The transport layer's event filter also now runs an additional check and drops frames that fail a new unverified-session-channel check.

**Why**

This tightens what a remote bridge connection can change by default, so a connection has to explicitly be granted permission before it can alter plugin or safeguard-related settings, reducing the risk of a remote client silently weakening protections.

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

### Security-default hooks module locked to managed/Team-Enterprise settings

A locked-down 'Security default' hooks module restricts what installed plugins can touch

**What**

Claude Code adds a built-in hooks module (hooks are scripts that run automatically at certain points, like before a tool runs) called "Security default." It can only be turned on through settings that are marked as trusted or set by an organization's policy, not by a user or a plugin. Its purpose is to keep an organization's own hooks, prompt content, settings, and tool policy safe from plugins that a user installs on their own.

**Why**

This closes off a path where an installed plugin could otherwise interfere with security controls an organization has already put in place, keeping that boundary under organizational control rather than the individual user's.

- Area: Plugins Security
- Names: `secDefault`
- Tier: Under the hood
- Useful: 3/5
- Signal: 3/5

### New 'safeguards' trust category added to the remote-io flag-settings filter, with skip reporting

Remote connections get a new 'safeguards' trust category that blocks unverified attempts to disable protections

**What**

The system that governs which settings a remote, potentially untrusted connection is allowed to change now has a fourth trust category called `safeguards`, joining the existing `remoteTools`, `hooks`, and `plugins` categories. It's used to decide whether an unverified remote peer can turn off Safeguards through the `apply_flag_settings` mechanism. Any attempt to lower safeguards below a floor that can't be verified is now dropped and logged.

**Why**

This closes a gap where an untrusted remote connection could otherwise weaken safety protections; unverifiable attempts to do so are now blocked and recorded rather than silently applied.

- Area: Remote Control
- Names: `safeguards`
- Tier: Under the hood
- Useful: 3/5
- Signal: 3/5

### Model-capability lookup can now explicitly force fast_mode/lean_prompt/thrifty_sonic/mid_conv_tool_change/refusal_fallback off

Model capability settings like fast_mode and lean_prompt can now be explicitly forced off, overriding model-name guesses

**What**

The shared internal logic that looks up model capabilities can now distinguish an explicit "off" setting from one that was simply never set. Features that use this lookup, including `fast_mode`, `lean_prompt`, `thrifty_sonic`, `mid_conv_tool_change`, and `refusal_fallback`, now turn off immediately when told to, instead of falling back to guessing based on the model's name (for example, matching strings like `opus-4-8`).

**Why**

Previously these features could only be disabled by relying on name-matching heuristics against the model name, which could misfire for new or renamed models. An explicit override removes that guesswork.

- Area: Model Capabilities
- Tier: Under the hood
- Useful: 2/5
- Signal: 3/5

### Subagent completion result now carries a 'handback' payload

Subagent completion results now carry a 'handback' payload for non-top-level agents

**Unclear.** The finding doesn't say what the `handback` payload contains or what consumes it.

**What**

When a subagent's task finishes, the result now includes new `handback` and `handbackInterim` values. `handback` is populated only when the task isn't a top-level agent, and `handbackInterim` reflects whether telemetry is currently suppressed.

**Why**

This is internal plumbing whose purpose isn't detailed in the finding, but it suggests subagents can now pass structured data back up when they finish, distinct from top-level agent completions.

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

### Conversation now tracks its own "origin" (local vs remote)

Claude Code now tracks whether a conversation originated locally or was resumed from a remote session

**Unclear.** What behavior differs based on this origin tracking, beyond restoring frame/artifact state, isn't detailed.

**What**

Claude Code now keeps track of a conversation's "origin" — whether it started locally on this machine or came from a remote (resumed) session. Specifically:

- Resetting a conversation now records the previous origin and resets the origin to `"local"`.

- Resuming a session threads an `initialMessagesOrigin` value (`"local"` or `"remote"`) through app setup, and stores a `conversationOrigin` on the conversation, used when restoring window/artifact state after a resume or rewind.

- When resuming a session pulls in existing messages, the result now also reports `messagesOrigin: "remote"`.

**Why**

This lets Claude Code distinguish state that originated on this machine from state pulled in from a remote session, which matters for correctly restoring things like open artifacts after a resume or rewind.

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

### New sub-agent 'veto under prompt' tracking

Subagent telemetry now tracks when a subagent is 'vetoed' under a specific prompt

**Unclear.** What triggers a veto and how it affects a subagent's behavior isn't specified in the finding.

**What**

Claude Code's subagent tracking now includes a `recordVeto` method and an `isVetoedUnder` check, backed by a new map that records whether a given subagent was vetoed under a particular prompt. This data is cleared along with the rest of a subagent's telemetry when it's cleaned up.

**Why**

This lets Claude Code keep track of veto decisions tied to specific prompts for subagents, though the finding doesn't specify what triggers a veto or how it affects subagent behavior.

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

### thinking_disabled_effort_cap follows the same gate-precedence rework

The thinking_disabled_effort_cap flag can now override the claude-opus-5 hardcoded default in either direction

**What**

A helper that decides whether an extra-high reasoning effort cap applies to a model previously required the `thinking_disabled_effort_cap` flag to be exactly true, or the model to literally be `claude-opus-5`. Now, any explicit value returned by the flag (true or false) is used first, and the `claude-opus-5` hardcoded default only applies when the flag has no value at all.

**Why**

This mirrors a similar change to another flag in this release, letting the server control this cap explicitly instead of it always being forced on for `claude-opus-5`.

- Area: Model Safety
- Tier: Under the hood
- Useful: 2/5
- Signal: 3/5

### TranscriptSegmenter native module wired in

A transcript-processing function now uses a dedicated TranscriptSegmenter component

**Unclear.** It's not clear what feature relies on the TranscriptSegmenter or what changes for the user as a result.

**What**

A function that previously built a generic placeholder object now creates an instance of a `TranscriptSegmenter` class instead, which appears to be a dedicated, bundled component for breaking up conversation transcripts.

**Why**

This is internal groundwork; it suggests transcript segmentation is being handled by dedicated logic rather than a generic stand-in, but the finding doesn't specify what user-facing behavior depends on it.

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

### Sub-agent auto-mode classification now skips or clears output based on a 'handback' outcome

Sub-agent output classification in auto mode now depends on a new handback outcome

**What**

When Claude Code decides whether a sub-agent's (a separate Claude instance handling a sub-task) final output needs auto-mode safety classification, the relevant function now takes a `handback` parameter. If handback is "send" or "flagged," classification is skipped entirely. If handback is "withheld," the sub-agent's final result text is discarded before any classification happens.

**Why**

This lets the handback outcome, meaning how a sub-agent's result is passed back, determine whether that result even needs to go through auto-mode safety classification, avoiding unnecessary classification work or exposure of withheld results.

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

### Artifact hot-update flag renamed / decoupled from artifact-types flag

Artifact hot-reload now has its own dedicated env var and gate, separate from the artifact-types feature

**What**

Artifact hot-update (live-reloading an artifact without a full refresh) previously shared its on/off control with the unrelated artifact-types feature, reusing the `CLAUDE_CODE_ARTIFACT_TYPES` environment variable and the `tengu_cobalt_plinth_larch` gate. It now has its own dedicated environment variable, `CLAUDE_CODE_ARTIFACT_HOT`, and its own gate, `tengu_copper_hinge_wren`. The old environment variable and gate remain in place for the artifact-types feature they were originally meant for.

**Why**

This separates two previously entangled controls, so enabling or disabling artifact hot-reload no longer accidentally affects the artifact-types feature, and vice versa.

- Flag `tengu_copper_hinge_wren`: Not enough to say (read for one account on one subscription tier against v2.1.267; this account: no value returned, anonymous baseline: no value returned, compiled default: on)
- Flag `tengu_cobalt_plinth_larch`: Off in both readings (read for one account on one subscription tier against v2.1.267; this account: off, anonymous baseline: off, compiled default: not a boolean we can read)
- Area: Artifacts
- Names: `CLAUDE_CODE_ARTIFACT_HOT`
- Tier: Under the hood
- Useful: 2/5
- Signal: 3/5

### Terminal renderer adds a pointer-capture model for mouse press/drag/release/hover

Claude Code's terminal display now tracks mouse pointer presses, drags, releases and hovers with a capture model

**What**

The engine that draws Claude Code's terminal interface now explicitly handles mouse pointer presses, drags, releases and hovering, and can "capture" the pointer to a specific on-screen element for the duration of a drag. While an element holds the pointer captured, mouse wheel scrolling is suppressed.

**Why**

This is groundwork for more precise mouse interaction in the terminal UI, such as dragging something without the screen also scrolling underneath it at the same time.

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

### Per-model capability gate can now explicitly disable a feature, not just fail to confirm it

A per-model capability check can now explicitly turn a feature off, not just fail to confirm it's supported

**What**

Claude Code's per-model capability check, used for things like mid-conversation system prompts, adaptive thinking, rejecting disabled thinking, and context management, now treats an explicit "no" answer differently from no answer at all. Previously, both an explicit `false` and an unclear result fell through to the same fallback. Now, an explicit `false` immediately disables the feature for that model.

**Why**

This lets a model be marked as definitely not supporting a capability, rather than that capability defaulting to whatever happens when nothing is known about it, giving more precise control over what each model is allowed to do.

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

### Overage status now reports which quota window it applies to

Rate-limit overage status now specifies which quota window ("channel") it applies to

**What**

When Claude Code reports that you're over a usage quota, the status it tracks internally now includes an `overageScope` field set to `"channel"`, replacing a simple true/false overage flag that was based on a single response header. The new value is read from a different header check.

**Why**

This makes it possible to know which specific quota window an overage applies to, rather than just that some overage exists, which is a building block for more precise rate-limit reporting.

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

### Precomputed compaction gains a veto mechanism to avoid repeat attempts

Precomputed compaction now remembers when a plugin hook rejected it, to avoid retrying the same attempt

**What**

When Claude Code tries to arm a precomputed (background) compaction, it now checks whether that attempt has already been vetoed. If a `session.compact` plugin hook previously rejected the compaction, the attempt is skipped, and a veto is recorded whenever a hook-driven compact is skipped this way.

**Why**

This stops Claude Code from repeatedly trying to precompute the same compaction that a plugin hook keeps rejecting, avoiding wasted work.

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

### New startup step: 'artifact roster' cache is refreshed and awaited during CLI setup

Startup now refreshes an 'artifact roster' cache and can wait for it before continuing

**What**

Claude Code's startup sequence now conditionally kicks off a refresh of an 'artifact roster' cache early on, based on checks of whether it's needed and whether identity is already known. If that refresh was started, startup later waits for it to finish, up to a timeout, before continuing — the same pattern already used for refreshing policy limits at startup.

**Why**

This keeps the artifact roster (Claude Code's record of available artifacts) up to date at the start of a session without indefinitely blocking startup if the refresh is slow, since it only waits up to a capped timeout.

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

### MCP remote-tool registry now tracks passthrough tools and a generation counter

MCP remote-tool registry now tracks individual passthrough tools and a change counter

**What**

The internal registry that tracks tools announced by remote MCP (Model Context Protocol) servers now keeps its list of "passthrough" tools (tools forwarded through rather than wrapped) as a full map instead of just a count. It also now:

- reports `passthroughAdopted` in the results when tools are announced

- exposes a `passthroughTools` map of tool name to local name via `hostsForTable()`

- adds a `generation()` counter that increases every time something meaningful changes, such as a tool being accepted, cleared, or its status changing

**Why**

Tracking individual passthrough tools and a generation counter, rather than just a count, lets other parts of Claude Code detect exactly what changed and when, which matters for keeping remote tool state in sync.

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

### Forked-agent queries can now skip inline cache markers

Forked agent queries can now skip inline cache markers

**Unclear.** The finding does not say what situation calls for skipping cache markers specifically.

**What**

The internal mechanism used to run forked agent queries (a way of branching an agent's work) gained a new `skipMessageCacheMarkers` option, alongside the existing options to skip writing to the transcript or skip writing to the cache.

**Why**

This gives finer control over caching behavior for forked agent runs, letting a run avoid inserting cache markers into its messages when that isn't wanted.

- Area: Subagents
- Names: `skipMessageCacheMarkers`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### remote_tools_announce schema documents passthrough adoption fields

The remote_tools_announce acknowledgement schema now documents passthrough adoption fields for MCP tools

**What**

The schema for `remote_tools_announce` acknowledgements now formally includes `passthrough_adopted` (a count of MCP tools kept without going through the device bridge) and `passthrough_declined` (with a reason of policy, pending, or unavailable). The `ignored_tools` field also now documents more reasons a tool can be ignored, including tools beyond a cap that the worker itself decides to keep.

**Why**

Documenting these fields in the schema makes the passthrough-adoption behavior a supported, checkable part of the protocol for anyone building against it, rather than an internal implementation detail.

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

### TUI: new pointer-press subscription and frame pacing internals

Internal groundwork was added for mouse clicks and smoother frame timing in the terminal UI

**Unclear.** The finding shows only internal state and method names, not what user-facing behavior, if any, is wired up to them yet.

**What**

The terminal renderer (the part of Claude Code that draws its text-based interface) gained internal plumbing for two things: a way for parts of the interface to subscribe to pointer (mouse) press events, including a way to notify them when a press lands nowhere in particular, and new internal state for pacing how often frames are redrawn.

**Why**

This is internal scaffolding rather than a user-facing feature by itself. It lays groundwork that could support mouse-click interaction and smoother screen updates in the terminal interface.

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

### New cloud_credential_error category alongside wif_credential_error

A new cloud_credential_error category covers Google Cloud credential failures alongside AWS's wif_credential_error

**What**

Claude Code's error classification now has a distinct `cloud_credential_error` category for Google Cloud credential problems, alongside the existing `wif_credential_error` category for AWS. It's treated like other non-fatal error categories in places such as the error-type switch (which returns null for it) and API error logging. A related developer-facing description in the SDK-host code was widened from 'AWS credential-expiry error' to 'AWS / Google Cloud credential failure'.

**Why**

This lets Claude Code recognize and handle Google Cloud credential failures as a distinct, non-fatal case, separately from the AWS-specific credential error it already handled.

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

### New "recap fold" transcript message type

A new "recap fold" message type appears in transcripts, styled like other non-animated summary messages

**Unclear.** What content triggers a recap_fold message or what it displays isn't stated.

**What**

Claude Code's transcript renderer now supports a new message kind called "recap_fold", shown using a new `RecapFoldMessage` component. It's treated the same way as existing `speaker_label`/`work_segment` messages for metadata headers and animation: it never animates in and never appears as a top-level metadata message.

**Why**

This adds a new way for Claude Code to fold a recap or summary into the transcript display, presented consistently with similar existing message types.

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

### New telemetry fields for session-messaging pin resolution: restartedSincePin, identityContested

Cross-session messaging telemetry now records if the target session restarted or its identity was ambiguous

**What**

When Claude Code sends a message to another Claude Code session, its telemetry ('uds' event) now records two new true/false fields: `restartedSincePin`, whether the target session has restarted since it was pinned (selected as the target), and `identityContested`, whether the target's identity was ambiguous when resolving which session the pin pointed to. Related pin-resolution logic now also produces distinct follow-up message text for each case, and pin objects carry a `pinId` plus optional `claimedSessionIds` alongside the socket.

**Why**

This helps distinguish failed or confusing cross-session messages caused by a restarted target or an ambiguous match from other kinds of failures, and gives users clearer follow-up messages when either happens.

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

### New tool_schema_invalid error classification for 400s referencing tools.N.input_schema

API 400 errors about an invalid tool input schema now get their own error type instead of being generic

**What**

When Claude Code calls the API and gets back a 400 error whose message references `tools.*.input_schema` (or the custom-tool variant `tools.*.custom.input_schema`), it's now recognized and labeled as a `tool_schema_invalid` error, rather than being treated as a generic, unclassified 400 error.

**Why**

Giving this specific error its own classification makes it easier to identify that a tool's input schema is the actual problem, rather than having to dig through a generic error message to figure out what went wrong.

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

### Plugin UI press handling can be overridden per plugin/handle, plus a plugin 'tier' concept

Plugin button presses can now be intercepted by a runner override, and plugins gain a 'core' tier label

**Unclear.** What consumes the `tier` field or the runner override, and what other tier values exist besides 'core', is not stated.

**What**

When a plugin UI button or press is handled, Claude Code now first checks for a runner-level override before falling back to the plugin's own press handler. Separately, plugin descriptors and loaded module listings now carry a `tier` field, with 'core' as one observed value.

**Why**

The override mechanism suggests something outside a plugin's own code can now intervene in how its button presses are handled, and the new `tier` field suggests plugins are now categorized, for example distinguishing built-in 'core' plugins from others, though the finding doesn't say what uses this distinction.

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

### IDE MCP server identified via x-mcp-server-id header and fixed UUID

Claude Code now recognizes its own IDE MCP server via a header and fixed ID, driving tool auto-allow

**What**

Claude Code can now tell when an MCP (Model Context Protocol) server connection is actually its own IDE integration by reading an `x-mcp-server-id` header from the server's configuration and comparing it against a fixed, known value. This recognition feeds into decisions like automatically allowing the `mcp__ide__executeCode` tool and detecting servers that are set up dynamically.

**Why**

By positively identifying the IDE's own server instead of guessing, Claude Code can safely grant it default permissions (like running code) without prompting, while still treating unrecognized MCP servers cautiously.

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

### New account-blocking state: cloud_credential_error

Claude Code now shows a specific blocked state when cloud credentials are unavailable

**What**

A new account status, `cloud_credential_error`, now maps to a blocked state with the message "cloud credentials unavailable — check or refresh them".

**Why**

If your cloud credentials stop working, you now get a specific message telling you to check or refresh them, instead of a generic or unclear error.

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

### Org policy check gains a "latched" denial state

Organization policy checks now also block on a new "latched" denial state

**Unclear.** What specifically triggers the "latched" state, or how it differs in practice from "org_denied", is not explained.

**What**

The function that checks organization policy settings now treats a policy value of `latched` as a denial, in addition to the existing `org_denied` value.

**Why**

This adds a second way for an organization's policy to block an action, so administrators have another state to enforce restrictions with, and users may see actions blocked under this new condition.

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

### Memory conflict errors can now carry tombstone info

Memory conflict errors can now carry tombstone (deletion) information

**Unclear.** How this information is surfaced to the user, if at all, is not specified in the finding.

**What**

The error thrown when two edits to a memory file conflict now can carry information about a "tombstone" — a record that the memory was deleted — including a deletion timestamp (`deletedAtMs`). The underlying data format gained matching fields (`deleted_at`, `conflicting_memory_id`), and a new `tombstoneNoticedFor()` tracker was added alongside the existing `oversizeNoticedFor()` tracker.

**Why**

This lets Claude Code distinguish a conflict caused by a deleted memory from other kinds of conflicts, which likely improves how such conflicts are reported or handled.

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

### Plugin hooks now report a tier (core/prepend/user)

Plugin hooks now report a tier of core, prepend, or user

**What**

When Claude Code looks up plugin hooks (scripts that run automatically at certain points), the result now includes a `tier` field, computed as `"core"`, `"prepend"`, or otherwise `"user"`. Plugin hook metadata now carries `{plugin, tier, hook, generation}` instead of just `{plugin, hook, generation}`.

**Why**

This lets Claude Code distinguish hooks that are built-in ("core"), inserted ahead of others ("prepend"), or defined by the user, which likely matters for how hooks are ordered or prioritized when several apply.

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

### Terminal/desktop component allowlist tightened, "Client" component added

Terminal and desktop UI component allowlists drop raw HTML tags; terminal gains a "Client" component

**What**

The list of components allowed to render in the terminal interface no longer includes the raw HTML-like tags "div", "span", and "b"; the desktop list also drops these. The terminal list gains a new "Client" component.

**Why**

This tightens what can be rendered in these interfaces, likely closing off generic HTML-style tags in favor of a more controlled, named set of components such as the new "Client" one.

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

### Published artifacts/session-context can carry a deadline field

Artifacts and session-context data can now carry an optional deadline field

**Unclear.** It's unclear what feature or UI actually uses this deadline field once set.

**What**

The internal option builders for artifacts and session context (data Claude Code uses to track what's happening in a session) can now include a `deadline` field when one is set. The schema helper for session context was also updated to accept a `deadline` alongside the existing `label` field.

**Why**

This lays groundwork for artifacts or session context to carry timing information, though the finding does not say what feature consumes it yet.

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

### Attribution source can now be 'owner' in addition to typed/relay

Message attribution now recognizes 'owner' as a source, alongside typed and relay

**What**

The code that determines who or what sent a message previously recognized `typed` and `relay` as attribution sources, collapsing anything else to "unattributed." It now also recognizes an `owner` source value and passes it through instead of discarding it, with corresponding new cases added to related switch statements.

**Why**

Messages attributed to an owner are now tracked distinctly instead of being lumped in as unattributed, giving more accurate accounting of where a message came from.

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

### Deferred-tool 'kept' bookkeeping reworked around a unified strict/eager schema builder

Deferred MCP tool tracking was reworked around a unified schema-building helper

**What**

Claude Code keeps track of "deferred" tools from MCP servers, meaning tools that are temporarily set aside when a server disconnects and restored if it reconnects. The logic for rebuilding these tools' definitions was reworked to go through one consistent helper function everywhere, instead of each call site handling the `strict` and `eager_input_streaming` settings on its own. Whether a tool is treated as "eager" is now computed fresh each time rather than checked once against a static list.

**Why**

This is an internal consistency fix that should make deferred tool handling behave the same way everywhere it's used, reducing the chance of one call site treating a tool's schema differently from another.

- Flag `tengu_plucky_orchard`: Gate removed from the code (read for one account on one subscription tier against v2.1.267; this account: on, anonymous baseline: on, compiled default: not a boolean we can read)
- Area: MCP
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Auto-mode safety classifier now explicitly blocks when it's unavailable or the transcript is too long, but only for large output schemas

Auto mode now explicitly blocks large tool outputs when its safety classifier can't run

**What**

When Claude Code runs in auto mode (which can act on tool results without asking first), it uses a classifier to help decide whether output is safe to proceed with. That decision logic now has a new "blocked" outcome, separate from the existing "unavailable," "refused," and "allowed" outcomes. It triggers when the classifier is unavailable or the conversation transcript is too long to classify, but only when the tool's output schema is large. The reason given is either "classifier context exceeded; output schema too large to pass unreviewed" or "classifier unavailable; output schema too large to pass unreviewed," and the result now also includes an `unreviewed` true/false flag.

**Why**

This closes a gap where a large, unreviewable tool output could otherwise slip through auto mode simply because the safety classifier couldn't run; now it's explicitly blocked instead.

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

### New system-reminder template constant

A new reusable template for building system-reminder messages was added internally

**Unclear.** What specific content this template is used to prefix, or when it fires, is not stated.

**What**

A new internal template string was added that wraps content in a `<system-reminder>` tag. System reminders are short notes Claude Code injects into the conversation to give the model extra context it wouldn't otherwise have. This looks like a reusable building block for constructing one, rather than a new reminder itself.

**Why**

This is small internal refactoring-style plumbing; it doesn't change what reminders say, just how one gets assembled.

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

### Marketplace name now hashed/redacted in telemetry unless it is an official marketplace

Marketplace names sent in telemetry are now hidden as 'third-party' unless the marketplace is an official one

**What**

When a plugin marketplace is removed or updated, Claude Code sends usage telemetry events (`tengu_marketplace_removed` and `tengu_marketplace_updated`). These events now pass the marketplace's name through a check that only reveals the real name for marketplaces Claude Code recognizes as official; any other marketplace is reported simply as `'third-party'`. A new `is_official_marketplace` true/false field is also included, and the raw, unredacted name is still sent separately under a differently-named field.

**Why**

This limits how much identifying information about third-party plugin sources gets reported in telemetry, while still letting Anthropic distinguish official marketplaces from others.

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

### MCP remote tool dispatch reworked for session-sourced hosts and presentability

MCP tool call routing was reworked to better track per-session remote tool hosts and report a new 'not served' error

**Unclear.** The finding does not say what user-visible situations now trigger `not_served` versus the previous behavior.

**What**

The internal logic that decides whether a tool call runs locally or is sent to a remote MCP (external tool provider) host was substantially reworked. It now tracks which "machine" handles each tool individually, checks whether a host is presentable, and distinguishes hosts whose source is the current session from other kinds of hosts. In more cases than before, a call can now fail with a new `not_served` error, even when the remote-tools capability check itself doesn't fail.

**Why**

This changes how Claude Code routes tool calls to remote MCP hosts, particularly for session-based hosts, and gives clearer feedback (`not_served`) when a tool call can't be routed to any host, instead of failing for less specific reasons.

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

### Large expansion of protected/reserved paths under Claude's config directory

Claude Code's config directory reserves dozens more file and folder names as internal

**What**

Claude Code keeps a list of special file and folder names inside its own configuration directory (where it stores settings, sessions, logs and so on) that it treats differently from ordinary project files. That list has grown substantially, adding dozens of new reserved names covering things like usage data, caches, telemetry, task state, remote settings, and skill storage.

A related new function reads a per-skill claim file to determine skill ownership, capped at a size limit; if that file is too large, unreadable, or missing, it falls back to treating everything as claimed.

**Why**

Reserving these names prevents Claude Code's own internal bookkeeping files from colliding with anything a user or project might otherwise place in that directory, and supports newer features (like skills, daemons, and remote settings) that need their own protected storage.

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

### Transcript pass2 loader reworked around assistant/run-link tracking

Transcript replay's pass-2 loader rewritten to track messages by assistant/run-link ancestry

**Unclear.** The finding does not say what behavior difference, if any, this produces for a user.

**What**

The internal logic used when loading or replaying a saved conversation transcript (pass2) was substantially rewritten. It now decides whether to include each line of the transcript by tracing back to its nearest "assistant" message and tracking "runLink" entries through helper functions, rather than using a flat list of offsets as before.

**Why**

This is an internal rework of how transcripts are reconstructed; it changes how the loader determines what belongs together in a conversation, which affects the accuracy of transcript replay rather than anything directly visible in the UI.

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

### New 'owner timeline' relay for background/spawned agents, with a killswitch

Spawned background agents can now be given a relayed summary of the project owner's recent 'timeline' posts

**What**

New code assembles what the project owner recently wrote on "its timeline" and passes it into the context given to a spawned background agent when it starts, with a preface explaining that this is context only, not an instruction to follow. A killswitch can anonymize the attribution so it shows as "unattributed" instead of naming the owner.

**Why**

This gives background agents visibility into recent owner activity as background context, while the disclaimer guards against the agent mistaking that context for a command, and the killswitch offers a way to strip owner identity from it if needed.

- Flag `tengu_worker_owner_rows_killswitch`: Not enough to say (read for one account on one subscription tier against v2.1.267; this account: no value returned, anonymous baseline: no value returned, compiled default: on)
- Area: Cloud Agents
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### MCP tool schema normalization/validation consolidated into a single verdict function

MCP tool schema validation logic consolidated into one shared function with clearer reasons

**What**

The logic that normalizes an MCP (Model Context Protocol) tool's input schema and checks whether the Anthropic API will accept it — previously duplicated in two places — is now a single shared function. It returns a structured result of either `send` or `drop`, with a `cause` of `schema_unsupported`, `normalize_gated`, or `api_invalid` when dropping.

**Why**

This is an internal cleanup that removes duplicated logic and gives clearer, consistent reasons when a tool schema is rejected, without changing what gets accepted or dropped.

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

### Cloud credential errors now tagged and categorized separately

Cloud credential failures from AWS or Google Cloud are now identified and categorized separately

**What**

A new function inspects errors to detect whether a credential failure came specifically from AWS or Google Cloud. When this fires, API-error objects are tagged with an `isCloudCredentialError` flag, and a new classifier bucket, `cloud_credential_error`, separates these failures from generic authentication failures.

**Why**

This lets Claude Code distinguish cloud-provider credential problems (like an expired AWS or Google Cloud credential) from other kinds of auth failures, which should make error reporting and troubleshooting more precise for people using cloud-based credentials.

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

### Memory/artifact API surfaces tombstone-conflict and deletion-time details on write conflicts

Memory write-conflict errors now surface tombstone-conflict details and deletion time

**What**

The error thrown when a memory or artifact write conflicts with existing data now detects a `tombstone_conflict` reason (including a fallback check when the error message ends with "(tombstone_conflict)"), and parses a `deleted_at` timestamp into a millisecond value when the conflict is due to a tombstone (a marker left behind for deleted data).

**Why**

This gives more detail about why a memory write failed, specifically distinguishing conflicts caused by writing over recently-deleted data and when that deletion happened, which should make these conflicts easier to diagnose and handle.

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

### New 'result_from' content block type for tool results tied to host classifier context

Assistant transcripts can now include a result_from block linking a tool result to host classifier context

**Unclear.** What practical effect this has for users, or what a 'host' refers to here, is not stated.

**What**

When Claude Code reconstructs the assistant's transcript, it can now include a new kind of content block called `result_from`, alongside the existing `outcome` and `host_context` blocks. It is built from a new internal lookup of tool host result lines and associates a specific tool call with a `host`.

**Why**

This is an internal transcript-format addition, so it doesn't change what you see directly, but it lays groundwork for tracking which host produced a given tool result.

- Area: Transcript
- Names: `result_from`
- Tier: Under the hood
- Useful: 2/5
- Signal: 2/5

### Plugin hook system gains matcher/argument-shape validation and size-limited ui.message data

Plugin hooks now get validation errors for malformed matchers, disallowed edits, and oversized ui.message data

**What**

Plugins can register hooks (code that runs on specific events) and this release adds new validation for how those hooks are written and how they respond:

- a warning if a hook's `on('event')` matcher is written as a nested object but is being matched against a plain (primitive) value

- a rule that `next(e)` in `env.get`/`env.set` hooks can only change the value being read or written, not other fields

- a rule that `ui.message` calls can only change the `data` field, not `surface`, `component`, `requestId`, `element`, or `module`

- a size limit on `ui.message` calls: the serialized `data`/`props` must not exceed limits on nesting depth, number of values, or character length

**Why**

These checks catch plugin bugs early with clear error messages (like "nests deeper than" or "serializes to more than … characters") instead of letting malformed hook behavior fail silently or corrupt state elsewhere.

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

### Prompt-cache diagnostics gains fork-agent baseline tracking

Prompt-cache diagnostics now let a forked agent inherit its parent's cache baseline instead of starting cold

**What**

Claude Code tracks prompt-cache diagnostics per request to detect changes that would break the prompt cache (a mechanism that reuses previously processed prompt text to save time and cost) between calls. This tracker now accepts a `baselineAgentId`, and when an agent is a "fork" (a copy spawned from another agent) with no existing baseline of its own, it records `forkAgentId` and `parentKey` so it can seed its diagnostics from its parent's baseline. It also tracks a new `prefixBreakHash`, `hydratedHashRows`, and a `baselineHashSource` field showing whether the baseline came from memory, disk, or nowhere.

**Why**

This should make cache-busting detection more accurate for forked agents, since they no longer start with no baseline to compare against.

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

### Plugin/UI environment dispatch gains resolveTables for terminal/desktop surfaces

Plugin/desktop UI dispatcher gains a resolveTables method for resolving requests per surface

**Unclear.** What user-visible effect resolveTables and the new tier/nextTo/framing plumbing has, beyond the internal mechanism described.

**What**

The internal dispatcher that manages UI environments (such as terminal and desktop plugin surfaces) gained a new `resolveTables` method, which resolves a batch of requests against per-surface "core" contexts and passes the answers back through the environment's `storeResolved`. The `load()` step now also threads through a `tier` and a `nextTo` set for each environment, and the dispatch and `callInterface` logic gained additional "framing" and "leftOut"/"floors" plumbing.

**Why**

This is internal plumbing for how plugin UI surfaces resolve and route data; the finding doesn't specify what user-facing capability it enables.

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

### 'cloud_credential_error' added as a recognized abort/error reason

Claude Code can now recognize and report a 'cloud_credential_error' as a distinct failure reason

**Unclear.** The finding does not say which cloud provider or credential flow triggers this error.

**What**

A new error type called `cloud_credential_error` has been added to Claude Code's internal error handling. It is now fully recognized alongside the existing `wif_credential_error` type, with its own detection logic and error-code mapping.

**Why**

This lets Claude Code distinguish cloud credential problems from other kinds of failures, which should make error messages and diagnostics more accurate when something goes wrong with cloud authentication.

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

### Marketplace telemetry stops sending raw marketplace names by default

Marketplace add/remove telemetry now sends a redacted name instead of the raw marketplace name by default

**What**

When a plugin marketplace is removed or updated, the telemetry events `tengu_marketplace_removed` and `tengu_marketplace_updated` no longer send the raw marketplace name by default. Instead they send either a recognized name for official marketplaces or the literal value `third-party` for anything else. A new `is_official_marketplace` boolean is also included. The raw name is still captured, but now in a separate `_PROTO_marketplace_name` field.

**Why**

This reduces how much identifying information about third-party marketplaces is sent in standard telemetry, while still letting Claude Code distinguish official from third-party marketplaces in the data it collects.

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

### Effort computation now factors in turnEffort from permission layers

Claude Code's effort-level calculation now also factors in an extra turnEffort value derived from active permission layers

**Unclear.** What specifically about permission layers changes the resulting effort value isn't detailed in the evidence.

**What**

Several places that compute the effort level Claude Code actually uses, including conversation compaction, the `/effort` command's output, the `${CLAUDE_EFFORT}` prompt substitution, and agent session metadata, now pass in an additional `turnEffort` value calculated from the current permission layers, on top of the model's default effort and any explicit override you've set.

**Why**

This lets the permission layers active in a session influence the effort level used for a turn, not just the model's default or a manual override.

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

### Team/personal memory sync: org-memory connected mode gains an active picker mount check

Memory sync now also checks whether another process already owns the local memory endpoint before reporting the org-memory picker as ready

**What**

When `CLAUDE_MEMORY_STORES` isn't set, Claude Code's memory-store watcher now runs an extra check before firing the event that marks the org-memory picker as mounted, replacing a differently-named check it used before. Alongside store discovery, a new asynchronous check also runs to detect whether another process already owns the local memory endpoint, reported as `ownEndpointShadowed`.

**Why**

This helps Claude Code avoid telling the interface the org-memory picker is ready when it isn't, and lets it notice when a different process is already using the local memory endpoint it would otherwise rely on.

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

### Remote/headless transcripts now tag messages as 'remoteSourced' for artifact-state reconstruction

Remote and headless transcripts now tag messages so rebuilt artifact state can tell local from remote changes apart

**What**

Messages coming from a remote or headless session are now marked with a `remoteSourced` tag. The internal logic that reconstructs artifact state (the saved output of things like generated documents or code) from a transcript now uses this tag to track which tool calls originated remotely, and skips local-only reconciliation steps for those. A related check now only rebuilds artifact state from local history when it originates locally and is eligible to be used as a seed.

**Why**

This keeps artifact-state rebuilding from local session history separate from state that came in through a remote or headless session, avoiding incorrect merging between the two sources.

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

### ANTHROPIC_BETAS values now filtered through a new exclusion list before being applied

ANTHROPIC_BETAS entries are now filtered against a new exclusion list before being applied

**Unclear.** The finding doesn't say which beta names are on the new exclusion list or why they're excluded.

**What**

When Claude Code builds its list of beta headers from the `ANTHROPIC_BETAS` environment variable (used to opt into experimental Anthropic API features), each entry is now also checked against a new exclusion list. Entries that match are dropped, on top of the existing trimming of blank entries.

**Why**

Some beta names can now be blocked outright from being applied via `ANTHROPIC_BETAS`, regardless of what the user sets, beyond the earlier org-compliance-based blocking of the whole variable.

- Area: Elsewhere
- Names: `ANTHROPIC_BETAS`
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### Max-effort-level resolution now also considers a session/local override, not just the API-name-based table

The maximum allowed effort level now also considers a local session override, not just the model's fixed table

**What**

The logic that resolves the maximum effort level a turn can use now combines a locally-resolved value with the existing table lookup based on the model's API name, and uses whichever is lower. If the resolved value comes out to "max," it's now treated as no cap at all rather than as a specific ceiling.

**Why**

This lets a session or local setting further restrict the maximum effort level below what the model's built-in table would otherwise allow.

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

### Prompt-cache-break diagnostics reworked, with a new bypass path for one source

Internal prompt-cache-break diagnostics were restructured, with a new bypass for one message source and for disk-seeded cache state

**What**

Claude Code's internal logic for detecting "prompt cache breaks" (when a cached prompt prefix stops being reusable) was reorganized: the threshold logic for deciding when a break occurred now lives in a shared helper. A new branch handles the case where a specific message source reports no session state, logging a diagnostic event with request ID and cache token counts instead of just returning early. There's also a new early exit that skips break diagnosis entirely when the cache state was seeded from disk.

**Why**

This is internal diagnostic plumbing rather than a user-facing feature; it should make prompt-cache-break issues easier to trace by giving certain edge cases (missing session state, disk-seeded cache) their own explicit handling instead of falling through to generic logic.

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

### Auto-mode classifier now factors in owner-sourced permission rules

Auto model/effort selection now knows whether an active permission rule came from the account owner

**Unclear.** The finding doesn't say how the owner-source flag actually changes the classifier's model or effort decision.

**What**

The internal classifier that automatically decides which model and effort level to use for a message now also receives a flag indicating whether any of the currently active permission rules were set by an 'owner' source.

**Why**

This lets the automatic model/effort decision take account-owner-set permissions into consideration, though the finding doesn't say exactly how that factors into the choice.

- Area: Auto Mode
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### Transcript preview store now threads a transcriptV2 flag

Message list rendering now passes a new transcriptV2 flag into the transcript preview component

**Unclear.** It's unclear what behavior `transcriptV2` actually enables or changes for the reader.

**What**

The part of Claude Code that renders the message list now passes a new `transcriptV2` flag into the transcript preview component, alongside the existing `stream.previewStore` setting.

**Why**

The finding doesn't say what this flag controls in practice; it appears to be plumbing for a transcript rendering path.

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

### Automode remote-tool classifier now special-cases passthrough tools

Permission classifier now short-circuits for passthrough remote tools

**What**

The internal classifier that decides whether a remote tool call needs a permission check now specifically detects passthrough tools (tools forwarded directly rather than wrapped). If a tool is flagged as a possible passthrough tool and its input already carries certain reserved keys, the classifier skips its normal logic and returns "no_verdict" immediately. It also tags the classifier's internal record of the call with a reason noting that the tool is a passthrough tool.

**Why**

This avoids running the full permission classifier on tool calls that are already known to be passthrough, keeping their handling separate and consistent with the rest of the passthrough tool system.

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

### Artifact input-schema log line gains an assets_source flag and drops an endpoints-specific killswitch check

Artifact schema debug log gains an assets_source flag; an endpoints killswitch check was removed

**Unclear.** The finding does not explain what the removed endpoints exclusion controlled in practice or what effect its removal has.

**What**

The debug log line generated when Claude Code builds the input schema for the Artifact tool now includes an `assets_source` value, and a `frozenHotUpdate` value is now also captured. Separately, the check for the "endpoints" capability flag no longer excludes the case where the `endpoints` feature flag is set; that exclusion clause was removed.

**Why**

The added logging gives more visibility into how the Artifact tool's schema is built, while removing the endpoints exclusion changes when the endpoints capability is considered active.

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

### Function-hooks loader adds a per-tier 'user tier held' gate

Plugin hooks loader can now hold an entire 'user tier' of hooks after a prior failure

**What**

The loader for plugin function-hooks (custom code plugins can run at certain points) now checks each module's `tier` field. If a previous failure has marked a tier as "held," any module still loading with a "user" tier is skipped entirely rather than going through the normal load process, and it is logged as "not loaded: the user tier is held."

**Why**

This stops an entire tier of user-level plugin hooks from continuing to load after something in that tier has already failed, rather than letting each module fail individually.

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

### Subagent tool calls now pass a 'turnEffort' value into permission-layer checks

Subagent tool calls now pass a turnEffort value into permission checks

**What**

When a subagent (a Task tool call that runs a sub-instance of Claude) is about to run a command, the permission-checking logic now includes a `turnEffort` value, computed from the current permission layers. The same value is also used when resolving which model the effort setting should apply to.

**Why**

This keeps permission decisions and effort-based model resolution aware of the actual effort level in play for a subagent's turn, rather than relying on a value that could be stale or missing, particularly relevant if the effort level was set to track the running model mid-turn.

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

### Turn-updates and sibling prompt-nudge flags consolidated behind a shared gate helper

Internal cleanup: turn-update prompt instructions now check their enablement through a shared helper alongside three related flags

**What**

The internal logic that decides whether Claude's system prompt includes instructions for progress updates during a turn (the "Communicating with the user" section) now shares a common check function with three related settings: `bash_output_audience_note`, `silent_turn_reminder`, and `thinking_display_updates`. The environment variable `CLAUDE_CODE_TURN_UPDATES` still overrides everything else when set; otherwise the check falls through to a remote configuration lookup and then a per-client capability setting.

**Why**

This is a behind-the-scenes consolidation of how several related prompt behaviors are turned on or off, making them consistent with each other rather than changing what turn updates look like for users.

- Area: Elsewhere
- Names: `CLAUDE_CODE_TURN_UPDATES`
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### Remote-tools announce flow now tracks passthrough adoption and 'announced' vs 'displaced' state

Remote-tools connection tracking now records passthrough adoption and distinguishes 'announced' from 'displaced' tool states

**What**

The internal system that manages tools shared over a remote connection now tracks a `passthrough_adopted` value as part of its telemetry when tools are announced, and formally distinguishes between a tool being newly 'announced' versus being 'displaced' (replaced by another). This replaces what was previously just a console log message about passthrough tool counts.

**Why**

This is internal bookkeeping that gives clearer, more structured visibility into how remote tools are being adopted and replaced, rather than changing what users see or can do.

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

### REPL main-thread cache snapshots can now hydrate prefix-break hash rows from disk

Restored REPL session cache can now rebuild hashed prefix-break rows from disk and resets pending call counters

**Unclear.** What user-visible effect this has, if any, isn't stated in the finding.

**What**

When Claude Code restores its cached session state from disk, cache entries can now rebuild a `hydratedHashRows` value from a stored `prefixBreakHash`, as long as its salt is recognized. Under a new condition, restoring from disk also resets the `callCount` and `cacheDeletionsPending` tracking fields.

**Why**

This is an internal caching detail that helps the session correctly rebuild its cache bookkeeping after being restored from disk, rather than starting with stale or inconsistent counters.

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

### New sets of tool names for detecting dynamic web-search-capable MCP config

New internal tool-name lists help detect web-search-capable dynamic MCP server configs

**Unclear.** The finding does not say what user-facing behavior uses these new tool-name lists and helper function.

**What**

Claude Code gained two new internal lists of tool names: one covering search and lookup tools like `image_search`, `web_search`, `web_search_fast`, `web_fetch`, and several display-card tools, and another covering tools like `image_annotation`, `generate_image`, `conversation_search`, and `recent_chats`. A new helper function checks whether any dynamically configured HTTP MCP (Model Context Protocol, a way of connecting external tool servers) server matches a given tool name and scope or type.

**Why**

This is internal infrastructure for recognizing when a dynamically configured MCP server provides web-search-like capabilities, though the finding doesn't say what feature consumes this detection.

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

### Builtin plugin registration now runs unconditionally, plus again for non-local-agent entrypoints

Built-in plugins now register unconditionally at startup, in addition to existing conditional registration

**Unclear.** What practical difference this makes for a user, beyond registration now happening unconditionally as well as conditionally, is not stated.

**What**

Claude Code's built-in plugins are now registered once unconditionally as part of its startup check, in addition to the existing registration that happens when `CLAUDE_CODE_ENTRYPOINT` is not set to `local-agent`.

**Why**

This is internal startup plumbing. The finding doesn't specify a user-visible effect, but it suggests built-in plugins are now registered more consistently regardless of entrypoint.

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

### Precomputed compaction results

Conversation compaction can now apply precomputed summaries, with a dedicated error if one fails to settle

**Unclear.** The finding doesn't explain what triggers precomputing a summary ahead of time or what a reader would notice differently during compaction.

**What**

When Claude Code compacts a conversation (compressing older history to save space), the result of applying a compaction swap now carries additional tracking data: a key, a flag indicating whether it was a replacement, and a `precomputedAtUuid` identifying when the summary was precomputed. There's also a new dedicated error type for when a precomputed summary fails to settle properly.

**Why**

This points to compaction summaries now being computed ahead of time in some cases rather than only on demand, with better error handling and traceability if a precomputed summary doesn't finish correctly.

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

### New override path for effort-level resolution (effort/max_effort/xhigh_effort)

Effort-level settings now check a new lookup before falling back to the old model-id list

**Unclear.** The finding doesn't say what feeds the new lookup or which models it currently covers.

**What**

When Claude Code decides whether an `effort`, `max_effort`, or `xhigh_effort` setting applies to the model you're using, it now first checks a new named lookup. Only if that lookup doesn't resolve does it fall back to the previous method, which checked a list derived from the model's ID.

**Why**

This adds a more direct way to control which models get which effort levels, rather than relying solely on matching pieces of the model's name.

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

### Conversation replace-all now marks session as remote-originated

Replacing all messages in a conversation now marks the session as remote-originated and transforms messages before storing them

**Unclear.** The finding doesn't say what the Coe() transform does to the messages, so its exact effect on stored data is unclear.

**What**

When Claude Code replaces the entire set of messages in a conversation, it now marks the conversation as remote-originated (via `markConversationRemote`) and runs the messages through an additional transform step before saving them, rather than storing the raw list as before.

**Why**

This helps Claude Code correctly track which conversations came from a remote source (such as a synced or delegated session), which matters for features that behave differently depending on where a conversation originated.

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

### New "unavailable" passthrough-declined reason

Session protocol adds a new "unavailable" reason for declined passthrough

**What**

The `passthrough_declined` value used in some worker/session protocol messages now supports a third reason, `unavailable`, alongside the existing `policy` and `pending` reasons.

**Why**

This lets Claude Code's internal messaging distinguish a passthrough request that's declined because the feature is unavailable from one declined by policy or one that's still pending.

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

### "snooze"-like entries (name/until) now scoped by sessionId

Snooze-style entries (name/until) can now be scoped to a specific session

**Unclear.** What feature actually creates or reads these session-scoped snooze entries is not stated.

**What**

Internal "snooze" entries, which pair a `name` with an `until` time, can now also carry an optional `sessionId`. Both the validator that checks these entries and the code that redacts them before logging now accept and pass through this field.

**Why**

Scoping these entries by session means the same name/until pattern can apply differently depending on which session it belongs to, rather than being treated as global.

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

### Artifacts subsystem: new mintsArtifactKeys() capability check

Artifacts logging now checks a new mintsArtifactKeys() capability first

**What**

Before logging or recording certain events related to Artifacts, Claude Code now checks a new capability called `mintsArtifactKeys()`. Where this was added, it always returns true, and its effect is to suppress that logging path for contexts that generate their own artifact keys.

**Why**

This avoids duplicate or unnecessary logging in situations where a context is already responsible for minting its own artifact keys.

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

### Numbered-list detector on the first message, no in-bundle caller found

A new check detects numbered lists at the start of a conversation, though nothing yet appears to call it

**Unclear.** No call site was found that actually invokes this numbered-list check, so it's unclear whether or how it currently affects behavior.

**What**

Claude Code now has a regular expression and function that check whether the very first message in a conversation starts a line with a numbered-list marker, like "1." or "1)". No place in the code that actually calls this specific check with a message list could be found; other similarly-named functions in the code take a different kind of argument (a callback) and are unrelated.

**Why**

This likely exists to decide whether to suppress a formatting nudge that normally discourages Claude from using numbered lists, based on whether the user's own first message already used one. Since no caller was found, it may not be active yet.

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

### Prompt-cache prefix-break hash tracking added for prefix-caching diagnostics

New internal tracking of prompt-cache prefix breaks for cache-hit diagnostics

**What**

The per-request cache-state updater now computes and stores a `prefixBreakHash`, in addition to its existing message-hash tracking. Related new logic tracks a `summaryForks` map recording parent/child cache state around session summarization and forking (capped at a fixed number of entries), and reports cache-break telemetry, including whether the cache broke and what kinds of changes caused it.

**Why**

This is diagnostic plumbing for understanding when and why Claude Code's prompt cache (which reuses previously-processed context to speed up and cheapen requests) stops hitting, particularly around session summarization. It doesn't change visible behavior directly but supports better diagnosis of cache-related slowdowns.

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

### Model catalog shadow-compare now cache-aware with bounded late-fetch wait

Background model-catalog comparison checks now use a local cache and no longer block if the network is slow

**Unclear.** The finding does not say what reading `tengu_model_catalog_compare` gets for this release, since nothing has been read about that gate yet.

**What**

Claude Code periodically runs a background 'shadow compare' check that fetches the current model catalog to compare it against what's built in. This check now first looks at a local cache before deciding whether to make a network request, and writes the result (success or failure) back to that cache afterward.

If the fetch doesn't finish within a fixed time budget, Claude Code no longer waits for it. Instead it lets the fetch keep running in the background and logs a new `model_catalog_late_fetch` event once it eventually settles.

**Why**

This avoids the model-catalog comparison holding things up when the network is slow, while still recording the outcome for later use once the request finally completes.

- Area: Model Catalog
- Tier: Under the hood
- Useful: 1/5
- Signal: 2/5

### Workflow-tool ("ultracode") consent-prompt bypass now reads turn effort from the permission-layers stack

Workflow-tool consent prompt now reads effort level from the current permission layers stack

**What**

Claude Code can sometimes skip prompting you for consent before using the Workflow tool (also called "ultracode", which lets Claude orchestrate multiple subagents). The check that decides whether to skip this prompt now determines the current turn's effort level through a dedicated accessor that reads it from the active permission layers, and passes it as its own explicit argument to the check for extra-high ('xhigh') effort, rather than folding it into one combined true/false value.

**Why**

This is an internal refactor of how the consent-skip logic determines effort level; it keeps the same kind of decision but sources the effort information more directly from the permission stack.

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

### Remote settings eligibility now excludes hermetic remote sessions

Remote background-settings feature now treats hermetic remote sessions as ineligible

**What**

A feature that checks whether background/remote settings can be used now returns "not eligible" (with the reason `hermetic_remote_session`) when a session is running with both `CLAUDE_CODE_REMOTE` and `CLAUDE_CODE_REMOTE_HERMETIC_MODE` set. This check runs before the existing checks for gateway and first-party accounts.

**Why**

Hermetic remote sessions are isolated remote runs that don't carry the usual environment through. Excluding them from this eligibility check means such sessions won't attempt to use a feature that assumes a normal remote setup.

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

### New helper `bce()` gates an unspecified capability on interactive, non-VSCode, non-childSession context

New internal helper combines interactive/non-child-session/non-VSCode checks into one condition

**Unclear.** It is not established which capability this new helper actually gates.

**What**

A new helper function combines three existing checks — whether the session is interactive, whether it is not a child session (and not itself a nested `claudecode` session), and whether it is not the VS Code extension — into a single true/false result.

**Why**

The finding does not say what feature this gate controls, only that it bundles the same conditions used by the nearby OAuth plugin-scope refresh change, so it likely governs a similar capability.

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

### Initial message hydration now carries an origin and seed-eligibility flag

Initial transcript loading now tracks where messages came from and whether they're eligible to seed the session

**Unclear.** The finding doesn't say what consumes `initialMessagesOrigin` or `seedEligible`, or what practical effect this has for a user.

**What**

The internal call that sets up or reconciles a session's initial transcript state was changed to pass along an origin for the messages and a flag marking them as eligible to seed the session, instead of just the messages and a conflict flag. A new `initialMessagesOrigin` property is threaded through from the session engine's setup, defaulting to `"local"` if not otherwise specified. A second place that builds an empty or default starting transcript now uses a dedicated function instead of a hardcoded object.

**Why**

This is internal restructuring of how a session's starting messages are loaded and reconciled; it allows Claude Code to distinguish where initial messages originated from and whether they should be used to seed a session.

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

### Remote-tools-announce worker now reports the dynamic bridge MCP server

Remote tools announcements now report the status of the dynamic bridge MCP server

**What**

The handler that responds to `remote_tools_announce` requests now includes a `bridgeServer` callback among its dependencies. This callback looks up the app's MCP client that has `scope === "dynamic"` and reports its name, configuration, and whether it's disabled.

**Why**

This lets the remote-tools-announce process include information about the dynamic bridge MCP server, giving a more complete picture of active MCP connections when tools are announced remotely.

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

### Artifact/file title-to-filename logic reworked to distinguish 'file' vs artifact kinds

Artifact filename and extension logic reworked to better distinguish plain files from other artifact kinds

**What**

Claude Code's logic for turning an artifact's title into a filename has been reworked with new helpers: one splits a filename into its stem and extension, one maps an artifact's content type and language to the right file extension (using an expanded language-to-extension map), and one derives a clean filename from an artifact's title. This replaces and extends the older extension-derivation code, and adds a set of extensions considered "plain."

**Why**

This should make filenames generated for artifacts (including plain files, distinct from other artifact kinds like diagrams) more accurate and consistent, particularly for content types and languages that weren't well handled before.

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

### Terminal renderer gets input-priority frame pacing

Claude Code's terminal display now redraws faster right after you type

**What**

Claude Code's terminal interface normally redraws itself on a steady timer (about every 16 milliseconds). Now, for a brief 50-millisecond window right after keyboard input arrives, it switches to a much faster redraw rate (about every 4 milliseconds).

**Why**

This makes typing feel snappier and more immediately responsive, since the display catches up to your keystrokes faster instead of waiting for the next regular redraw tick.

- Area: Terminal UI
- Tier: Under the hood
- Useful: 2/5
- Signal: 1/5

### New mouse/pointer-press subscription plumbed through the terminal UI context

The terminal UI gains a way to track mouse/pointer clicks so clicking elsewhere deselects things

**What**

Claude Code's terminal interface internals now support subscribing to pointer (mouse) press events, alongside the existing layout subscription. The renderer implements a real listener system, including a way to signal that a click landed somewhere with nothing registered, and this is already used to deselect the current focus when you click outside it.

**Why**

This is groundwork for more mouse-aware behavior in the terminal interface, and it already fixes the specific case of clicking away from a selected element clearing that selection.

- Area: Terminal UI
- Tier: Under the hood
- Useful: 2/5
- Signal: 1/5

### Async SessionStart hooks are now settled with a grace period before the run reports settled

Claude Code now waits, with a grace period, for pending SessionStart hooks to finish before continuing

**What**

When a session starts, Claude Code now gives any still-running asynchronous `SessionStart` hooks (handlers that fire when a session begins or resumes) extra time to finish before moving on, waiting up to a set grace period for each hook's command and output to complete, then reading its trailing JSON response and attaching it to the result. The wait is logged as `workflow_launch_hook_settle`, or `workflow_launch_hook_settle_failed` if it doesn't finish in time, together with how many hooks were pending and how many delivered a response.

**Why**

This avoids losing a `SessionStart` hook's response just because it hadn't finished by the time Claude Code was ready to continue, making session-start hooks more reliable.

- Area: Hooks
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Artifact publish-check crash tracking added (Bv/Hv wrapper)

Claude Code now records tool calls whose permission check crashed, before the error is thrown further up

**What**

A new small tracking module records the ID of any tool call whose permission check crashed with an unexpected error, rather than a normal halt, keeping a capped list of the most recent crashes and dropping the oldest once the limit is reached. The permission-check function is now wrapped so it records a crash before re-throwing the error.

**Why**

This gives Claude Code an internal record of tool calls that failed their permission check abnormally, which can help track down why a particular tool call didn't go through as expected.

- Area: Artifacts
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Compaction request now stamps usage onto turn.complete when available

The turn-complete event now includes a computed usage figure whenever one is available

**Unclear.** What consumes this usage field, and why it's only included conditionally, isn't shown in the evidence.

**What**

When a conversation turn finishes, the event Claude Code emits for it now includes a `usage` object, alongside the existing answer, duration, aborted state and turn ID, whenever a usage figure was actually computed for that turn.

**Why**

This makes usage information available right at the point a turn completes, which is useful for anything that needs to track how much a turn consumed.

- Area: Compaction
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Auto-mode safety classifier gets hard size/node budgets on output schemas

Auto mode's safety classifier now enforces separate hard limits on a tool schema's size and nesting depth

**What**

When Claude Code's auto mode decides whether a tool call needs your approval, it feeds the tool's output schema to a safety classifier. That schema is now checked against two separate hard limits, one on how many nodes it can expand into and one on its total byte size, each raising its own error when exceeded, instead of a single overall length check.

**Why**

This makes the safety classifier used in auto mode harder to overwhelm with an unusually large or deeply nested tool schema, since either limit alone can now stop an oversized schema before it reaches the classifier.

- Area: Auto Mode
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### tengu_feature_bad / tengu_feature_sad now sanitize the error_code field before sending

Feature-bad/feature-sad telemetry now sanitizes the error_code field before sending it

**What**

The internal telemetry events `tengu_feature_bad` and `tengu_feature_sad` now validate the `error_code` value they record. If the value doesn't match an expected pattern, it gets replaced with a placeholder value of `nonconforming` before being sent.

**Why**

This keeps malformed or unexpected error codes from being recorded verbatim in telemetry, making the data more consistent and predictable to analyze.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### tengu_input_prompt's effort_level now also factors in active permission layers

The effort_level recorded with tengu_input_prompt now also accounts for active permission layers

**What**

The `effort_level` value logged with the `tengu_input_prompt` telemetry event is now calculated using the session's active permission layers (the rules that govern what Claude Code is allowed to do), in addition to the model and input options it already considered.

**Why**

This makes the recorded effort level reflect permission context as well as model and input settings, giving a more complete picture in telemetry of how a given turn's effort was determined.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New upload-wire telemetry: byte-flush/response timing and socket reuse tracked per publish request

New internal telemetry tracks upload connection timing and socket reuse during artifact publishing

**What**

Claude Code now instruments its network layer to record detailed information about publish/deploy uploads: whether the network connection (socket) was reused from a previous request, how long it sat idle before reuse, whether a response started coming back, how many bytes actually made it onto the wire compared to the total body size, and which local IP address family was used.

**Why**

This data feeds the new retry-on-dropped-connection logic and related telemetry, giving better visibility into why an upload might have failed or been slow.

- Area: Artifacts
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Box `key` props are validated for uniqueness and stripped before final render

Terminal UI Box components now validate `key` props for uniqueness and strip them before rendering

**What**

In the terminal interface's internal layout system, `Box` elements can carry a `key` prop, similar to how React list items use keys. Claude Code now checks that each key is a short string (between 1 and a fixed maximum length) with no control characters, and warns if the same key is used twice under the same parent. If it is duplicated, only the first instance is treated as a valid hover target. After the key has been used to wire up hover behavior, it's now removed from the internal tree before final rendering.

**Why**

This is internal plumbing that guards against subtle rendering bugs from malformed or duplicate keys in the terminal UI, and keeps the `key` prop from leaking into what actually gets drawn on screen.

- Area: Plugin UI
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Session cache no longer read from disk for thin/adopted sessions

Session cache no longer reads from disk for thin or adopted sessions

**What**

When fetching cached session data or checking how old a cache file is, Claude Code now skips reading from disk entirely in cases where disk-based session adoption has been suppressed or an alternate session source is active instead.

**Why**

This avoids unnecessary or incorrect disk reads for session types, like thin clients or adopted sessions, that shouldn't be relying on the local disk cache in the first place.

- Area: Sessions
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin UI client rendering gets a bounded per-request row budget

Plugin UI rendering now enforces a cap on terminal rows used per request, with older requests evicted

**What**

Claude Code now tracks how many terminal rows each plugin's UI client contributes to a given render, keyed by the request, plugin, and client. There's a cap on the total rows allowed, and older tracked requests are evicted once that cap is reached.

**Why**

This keeps a single plugin's UI output from consuming an unbounded amount of terminal space, and the eviction keeps the tracking data itself from growing without limit.

- Area: Plugin UI
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Reactive compaction failures now report a structured error kind

Failed reactive compaction now reports a specific reason code, not just free text

**Unclear.** The `tengu_reactive_compact_failed` gate hasn't been read for this site's account, so nothing can be said about whether it's active here.

**What**

When Claude Code's reactive compaction (automatic conversation shrinking that happens in response to running low on space) fails, the result now includes a structured `errorKind` field, such as `thrown`, `no_assistant_message`, or `empty_summary`, or an error tag from the API itself, in addition to the existing free-text description. The related telemetry event also now logs whether the cache was cold (`cacheCold`) and a `status` field.

**Why**

This makes compaction failures easier to categorize and diagnose, rather than relying on parsing free-text error messages.

- Area: Compaction
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Remote-control client_initialize gains an extra internal callback

Remote Control's client-initialize handler now runs an extra internal callback

**Unclear.** The finding doesn't say what the new function (`Po()`) actually does when a Remote Control client initializes.

**What**

When a Remote Control client connects and sends `client_initialize`, Claude Code's handler now calls an additional internal function alongside the existing force-reinitialize step it already ran.

**Why**

The finding doesn't say what the new function does, so its practical effect on Remote Control connections isn't clear.

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

### UI element-tree validator (used to check what gets rendered around dialogs) gained hover-scope and Box-key checks

Internal UI validator adds hover and layout checks and clearer error messages for dialog rendering

**What**

Claude Code's internal check that validates what can be drawn on screen (used when rendering dialogs and overlays) now tracks additional context called 'hoverScope' and 'siblingBoxKeys', and rejects a `Box` component's `hover.display` setting when it's placed around a dialog. It also gives a clearer error message when a `Button`'s properties are misused, and a friendlier error for an unrecognized UI element that now lists the valid element names.

**Why**

These are internal correctness checks for how Claude Code's own interface is built, but the improved error messages mean any related bug shows up as a much more useful message rather than a cryptic one.

- Area: Plugin UI
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Reactive compaction telemetry now reports cache-cold state

Reactive compaction telemetry now records whether the cache was cold

**What**

When Claude Code automatically compacts (summarizes) a conversation to save space, the internal event that logs this, `tengu_reactive_compact_succeeded`, now also records a `cacheCold` value indicating whether the prompt cache was cold at the time.

**Why**

This gives more detail for diagnosing compaction behavior, specifically whether a cold cache played a role, building on earlier additions that already recorded the kind of split performed and whether the whole conversation was summarized.

- Area: Compaction
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Artifact write-through-store now excludes MCP-fronted types from the store-write path

Artifacts no longer route MCP-backed data types through the store's write-through path

**What**

Artifacts (documents Claude Code can create and update, like code files or data files) can be backed by different storage types. The logic that decides which types get written straight through to the data store previously included MCP-fronted (Model Context Protocol) types alongside plain "data" and "write_db" types. That MCP case has been removed, so only "data" and "write_db" types now use this write-through path.

**Why**

This narrows which artifact types are treated as directly writable to storage, likely because MCP-backed artifacts need different handling than locally stored ones.

- Area: Artifacts
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Artifact URL inputs are now classified for telemetry on write/publish errors

Malformed Artifact URLs passed to publish or link actions are now classified and reported in telemetry

**What**

When a publish or link action receives an artifact URL that's malformed or unexpected, a new classifier now categorizes what's wrong with it, using labels such as `chat_artifact_link`, `viewer_path_bad_id`, `bare_id`, `missing_scheme`, `loopback_host`, and `same_artifact`. This classification is sent via telemetry whenever a specific error code is hit.

**Why**

Categorizing the specific way a URL is malformed makes it easier to spot patterns in what's going wrong with artifact links, rather than lumping every bad-URL error together.

- Area: Artifacts
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Scheduled/cron worker now awaits policy-limits cold start before running

Scheduled cron tasks and claude mcp serve now wait for policy limits to finish loading before starting

**What**

The worker that runs scheduled (cron) tasks now waits for `awaitPolicyLimitsColdStart` to complete before it starts dispatching any scheduled tasks, and registers a `stopPolicyLimits` cleanup step if the operation is aborted partway through. The `claude mcp serve` command does the same: it now waits for policy limits to finish loading before running its usual setup, sandbox check, and server startup.

**Why**

Waiting for policy limits to be ready before running scheduled tasks or starting an MCP server should prevent those tasks from running briefly without the correct limits in place.

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

### Severity-threshold config no longer requires two feature checks to apply

Severity-threshold settings now read the site's configured severity directly instead of needing two feature checks first

**Unclear.** The finding does not say what user-visible effect, if any, this has since the explicit off case is still respected.

**What**

A function that determines severity thresholds for a given key used to require two internal feature checks to pass before it would even look at the site's severity configuration. That gate has been removed, so the site's severity settings (`severityBySite`) are consulted directly, though an explicit "off" value is still honored.

**Why**

This is an internal simplification to how severity thresholds get resolved; it removes a redundant condition rather than changing what values are ultimately used.

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

### Session-name telemetry now classifies theme into a fixed set, defaulting unknown themes to 'custom'

Startup telemetry now reports theme as one of a known set of names, labeling anything else 'custom'

**What**

When Claude Code sends startup telemetry, the `theme` field used to report whatever value was set for the theme, verbatim. It now checks that value against a fixed list of known theme names and sends `custom` instead if the configured theme isn't on that list.

**Why**

This keeps theme telemetry data consistent and easier to analyze, by grouping any non-standard or custom theme configurations under a single label rather than sending arbitrary values.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Policy-limits loader can now be kicked off lazily post-startup

Policy-limits configuration can now be loaded on demand after startup if it wasn't already loading

**What**

A new `ensureLoadRequested` method lets Claude Code kick off loading of the policy-limits configuration after startup, if that load wasn't already claimed during boot. It's guarded by a check for whether there's any reason to skip policy limits at all (for example, using the first-party provider without an `ANTHROPIC_UNIX_SOCKET` override), plus internal state tracking whether the load has already started or completed.

**Why**

This is internal plumbing that lets policy-limits data be fetched lazily when needed rather than only at startup, making the loading logic more flexible without changing what policy limits do.

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

### Recap component supports a trailing element

The recap UI row can now render an extra trailing element after its content

**Unclear.** The finding doesn't say what, if anything, currently makes use of the new trailer element.

**What**

The UI component used for "recap:" rows now accepts an optional `trailer` element, which is displayed after the recap's main content, alongside its existing content and margin options.

**Why**

This is a small building-block change that lets recap rows show additional trailing information, though the finding doesn't specify what content now uses it.

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

### Plugin marketplace UI validates every entry with a shared allowlist-sanitizing helper

Plugin marketplace settings now validate each allowlist entry and blank the list if every entry is bad

**What**

A new shared helper validates array-based settings such as plugin marketplace allowlists entry by entry. Any entry that fails validation gets reported individually rather than silently dropped. If every single entry turns out invalid, the whole list is forced to empty with a warning, instead of Claude Code quietly keeping a partially broken list around.

**Why**

This avoids a settings file ending up in a half-valid state that behaves unpredictably; if a list is completely broken, it's cleared with a clear warning instead of causing confusing partial behavior.

- Area: Plugins
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin/skill list degradation distinguishes missing-scope from not-entitled

Plugin and skill list failures now report whether it's a missing permission scope or no entitlement

**What**

When Claude Code fails to fetch the list of available plugins and falls back to showing an empty list, it now distinguishes between two causes: an HTTP 403 (access forbidden) combined with a new 'no_scope' condition versus other cases. Internally it reports one of two distinct reasons, `no_plugins_scope` or `not_entitled`, depending on which applies.

**Why**

This makes it possible to tell whether an empty plugin list is due to a missing permission scope versus a lack of entitlement, which should help diagnose why plugins aren't showing up.

- Area: Plugins
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Gateway skips retry-eligible-status marking for 429s tied to forwarded user identity

Gateway no longer treats per-user 429 rate limits as generic retryable errors when forwarding user identity

**What**

Claude Code's model gateway (the component that routes requests to an upstream AI provider) can be configured to forward a user's identity to the upstream. When a request made this way, using the 'raw' upstream kind with `forwardUserIdentity` and a resolvable user email, comes back with a 429 (rate limited) response, the gateway no longer marks it as a generic retryable error status.

**Why**

A 429 tied to a specific forwarded user's identity reflects that user's own rate limit rather than a generic gateway problem, so it no longer gets bucketed with other retryable gateway errors.

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

### New prependPlugins/appendPlugins managed-settings keys

prependPlugins and appendPlugins now fall back to an empty list on malformed values

**What**

The `prependPlugins` and `appendPlugins` managed-settings keys, which control plugin ordering, now handle malformed values by falling back to an empty list rather than failing in some other way, with the message 'Read as an empty list; the key stays the managed policy's.'

**Why**

This keeps a malformed `prependPlugins` or `appendPlugins` value from breaking plugin loading entirely, while making clear the setting still belongs to managed policy rather than being silently dropped.

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

### Nonblocking stdout install failures get richer, deduplicated telemetry

Failures installing the fast, non-blocking stdout writer now log more detail and report telemetry once per reason

**Unclear.** The finding does not say what effect, if any, this has on the reader beyond diagnostics; behavior when the fast path fails to install is otherwise unspecified.

**What**

Claude Code uses a fast, non-blocking way of writing to the terminal's standard output when possible. When that setup fails to install, the log message now includes the specific system error code (errno) instead of a generic message. A new 'skipped' telemetry event is also sent, but only once per distinct failure reason (duplicates are filtered out), alongside the existing 'installed' event that already reported successes.

**Why**

This makes it easier to diagnose why the faster output path isn't being used on a given system, without flooding telemetry with repeated identical failure reports.

- Area: Terminal UI
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### turn.step and turn.complete telemetry events now include usage data

Two internal telemetry events now include usage data like token counts when available

**What**

The internal telemetry events `turn.step` and `turn.complete` now include a `usage` field in their payload whenever the underlying event carries usage data.

**Why**

This is internal telemetry plumbing rather than something a reader interacts with directly. It means these two events now carry richer information, such as usage or token data, when it's available, alongside the turn-tracking data they already recorded.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### @mention rendering/redaction helper

A new helper renders @mention placeholders in text as @Claude, @you, or a truncated viewer name

**What**

A new internal function replaces `<mention:ID>` placeholders found in text with a readable form: '@Claude' for a mention of Claude, '@you' when the mention refers to the person viewing it, or a truncated '@viewer' name with an ID prefix for anyone else. Placeholders with IDs it doesn't recognize are left as-is.

**Why**

This lets text containing raw mention placeholders display as readable @-mentions instead of internal ID strings, similar to how @-mentions appear in chat apps.

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

### New telemetry recorded when remote tools are switched off

Turning off remote tools now logs a 'gate_off' telemetry event with the prior tool registry

**What**

When remote tools get switched off, whether because of a `channel_off` or `switch_off` condition, Claude Code now records a `gate_off` telemetry event that captures a snapshot of the tool registry as it existed right before clearing it.

**Why**

This gives better visibility into when and why remote tools got disabled, which can help diagnose unexpected loss of remote tool access.

- Area: Remote Tools
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### URL trust check simplified — 'reserved name' special case removed

URL trust checks simplified, dropping a separate 'reserved name' special case

**Unclear.** The finding doesn't say what the removed 'reserved name' case covered or whether its behavior is now fully absorbed by the remaining checks.

**What**

The internal check for whether a URL points to a trusted internal link is now a single combined check: it verifies the protocol is `https:`, runs a link-eligibility check, and confirms the path matches an allowed list of prefixes. A previous special case that separately handled certain 'reserved name' paths through its own dedicated function has been removed.

**Why**

This simplifies the trust logic for internal links into one consistent rule, removing a separate carve-out that existed before.

- Area: Permissions
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New "recap_fold" transcript segment type

Transcripts gain a new 'recap_fold' segment type, handled like speaker labels

**Unclear.** The finding doesn't say what a 'recap_fold' segment actually contains or when it gets created.

**What**

Claude Code's transcript display can now include a new kind of segment called `recap_fold`. It's handled the same way as the existing `speaker_label` segment type in several places that control whether a message is shown, whether it counts toward live status, and how messages get folded together in the view. Like system and attachment messages, `recap_fold` segments are skipped when counting messages, and like `speaker_label` segments, they never match when searching the transcript.

**Why**

This lets the transcript view represent a new kind of grouped or summarized content without breaking existing search, counting, or display logic.

- Area: Transcript
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Login telemetry adds via_unix_socket field

Login telemetry now records whether authentication happened over a unix socket

**What**

The base telemetry data sent with login events now includes a `via_unix_socket` field, recording whether the authentication request went over a unix socket (a local file-based connection method, as opposed to a network connection).

**Why**

This gives Anthropic more detail about how authentication is happening, which can help diagnose login issues tied to the connection method.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Rate-limit overage response can now be scoped to a channel

Rate-limit overage responses can now be marked as scoped to a channel

**Unclear.** What a "channel" scope means in practice, or where it's surfaced to the user, isn't stated in the finding.

**What**

When Claude Code parses rate-limit overage information from a response, it now checks a header, and if that header equals "channel", it sets `overageScope` to `"channel"`.

**Why**

This lets Claude Code distinguish overage limits that apply to a specific channel from other scopes, which affects how usage limits are tracked or displayed.

- Area: Rate Limits
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Redaction now scrubs req_ request IDs from logs

Log scrubbing now also masks req_ request IDs

**What**

Claude Code's log-redaction process, which already strips things like UUIDs, hex strings, base64 data, and IP addresses from logs, now also matches and replaces request IDs in the form `req_XXXXXXXXXXXX` with `<id>`.

**Why**

This keeps request identifiers out of stored or shared logs, reducing the amount of potentially sensitive or traceable data that gets logged.

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

### New error classification: cloud_credential_error

API errors now classify as "cloud_credential_error" as a distinct category

**What**

The general API error classifier now returns `cloud_credential_error` when an error is flagged with `isCloudCredentialError`, adding a new category alongside the existing rate limit, authentication failure, and server error buckets.

**Why**

This lets Claude Code respond to cloud-credential problems distinctly from other error types, which likely ties into the new blocked account state and message for unavailable cloud credentials.

- Area: Error Handling
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### 'server_unavailable_timeout' removed from timeout-suffix list

server_unavailable_timeout no longer gets a '(timed out)' suffix on its error message

**Unclear.** Why server_unavailable_timeout specifically was removed from the list is not stated.

**What**

A helper that appends " (timed out)" to certain error messages used to do so for `server_unavailable_timeout` along with `wall_clock_timeout`, `connection_timeout`, and `server_call_unavailable_timeout`. It no longer includes `server_unavailable_timeout` in that list; the other three still get the suffix.

**Why**

This changes the wording of error messages shown for that specific timeout case, though the finding does not say why it was singled out.

- Area: Error Handling
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### fs.readFile/fs.writeFile/fs.listDir renamed to fs.read/fs.write/fs.list; 'readFile' IPC event renamed to 'read'

File-system permission events renamed: fs.readFile/writeFile/listDir become fs.read/write/list

**What**

The internal permission and capability event names for file access were renamed from `fs.readFile`, `fs.writeFile`, and `fs.listDir` to `fs.read`, `fs.write`, and `fs.list`. A related internal event case was also renamed from `readFile` to `read`.

**Why**

This is an internal naming cleanup to the permission system; it does not change what file operations are permitted, only what the underlying event names are called.

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

### Version-string classifier regex extended with more distribution-channel suffixes

Telemetry now recognizes engine, byoc, gateway, and ccs as version-string distribution tags

**What**

The pattern used to classify version strings for telemetry sanitization now recognizes four new pre-release or distribution-channel tags: `engine`, `byoc`, `gateway`, and `ccs`, in addition to the existing `dev`, `alpha`, `beta`, `rc`, `test`, and `nightly` tags.

**Why**

This lets telemetry correctly categorize version strings coming from these additional distribution channels instead of treating them as unrecognized.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Credential-storage backend telemetry now distinguishes fallback chains

Credential storage telemetry now reports which backend or fallback chain was actually used

**What**

Telemetry sent when OAuth login tokens are saved (or fail to save) now tags the storage backend more precisely. It recognizes `keychain`, `plaintext`, and `windows-credman`, as well as composite fallback chains like "`<x>-with-<y>-fallback`", and reports anything else as `other`.

**Why**

This gives more detail on which credential storage method was actually used, including cases where the system fell back from one backend to another, which helps diagnose storage issues across different platforms.

- Area: Credentials
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Policy-denied reason now also covers a 'latched' state

A new 'latched' registration failure reason now also maps to a policy-denied error

**What**

The code that maps registration failure reasons to policy error codes previously only mapped `org_denied` to `policy_denied`. It now also maps a new reason value, `latched`, to the same `policy_denied` code.

**Why**

This means a registration failure caused by a "latched" state is now reported to the user in the same way as an organization-level denial, rather than as some other error.

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

### Bash command classification set consolidated (search/read/list)

Bash command classification for search/read/list commands was consolidated into one combined set

**What**

Claude Code's logic for recognizing whether a bash command counts as a "search," "read," or "list" command (used for permission decisions) now draws from a single combined set built out of several smaller ones. One of those smaller sets specifically lists `ls`, `tree`, and `du` as list-type commands.

**Why**

Consolidating these lists makes the classification used for permission checks more consistent, since commands like `ls`, `tree`, and `du` are now explicitly grouped as list operations alongside the existing search and read categories.

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

### Handoff bookkeeping for artifact auto-reply now bounded and swept

Artifact auto-reply handoff tracking is now capped at 64 entries and cleaned up automatically

**What**

The internal tracking of pending "handoffs" (used for artifact auto-reply) is now a bounded map capped at 64 entries, evicting the oldest entry that isn't for a currently live session once it's full. New cleanup logic also declines stale handoffs with the reason `auto_reply_off` when auto-reply has been turned off, and drops handoffs for sessions that no longer exist.

**Why**

This prevents handoff bookkeeping from growing without bound and ensures stale or orphaned handoffs are cleared out instead of lingering, particularly when auto-reply is disabled or a session ends.

- Area: Artifacts
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New telemetry for CCR (remote worker) event-upload queue draining

New telemetry tracks how the remote-worker event upload queue drains

**What**

The upload queue used for sending events (part of the CCR remote worker system) now tracks per-lane counters such as number of posts, rows sent, largest single post, failed posts, and dropped rows. When a batch of queued events finishes draining, it now fires a `ccr_upload_drain` telemetry event recording the lane, what triggered the drain, how long events were held, post and row counts, failures, drops, and how long the drain took.

**Why**

This is internal telemetry for diagnosing how efficiently and reliably event data is uploaded in the background, useful for spotting stuck queues, dropped data, or slow drains.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Worker event uploads now carry hold/batch metadata (`upload_hold`)

Worker event uploads now include metadata about how long and why events were held before sending

**What**

When event data is uploaded to `/worker/events` or `/worker/internal-events`, the request body now includes an `upload_hold` object describing whether the batch was held before sending, why it was flushed, how many events were held, how long they were held, how many retries were in flight, what hold rule applied, and the post's position in sequence.

**Why**

This gives the backend more context about the timing and batching behavior of event uploads, which helps diagnose delayed or backlogged telemetry.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Render tree now handles a 'Client' component type

Plugin UI rendering adds support for a new 'Client' component type

**Unclear.** What a 'Client' component type represents or looks like in a plugin's UI is not stated.

**What**

The function that walks a plugin's UI render tree (used for both rendering and permission checks) now has a dedicated branch for a component of type `Client`, handling it before falling through to the generic children-recursion or the existing Button/Input/Select handling.

**Why**

This adds support for a new kind of UI component in plugin interfaces, though what a `Client` component represents or renders as isn't stated.

- Area: Plugin UI
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Plugin event-clause dispatch now excludes already-registered clauses

Plugin event dispatch can now skip clauses that have already been registered

**What**

The function that matches an incoming event against a plugin's declared clauses (conditions that trigger a plugin handler) and builds the resulting handlers now accepts a list of clause indexes to skip, and passes along a `registration` value to each per-clause handler. Clauses whose index is in the skip list are no longer matched again.

**Why**

This avoids re-registering or re-triggering a plugin clause that's already been registered, preventing duplicate handler invocations for the same event clause.

- Area: Plugins
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New consolidated 'plugins effectively enabled' check `svr`

A new internal check consolidates several conditions that decide whether plugins count as effectively enabled

**Unclear.** The finding does not say what `M7e()` checks or what visible effect the consolidation has for users.

**What**

Claude Code now uses a single combined check to decide whether plugins are effectively enabled, folding together several existing conditions: an internal capability check, whether everything is disabled, whether hooks (automated scripts that run on events) are disabled, and whether the setup is management-only. This feeds into the existing security-default calculation.

**Why**

This is an internal consolidation of logic that previously existed as separate checks. It should not change behavior on its own, but it centralizes how Claude Code decides when plugin-related security defaults apply.

- Area: Plugins
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New URL/endpoint redaction helpers for MCP server telemetry and logs

MCP server addresses are now redacted before being logged or sent in telemetry

**What**

Claude Code can connect to MCP servers (external tool providers) over various endpoints and commands. New internal helper functions now parse an MCP server's endpoint before it's reported in logs or telemetry, and redact anything sensitive: they mask template placeholders, strip credentials and file paths from URLs down to just the origin or host, and replace sensitive substrings with `x` characters or `${...}` placeholders.

**Why**

This prevents credentials, file paths, or other sensitive details embedded in an MCP server's connection string from leaking into logs or telemetry data.

- Area: MCP
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Self-hosted runner host-config snapshot now skips skills already synced from org, plus daemon/agent-memory dirs

Self-hosted runners now skip re-copying already-synced skills into session containers, and exclude daemon/agent-memory folders

**What**

When a self-hosted runner prepares a session container, it copies over a snapshot of the host's `~/.claude` configuration directory. That snapshot now leaves out dotfiles in general, plus any paths starting with `daemon` or `agent-memory`, and checks a new bookkeeping file to avoid re-copying skills that were already synced in from an organization.

If that bookkeeping file can't be read or is malformed, the runner seeds no skills into the session at all, and logs a warning telling the operator to delete the stale file.

**Why**

This avoids duplicating skills that are already managed centrally by an organization, and keeps daemon and memory state out of session snapshots where it doesn't belong. The warning matters because a corrupted bookkeeping file silently disables all skill seeding until it's cleaned up.

- Area: Self-Hosted Runner
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Pane component gains a 'suggestion' top-border highlight state

Panes in Claude Code's terminal UI can now be highlighted with a distinct 'suggestion' top border

**What**

The `Pane` component used to draw boxed sections in Claude Code's terminal interface now accepts new `lit` and `resize` properties. When `lit` is set, the pane's top border is drawn in a distinct highlighted color instead of the normal dim border.

**Why**

This gives Claude Code a visual way to call attention to a specific pane, such as one being suggested to the user, without changing the rest of its styling.

- Area: Terminal UI
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### MCP tool-listing pipeline refactored to a shared metadata object plus overrides

Internal rework of how Claude Code builds MCP tool listings, with no user-facing behavior change described

**What**

The internal code that builds the list of tools exposed by MCP (Model Context Protocol, a standard for connecting external tools to Claude) servers was restructured. Shared metadata for a server, such as its name, scope, prompt overrides, and telemetry info, is now built once per server, and each individual tool merges in its own overrides (such as Claude-in-Chrome or SDK server overrides) through a shared builder function, instead of each tool being assembled inline from scratch.

**Why**

This is a code organization change to how MCP tool metadata is assembled internally; it does not describe a change in what tools do or how they behave.

- Area: MCP
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Ambient-credential detection for MCP servers now operates on the URL rather than full config object

Claude Code's ambient-credential check for MCP servers now looks only at the server URL

**What**

Claude Code flags an HTTP or SSE-based MCP server as using an 'ambient credential' when it appears to pick up authentication automatically rather than through an explicit credential you provided. That check now looks only at the server's URL instead of the entire server configuration object, and a new helper combines it with checks for static auth headers and CLI-owned servers.

**Why**

Narrowing the check to just the URL makes the ambient-credential detection more targeted, reducing the chance that unrelated configuration fields affect whether a server gets flagged.

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

### Session query context now tracks whether a conversation originated remotely

Claude Code sessions now track internally whether a conversation started from a remote device

**Unclear.** The finding does not say what, besides this internal flag, changes as a result of a conversation being marked remote.

**What**

Claude Code's session context now includes a `markConversationRemote` function that records when a conversation originated remotely, setting the session's `conversationOrigin` to "remote". It's triggered by a stop-hook path (code that runs when a session or turn stops).

**Why**

Tracking whether a conversation began remotely lets Claude Code distinguish remote-originated sessions internally, which can support features or behavior that need to know a session's origin.

- Area: Sessions
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Bridge polling now distinguishes 401 vs 404 as re-registration triggers

Remote Control's bridge now distinguishes a 401 from a 404 when deciding to re-register

**Unclear.** Whether the `tengu_bridge_env_reregister` gate is active has not been read for this account.

**What**

When Claude Code's bridge (the connection used for remote and cloud sessions) polls the server and needs to re-register its environment, it now tracks which specific response triggered that: a 401 (unauthorized) or a 404 (not found). It logs the correct status code for whichever one occurred, and records which trigger caused it in telemetry.

**Why**

Distinguishing these two triggers gives clearer diagnostic information about why the bridge needed to re-register, rather than logging a generic re-registration event regardless of cause.

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

### Auth check shortcut for ANTHROPIC_UNIX_SOCKET sessions

Sessions using ANTHROPIC_UNIX_SOCKET now skip most auth checks and rely only on token/key presence

**What**

When `ANTHROPIC_UNIX_SOCKET` is set, the internal check for whether a session is authenticated now short-circuits: it considers the session authed simply if `CLAUDE_CODE_OAUTH_TOKEN` or `ANTHROPIC_API_KEY` is present, skipping the usual checks of the base URL, the API-key helper, and OAuth scopes.

**Why**

This simplifies authentication checking for sessions that connect over a Unix socket, a local inter-process connection method, avoiding checks that don't apply in that setup.

- Area: Auth
- Names: `ANTHROPIC_UNIX_SOCKET`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Compaction buffer builder similarly reworked for assistant/runLink lineage

Companion buffer-compaction routine also reworked to follow assistant/run-link message lineage

**Unclear.** The finding does not say what practical effect this has beyond matching the loader's new approach.

**What**

A related low-level routine that trims a transcript buffer down to the working set of messages was also rewritten, now walking assistant-message lineage through ancestor-following helper functions instead of a simpler linked-offset walk.

**Why**

This pairs with the transcript pass-2 loader rework, changing how Claude Code decides which parts of a long conversation to keep in the working buffer during compaction.

- Area: Compaction
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Unix-socket sessions determine auth type from OAuth token env var, skipping keychain lookup

Unix-socket sessions now report auth type from the OAuth token env var instead of checking the keychain

**What**

When `ANTHROPIC_UNIX_SOCKET` is set, the function that reports which kind of authentication is in use (for status displays and telemetry) now short-circuits: it reports `oauth` if `CLAUDE_CODE_OAUTH_TOKEN` is set, otherwise `api_key`, without probing the API-key helper, the system keychain, or workload-identity/OAuth state.

**Why**

This mirrors the related simplification of the authentication-availability check for Unix-socket sessions, making the reported auth type faster and simpler to determine in that setup, at the cost of the more thorough probing used elsewhere.

- Area: Auth
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Automatic OAuth plugin-scope expansion now skipped in non-interactive sessions

Automatic OAuth plugin-scope refresh no longer runs silently in non-interactive sessions

**What**

Claude Code has a background flow that silently requests an OAuth token refresh adding the `user:plugins` scope. That flow now stops early with the reason `non_interactive` when the session isn't interactive, unless it's running inside the VS Code extension.

**Why**

This prevents an automatic, silent authentication refresh from happening in non-interactive contexts (such as scripted or CI runs) where prompting or refreshing credentials unexpectedly could cause problems, while still allowing it in the VS Code extension.

- Area: Auth
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Comment-thread handoff responses now carry a `handOff` field through

Comment-thread handoff responses now pass through a `handOff` field

**What**

When Claude Code explains why it didn't automatically reply to or edit a comment thread (for example, because the artifact is generated from a source file), the response now includes a `handOff` field carried through from the input, in addition to the existing summary and detail text.

**Why**

This makes the handoff information available alongside the explanation, though the finding doesn't specify what consumes this added field.

- Area: Artifacts
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New daemon/background-launcher failure-reason categorizer

Claude Code now explains more clearly why a background process failed to start

**Unclear.** The finding does not say where this categorized reason is surfaced to the user, only that it is computed.

**What**

A new internal function reads the error text (stderr) produced when a background launcher or daemon process fails to start, and works out a reason for the failure: an exit code, a signal name, a generic launcher failure marked with a `<daemon-stderr>` tag, an error that mentions a file path, or a fallback 'other' reason when none of those match.

**Why**

This makes failures of background processes easier to diagnose, since the underlying error is categorized into a specific reason instead of being reported generically.

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

### System-attachment inclusion in context summary now capped by byte/size budget

Conversation summaries now cap system attachments by total size, not just by count

**What**

When Claude Code builds a shortened view of the conversation for internal use, it already limited how many system attachments (files or data folded into the conversation) it could include by count. It now also tracks a running total of their size in bytes and stops adding them once that budget is reached, in addition to the existing count limit. The underlying data is also now read through a function that can explicitly signal when there is no more data.

**Why**

This prevents a conversation summary from growing too large just because it contains many small system attachments that individually stay under the count limit, keeping the summarized context bounded by actual size.

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

### Hook-failure reporting split into separate log and emit steps

Hook-failure handling now logs and reports failures as two separate steps

**What**

When a hook (a user-configured script that runs at certain points in Claude Code) fails, the code that handles this now performs two separate steps built from a shared failure report, instead of one combined step. This applies consistently both when a hook fails during normal use and during the startup/bootstrap process.

**Why**

Splitting logging from reporting makes the failure-handling path clearer and more consistent between the two places it runs, though the finding does not indicate any visible change in behavior to the user.

- Area: Hooks
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Background-agent telemetry no longer includes agent template name

Background-agent telemetry no longer records which agent template was used

**What**

The `tengu_bg_agent_action` telemetry event, sent for "respawn" and "reply" actions on background agents, no longer includes the name of the agent template that was involved.

**Why**

This is an internal telemetry change; it does not affect what Claude Code does, only what gets recorded about background agent actions.

- Area: Telemetry
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Tool-call context now threads an agentId into the managed-pass invocation

Tool-call context now passes through the id of the agent that invoked it

**What

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

### Policy-limits disk cache skipped under ANTHROPIC_UNIX_SOCKET

Policy-limits caching to disk is now skipped entirely when ANTHROPIC_UNIX_SOCKET is set

**What**

A new helper checks the `ANTHROPIC_UNIX_SOCKET` environment variable. When it's set, Claude Code's policy-limits fetcher no longer writes its response to a disk cache, `saveCachedResponse` immediately returns `"skipped"`. Deleting the cache file is also skipped (`deleteCacheFile` returns false without touching anything). Additionally, the 'would fail closed' staleness check, which normally treats a cache older than 24 hours as invalid, no longer applies that 24-hour threshold in this mode.

**Why**

This avoids writing or relying on a disk-based cache when Claude Code is running in the `ANTHROPIC_UNIX_SOCKET` mode, which matters for environments where that mode implies different file-system or persistence assumptions than normal operation.

- Area: Policy Limits
- Names: `ANTHROPIC_UNIX_SOCKET`
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Policy-limits fetch now uses an AbortController and reports cycle_aborted

Policy-limits fetches can now be cleanly aborted, logged as 'cycle_aborted'

**What**

The component that fetches policy limits now uses an `AbortController` to cancel in-flight network requests. Its abort signal is passed into the fetch call and gets recreated whenever the fetcher is stopped. If a fetch is aborted, or if the session generation changes mid-flight, the outcome is now logged as `cycle_aborted`, and the `fetchAndLoad` function checks for this aborted state in addition to its previous check for a changed session generation.

**Why**

This makes policy-limits fetching more robust by properly canceling requests that are no longer needed and giving clearer diagnostic information when a fetch is interrupted, rather than letting stale or interrupted requests run to completion silently.

- Area: Policy Limits
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Diff panel read-deny check now considers two root candidates instead of one

The git diff panel now checks two possible root paths when deciding if a changed file is hidden from view

**What

- Area: Diff Viewer
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### New MIME type for structured artifact-publish refusal responses

Artifact requests now also accept a new 'frame-refusal' response format from the server

**What**

Requests related to publishing artifacts (generated files or documents Claude Code sends to a server) now include a new content type, `application/vnd.ant.frame-refusal+json`, in their Accept header alongside the existing `application/json`.

**Why**

This lets the server respond with a distinct, structured format specifically for refusals when it can't fulfill an artifact request, rather than only plain JSON.

- Area: Artifacts
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Stats view (ctrl+s copy) component — internal recompile, one call-site argument order looks changed

Internal rework of the stats screen's ctrl+s copy handler, possible but unconfirmed argument change

**Unclear.** Whether the changed argument reflects an actual behavior change to what ctrl+s copies, or is purely a side effect of renaming.

**What**

The part of the terminal interface that handles pressing ctrl+s to copy stats had its internal code reorganized, including renamed variables and functions. One of the arguments passed to the copy-to-clipboard helper differs from before, which might reflect an actual change in what gets copied, though this could not be confirmed against the underlying function.

**Why**

If this is just a rename, nothing changes for users of ctrl+s to copy stats; but it's called out in case the copied content behaves differently.

- Area: Terminal UI
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Feedback notice card now reports whether it is occupying screen space

Feedback notice card now tells the layout when it's taking up screen space

**What**

The small card that prompts you to send feedback (with its dismiss, send, and off options) now has a new `onHoldsBandChange` callback that fires whenever the card switches between being shown and being hidden.

**Why**

This lets the surrounding layout know when to reserve or free up screen space for the feedback card, rather than guessing or leaving a gap when it isn't showing.

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

### Tool-entry dedup logic loosened in schema-change tracking

Tool-entry dedup when tracking schema changes now only checks against already-kept entries, not a separate reference set

**Unclear.** What visible effect this has for users, since the finding only describes the internal dedup condition, not its downstream consequence.

**What**

In the internal logic that tracks which tool entries are kept, stripped, or removed when a tool's schema changes, an entry is no longer excluded from the "kept" list just because a tool of the same normalized name exists in a separate reference set. Now, an entry is only blocked from being added if it's already in the kept list itself.

**Why**

This loosens the deduplication rule, which likely means fewer tool entries get incorrectly dropped from the kept list during schema-change tracking, though the finding doesn't specify the exact downstream effect.

- Area: MCP
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Command-queue dispatch loop internals reworked (drainCommandQueue)

Internal rework of the command-queue dispatch loop, no new behavior found

**What**

The internal loop that dequeues and dispatches commands within a session was substantially restructured, with helper functions renamed and refactored. It still handles the same things as before: prioritizing orphaned permission requests, redelivering poll events on reconnect, and waiting on MCP (Model Context Protocol) connections before dispatching commands.

**Why**

This appears to be an internal refactor with no new externally visible behavior identified.

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

### Compaction path records whether it was 'replaced by hook' vs core-run

Compaction now records when a hook fully replaced Claude Code's own summarization logic

**What**

When Claude Code compacts a conversation (shrinking old messages into a summary to save space), it now builds a marker recording whether the built-in compaction process actually ran, or whether a `session.compact` hook replaced it entirely. This is reported along with token counts through a new telemetry event, `tengu_compact_replaced_by_hook`.

**Why**

This gives Claude Code (and whoever reviews this telemetry) visibility into whether a custom hook is taking over compaction instead of the default logic, which matters for diagnosing unexpected compaction behavior.

- Area: Compaction
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Per-site severity thresholds: two gate checks silently dropped

A site-specific severity setting now runs without two checks that used to gate it

**Unclear.** What the two removed conditions (`_1()` and `On()`) were meant to guard, and what practical difference this makes, isn't stated.

**What**

A function that determines severity thresholds (used to decide how serious something is flagged as) for a specific site used to only look up a site-specific value if two internal conditions were both true; otherwise it fell back to a default. That early check has been removed, so the site-specific lookup now always runs, regardless of those two conditions.

**Why**

The finding doesn't say what those two conditions guarded against, so it's unclear what circumstances now get the site-specific threshold that previously fell back to the default.

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

### Remote-tools 'announced' telemetry gains passthrough_adopted counter

Remote-tools telemetry adds a passthrough_adopted counter and drops an old console log

**What**

The telemetry Claude Code's remote-tools worker sends when announcing tool status now includes a new `passthrough_adopted` count, alongside the existing passthrough counters, plus a companion log entry for displaced/announced tools. A console log line that used to report the count of MCP tools not taken over has been removed.

**Why**

This is internal telemetry bookkeeping for how remote tool handoffs are tracked; it doesn't change what a user sees or does.

- Area: Remote Tools
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Artifact roster refresh added right after account login

Claude Code now refreshes its list of available artifact capabilities right after you log in

**Unclear.** The finding does not say what the new condition checks or what specifically counts as an 'artifact capability' in this roster.

**What**

After switching or logging into an account, Claude Code now automatically kicks off a refresh of its roster of artifact capabilities in the background, when a new condition is met.

**Why**

This should help ensure that the set of artifact-related features Claude Code thinks are available stays up to date as soon as you sign in, rather than only updating later.

- Area: Artifacts
- Tier: Under the hood
- Useful: 1/5
- Signal: 1/5

### Version bump and build metadata (housekeeping)

Routine version bump to 2.1.267 with no independent behavior changes

**What**

This release's build metadata, including the version string, build time, and git commit identifier, was updated to 2.1.267.

**Why**

This is routine housekeeping tied to the release process and doesn't reflect a behavior change on its own.

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

### Compliance-taint restriction check consolidated behind a helper, semantics likely unchanged

Compliance-taint restriction check refactored to use a shared helper function

**Unclear.** Whether the consolidation changes behavior in any edge case is not confirmed.

**What**

The check that determines whether a compliance taint denies a given restriction now calls a single shared helper function instead of iterating directly over an internal lookup map. The finding indicates this is a code cleanup rather than a behavior change.

**Why**

This is an internal restructuring that consolidates logic into one place; it is not expected to change what gets restricted or allowed.

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

### "HAS OAuth token save" failure warning text

The "Failed to save OAuth tokens" warning text was moved into a shared constant

**What**

The warning message "Failed to save OAuth tokens," shown when Claude Code can't save an OAuth authentication token, is now defined once as a shared constant instead of being written inline. It's still combined with the specific error detail when logged.

**Why**

This is a small internal cleanup with no change to what you see when a token save fails.

- Area: Credentials
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Large MCP/session control-handler hunks are pure symbol renames

Large-looking diffs in two control-handler code sections turn out to be pure variable renames

**What**

Two sizeable code sections, one handling MCP tool-call, toggle, and auth control requests, and another handling artifact verify, upload_asset, list_files, read_file, read, and delete actions, show large diffs, but on inspection every changed line is just a minifier renaming internal variables (for example `Cn` to `In`, `Ze` to `nt`). No logic was added, removed, or changed.

**Why**

This is a cosmetic change from the build process with no effect on behavior; it's noted here only to explain why these sections appear heavily modified.

- Area: MCP
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### SDK control-protocol handler (mcp_set_servers/reload_plugins/reload_skills/mcp_call etc.) — no discernible functional change

Internal cleanup of the SDK control-message handlers, no functional change found

**What**

The internal code handling SDK (software development kit) control messages, such as `mcp_set_servers`, `reload_plugins`, `reload_skills`, `reload_output_styles`, `mcp_reconnect`, and `mcp_call`, was reorganized with renamed internal variables. The same validation rules, including the check that `sdkMcpServers` and `webSearchIsolationExemptMcpServers` must be arrays of strings, and the same underlying settings appear unchanged.

**Why**

This looks like housekeeping rather than a behavior change; nothing here should affect how these commands work.

- Flag `tengu_ptc_enabled`: Not enough to say (read for one account on one subscription tier against v2.1.267; this account: no value returned, anonymous baseline: no value returned, compiled default: off)
- Area: SDK
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Artifact asset/db/page-data tool actions: no functional change identified

Internal rename-only cleanup of artifact asset, database, and page-data tool code, no functional change found

**What**

The code handling several artifact tool actions, listing, reading, and deleting assets, syncing and versioning, reading page data, and saving database reads to disk, was reorganized with renamed internal variables. The same underlying error conditions, such as `asset_bad_url`, `asset_target_changed`, and `read_page_data_schema_unavailable`, remain in place.

**Why**

This looks like internal housekeeping with no behavior change for users of artifact asset, database, or page-data actions.

- Area: Artifacts
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5

### Plugin MCP sync/install internals renamed, no behavior change found

Internal plugin sync and MCP relay functions were renamed with no behavior change

**What**

A handful of internal helper functions used when Claude Code syncs plugins and connects to MCP servers (a protocol that lets Claude Code talk to external tools) were renamed. The telemetry events tied to these functions, `tengu_plugins_sync_mcp_relay_wait`, `tengu_sync_plugin_install_timeout`, and `tengu_plugins_sync_wait_timeout`, are unchanged.

**Why**

This is an internal cleanup with no effect on behavior. Nothing changes for anyone using Claude Code.

- Area: Plugins
- Tier: Under the hood
- Useful: 1/5
- Signal: 0/5
