← All changelogs v2.1.213 claude · claude-sonnet-4-6
Claude Code · Source-level changelog

Version 2.1.213

This release introduces two major new capabilities: native support for Claude Platform on Google Cloud as a first-class provider, and a /import command that migrates configuration from OpenAI Codex and Google Gemini CLI into Claude Code. It also adds CLAUDE_CODE_NO_MODEL_FALLBACK to lock sessions to a specific model, improves SDK protocol with several new schema fields, and removes the morning brief feature.

Official notes not listed Package @anthropic-ai/claude-code Diff v2.1.212 → v2.1.213Provider claudeModel claude-sonnet-4-6
20
Features & Changes
5
Bug Fixes
1
In Development
0
Env Vars / Flags

Official Changelog

No official entry
Not individually listed upstream
v2.1.213 does not have its own entry in Anthropic’s official changelog — prerelease builds are often folded into a neighbouring release. Browse the full changelog for the closest official notes.
Official changelog ↗
Source-Level Analysis
Reverse-engineered from a diff of the bundled CLI — deeper, structured detail. Unofficial.

New Features

3 items

Claude Platform on Google Cloud #

New
What

Claude Code can now connect to Claude running on Google Cloud infrastructure via claude.googleapis.com, using Application Default Credentials or an explicit bearer token provider.

Usage
# Set your GCP project and let Claude Code discover the workspace
export ANTHROPIC_GOOGLE_CLOUD_PROJECT=my-gcp-project
export ANTHROPIC_GOOGLE_CLOUD_LOCATION=us-east5   # optional, defaults to global
export ANTHROPIC_GOOGLE_CLOUD_WORKSPACE_ID=my-workspace

# Or provide a full base URL directly
export ANTHROPIC_GOOGLE_CLOUD_BASE_URL=https://claude.googleapis.com/v1alpha/projects/...

# Enable the Google Cloud path
export CLAUDE_CODE_USE_ANTHROPIC_GOOGLE_CLOUD=true

# Skip auth entirely (if your infrastructure handles it externally)
export CLAUDE_CODE_SKIP_ANTHROPIC_GOOGLE_CLOUD_AUTH=true
Details
  • Routes to https://claude.googleapis.com/v1alpha/projects/{project}/locations/{location}/workspaces/{workspace}/invoke
  • Authenticates using Google Application Default Credentials (ADC) automatically when no other auth is provided — no API key required
  • Accepts an explicit bearerTokenProvider callback, a googleAuth object, or an authClient directly
  • The deprecated text Completions API is not available on this provider
  • GCP environment variable values for project, workspace, and location are validated to only contain letters, digits, hyphens, and underscores — URL metacharacters that could rewrite the request path are rejected with a clear error
  • The anthropicGoogleCloud provider is now recognized in the provider enum in SessionStart hooks and other SDK schema positions
Evidence

AnthropicGoogleCloud client implementation (search for "Claude Platform on Google Cloud", "https://claude.googleapis.com", ANTHROPIC_GOOGLE_CLOUD_PROJECT)

/import — Migrate Config from Other AI Coding Agents #

New
What

A new /import slash command (and claude import CLI subcommand) scans for OpenAI Codex and Google Gemini CLI configuration and imports it into Claude Code — MCP servers, slash commands, subagents, skills, and instructions.

Usage
# From the terminal (interactive picker)
claude import                 # auto-detect Codex or Gemini
claude import codex           # Codex only
claude import gemini          # Gemini only
claude import --dry-run       # preview without writing
claude import --yes           # apply all user-level items without prompting

# From inside a Claude Code session
/import                       # scan and list what's importable
/import --yes                 # apply everything without the picker
/import --dry-run             # show what would be imported
Details
  • Detects Codex config at ~/.codex/config.toml and .codex/ (project-level)
  • Detects Gemini config at ~/.gemini/settings.json and .gemini/ (project-level)
  • Imports MCP servers, slash commands (skills), subagents, and system instructions
  • Project-level config from .codex/ or .gemini/ directories is listed but NOT auto-imported — anyone with repo write access could author those, so they must be reviewed manually
  • Shell-exec markers (!{…} in Gemini, !cmd`` in Claude Code) are flagged and require manual porting
  • Items with no automatic mapping generate a helper skill at skills/import-to-claude-code/ for follow-up review
  • Gemini extensions, project-level settings, and subdirectory-organized commands are listed as needing manual review
  • The --yes flag on claude -p (headless/scripted) applies the same import that the interactive picker would; on plain claude -p sessions without a terminal, it instructs users to run claude import from an interactive terminal instead
  • Codex permission mode default maps to defaultMode: auto in Claude Code; tool restrictions differ and are dropped with a warning
Evidence

CLI entry point (search for "claude import [codex|gemini] [--dry-run] [--yes]"), Gemini config support (search for ".gemini/settings.json"), Codex support (search for ".codex/config.toml")

CLAUDE_CODE_NO_MODEL_FALLBACK — Prevent Model Substitution #

New
What

A new environment variable that locks Claude Code to exactly the configured model and disallows any automatic fallback to a different model — including during compaction.

Usage
export CLAUDE_CODE_NO_MODEL_FALLBACK=true
claude --model claude-opus-4-5 ...
Details
  • When set, the availability fallback chain collapses to [primary] only — no alternate models are tried
  • Compaction is disabled with the message "Compaction unavailable: CLAUDE_CODE_NO_MODEL_FALLBACK is set and model substitution is disabled · unset it to allow the swap"
  • If code attempts a model-fallback pivot while the flag is active, a tripwire throws an error identifying the call site (this is a developer safety net, not a normal user-visible error)
  • The flag is intended for environments where model consistency is a hard requirement (compliance, billing, reproducibility)
Evidence

Tripwire implementation (search for "CLAUDE_CODE_NO_MODEL_FALLBACK tripwire: a model-fallback pivot was attempted", "CLAUDE_CODE_NO_MODEL_FALLBACK")

Improvements

17 items

Background Sessions: Clearer "No Terminal" Error Messages #

New

Error messages that previously said "in a background session" now say "no terminal is attached to this background session" and include instructions on how to attach. Three affected messages:

  • MCP server authentication: "Can't authenticate MCP servers while no terminal is attached to this background session. Attach to it and try again."
  • /install-github-app: "Can't run /install-github-app while no terminal is attached to this background session. Attach to it and run the command again."
  • /mcp panel: "Can't open MCP settings while no terminal is attached to this background session. Attach to it and run /mcp again, or use \/mcp enable|disable|reconnect <server>\ to steer without the panel."
Evidence

Background session guards (search for "no terminal is attached to this background session")

SDK Protocol: aborted Field on Assistant Messages #

New
What

The SDK wire schema now includes an optional aborted: true field on assistant messages that were cut short by an interrupt or abort before the stream completed.

Details
  • Present when stop_reason was never received and content may end mid-word
  • Absent on normally completed messages
  • Allows SDK hosts to visually distinguish truncated responses from complete ones
Evidence

Schema addition (search for "True when this assistant message was truncated by an interrupt/abort")

SDK Protocol: task-notification subkind: "scheduled-trigger" #

New
What

The task-notification origin kind now carries an optional subkind field. When subkind is "scheduled-trigger", the turn is the automatic firing of a stored scheduled prompt.

Details
  • Lets SDK integrations distinguish scheduled task deliveries from other background notifications
  • The harness frames scheduled triggers using a [SCHEDULED TASK - AUTOMATED FIRING OF A CONFIGURED PROMPT] prefix instead of the generic background-notification frame
Evidence

Schema addition (search for "Present when the delivery is the fired stored prompt of a scheduled task/routine", "[SCHEDULED TASK - AUTOMATED FIRING OF A CONFIGURED PROMPT]")

SDK Protocol: Heartbeat and Subagent-Retry tool_progress Filtering #

New
What

The SDK message adapter now silently drops tool_progress frames that carry heartbeat or subagent-retry payloads instead of surfacing them as messages.

Details
  • tool_progress frames with heartbeat: true or a subagent_retry object are now filtered
  • These frames exist for session keepalive and retry signaling; passing them to SDK consumers as messages caused confusion
  • A debug log entry is written: [sdkMessageAdapter] Ignoring heartbeat/subagent-retry tool_progress frame
Evidence

Filter logic (search for "[sdkMessageAdapter] Ignoring heartbeat/subagent-retry tool_progress frame")

SDK Protocol: Plugin Version Field #

New
What

Plugins now expose their version as declared in plugin.json through the SDK wire format.

Details
  • The version string is emitted verbatim from the plugin manifest (plugin-author-controlled — validate before trusting)
  • Omitted when the manifest declares no version
  • The version field appears in the plugins array in two SDK message types: the system:init message (sent at session startup listing all loaded plugins) and the reload_plugins engine-control response (sent after a plugin reload)
  • In both locations the field is typed as S.string().optional(), so hosts must handle its absence for plugins that omit a version in their manifest
  • A separate plugin_version attribute is also recorded in telemetry events for marketplace-approved plugins when a skill command is invoked, enabling per-version usage metrics on the server side; third-party plugins emit "third-party" as the repository sentinel and no version is sent to telemetry
Evidence

Schema addition (search for "The plugin's version as declared in its plugin.json manifest, emitted verbatim"); wire positions (search for u7a used in system:init plugins array and reload_plugins response schema)

SDK Protocol: matched_ask_rule in Permission Requests #

New
What

When Claude Code escalates a tool call to the host for permission (auto-mode escalation), the permission request now includes a matchedAskRule object describing which rule triggered the ask.

Details
  • Fields: source, toolName, and optionally ruleContent
  • Lets SDK hosts make informed decisions about why a specific call was escalated rather than just seeing that it was
Evidence

Permission protocol addition (search for "matched_ask_rule" in SDK message schema)

Hook System: policySettings Source #

New
What

A new hook source type policySettings is recognized in the hook source registry. It joins userSettings, projectSettings, localSettings, pluginHook, sessionHook, and builtinHook.

Details
  • Represents enterprise managed settings delivered out-of-band by an administrator; displayed to users as "managed" (short), "Managed" (header), and "enterprise managed settings" (long form) in the settings/hooks UI
  • Unlike userSettings, projectSettings, and localSettings, policySettings is always included in the allowed sources list regardless of the --allow-setting-source CLI flag (it is force-added alongside flagSettings in the source filter)
  • policySettings.disableAllHooks = true disables all hooks entirely — even plugin hooks — across all sources
  • policySettings.allowManagedHooksOnly = true restricts hook execution to only policySettings.hooks; user, project, and local hooks are silently ignored for the session
  • If qi().disableAllHooks is true but policySettings.disableAllHooks is not true, hooks from managed settings still run (the setting overrides only non-managed hooks)
  • Hooks declared under policySettings.hooks are therefore the only hooks an administrator can guarantee will always run; user-side hooks can be suppressed without touching the user's own settings files
  • In hook priority sorting, hooks sourced from policySettings share bucket 999 with pluginHook and builtinHook, making them sort after user/project/local hooks in the display
Evidence

Hook source labels (search for "policySettings" in hook source map at new TJt variable); hook resolution logic (search for Lzi, iOe, QX, allowManagedHooksOnly, disableAllHooks)

SessionStart Hook: fork Source Value #

New
What

The source field on SessionStart hook events now accepts a new "fork" value, in addition to the existing "startup", "resume", "clear", and "compact".

Details
  • Fires when a session is loaded with forkSession: true — the code path activated when a skill carries context: "fork" or when the fork-subagent experiment (tengu_copper_fox / tengu_fork_subagent_enabled) spawns a subagent by resuming an existing conversation under a new session ID
  • The hook JSON payload is { hook_event_name: "SessionStart", source: "fork", agent_type: <string>, model: <string>, session_title: <string> } — same fields as "resume" events
  • Unlike "clear" and "compact", a "fork" event does propagate the session title returned by the hook (same behaviour as "startup" and "resume"): the title is stored so the forked session can be labelled distinctly
  • The new session ID passed in the hook is the forked child's fresh ID (not the parent's); the hook fires after the fork's conversation history is loaded but before the first turn runs
  • Skills with context: "fork" are excluded from being re-dispatched inside the fork they created, preventing recursive expansion
  • Hook output (additional context messages, reloadSkills, watchPaths) works identically to other SessionStart sources — hooks can inject context or block the fork by returning a blocking error
Evidence

Schema enum (search for "fork" in SessionStart hook schema alongside "startup", "resume", "clear", "compact"); fork dispatch (search for forkSession, x$e("fork", "fork" : "resume", aye = "fork", tengu_copper_fox)

Docker: Additional Global Flag Pass-Through #

New
What

Several additional Docker CLI global flags are now recognized and passed through in the Bash safety analysis, preventing them from being treated as suspicious when used before a subcommand.

New flags recognized: -r, --url, --connection, --identity, --remote, --module, --out

Evidence

Docker argument list (search for "--connection" in Docker flags array)

Shell Safety: Command Length Limit #

New
What

Very long Bash commands now bypass static analysis rather than attempting to parse them, avoiding edge cases where the parser could diverge from what the shell sees.

Details
  • Commands exceeding the length limit return { behavior: "passthrough", message: "Command too long for read-only analysis" }
  • The command is still executed; only the safety pre-flight parse is skipped
Evidence

Length check (search for "Command too long for read-only analysis")

Shell Safety: Improved Redirect Analysis #

New
What

The Bash parser now validates redirect nodes for additional dangerous patterns that could hide behavior from the safety classifier.

New cases detected:

  • fd-variable assignment — a redirect that uses a shell variable ({var}>) as the file descriptor; this modifies the variable as a side effect
  • close-fd redirect followed by a word>&- or <&- followed by text that bash would pass as a hidden argument to the command
  • redirect target starting with - after >& or <& — bash treats the dash as a close-fd operator and passes the remainder as an argument
Evidence

Redirect analysis (search for "Redirect uses", "fd-variable assignment", "Close-fd redirect is followed by a word")

Shell Safety: Test Command Gap Analysis #

New
What

The Bash safety parser now checks test commands ([[ ... ]]) for unparsed bytes between children or after the last child, which would indicate the parser missed content the shell will actually see.

Details
  • A new recursive function dnu() walks test_command AST nodes and their four nested compound-expression node types: unary_expression, binary_expression, negated_expression, and parenthesized_expression
  • For each node the function tracks a byte-position cursor from startIndex to endIndex and measures the gap before each child and after the last child; gaps that contain only whitespace (spaces, tabs), backslash-newline continuations, or (in bash mode) comment characters are allowed
  • Between-children gap: if the bytes between two adjacent parsed children are non-trivial, the function returns { kind: "too-complex", reason: "Test command has unparsed bytes between children — parser dropped content that shell will see" }
  • After-last-child gap: if bytes remain between the last child's endIndex and the node's own endIndex, the function returns { kind: "too-complex", reason: "Test command has unparsed bytes after its last child — parser dropped content that shell will see" }
  • Child out-of-bounds: if a child's span extends outside the parent's span, the function returns { kind: "too-complex", reason: "Test command child extends past the node span — gap byte accounting is untrustworthy" }
  • All three cases produce a "too-complex" result; the safety classifier treats "too-complex" as inability to determine read-only status, so the command is not automatically approved — the user sees the standard "approve this command?" prompt rather than a silent pass-through
  • This closes a semantic gap where a tree-sitter parse failure inside [[ ]] could have caused the classifier to analyse a truncated/simplified version of the condition and incorrectly allow a command that the shell would evaluate differently
Evidence

Test command validation (search for "Test command has unparsed bytes between children", "Test command has unparsed bytes after its last child"); gap-check implementation (search for dnu, Zru, unu)

OTEL: Configurable Content Truncation Limit #

New
What

The length at which telemetry content is truncated is now configurable via environment variables, and respects standard OpenTelemetry limit variables.

Usage
export CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH=8192   # Claude Code specific cap
# Or use standard OTel variables (Claude Code takes the minimum):
export OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT=4096
export OTEL_LOGRECORD_ATTRIBUTE_VALUE_LENGTH_LIMIT=4096
export OTEL_SPAN_ATTRIBUTE_VALUE_LENGTH_LIMIT=4096
Details
  • Previously the limit was hardcoded to 60 KB
  • The truncation message now includes the actual limit: [TRUNCATED - Content exceeds NKB limit]
Evidence

Configurable limit implementation (search for "CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH", "OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT")

Host OTLP Telemetry for SDK Integrations #

New
What

SDK host integrations can now emit custom telemetry events into Claude Code's OTLP pipeline using a host.* namespace. The system includes rate limiting and deduplication of error messages to avoid log spam.

Details
  • Events must follow the naming pattern host.<lowercase.dotted.name>
  • Attributes must use snake_case keys with string values
  • Payload is validated and rejected if it uses reserved namespaces (claude_code.*) or has invalid shapes
  • Rate cap: 240 tokens, refilling over time
  • Error categories: bad_envelope, bad_event_name, bad_attributes_shape, too_many_attributes, bad_attribute_key, bad_attribute_value, payload_too_large, emit_failed
Evidence

OTLP routing implementation (search for "host OTLP event dropped", "host OTLP event route error", "host OTLP event emit failed")

Org Memory: Silo and Grouping Selection [Gradual Rollout] #

New
What

The org memory system (controlled by tengu_haze_glass) now supports selecting specific memory silos or groupings within an organization, rather than mounting all granted stores.

Details
  • Controlled by the tengu_moth_lantern feature flag
  • Users can have a stored memory selection (persisted in settings as orgMemorySelection) that pins them to a specific silo
  • If the selected silo is no longer in the grant, the system degrades gracefully to the full grant
  • The orgMemorySelectionAccount field validates the selection belongs to the current account
Evidence

Silo selection logic (search for "silo_id", "grouping_id", "selection_degraded", "tengu_moth_lantern")

Usage URL Updated #

New
What

The URL shown when users reach their usage limit now includes a tracking parameter.

Old: claude.ai/settings/usage New: claude.ai/settings/usage?from=cc_cli_limit_message

This change is internal but users will see the updated URL in limit messages.

Evidence

URL constant (search for "claude.ai/settings/usage?from=cc_cli_limit_message")

Memory System: Multiple Team Mount Directories #

New
What

The memory system's prompt generation now supports multiple team memory directories with per-mount read/write modes, instead of a single team directory.

Details
  • The teamMounts parameter replaces teamDir in internal memory prompt construction
  • Each mount can be individually read-only or read-write
  • Prompt text accurately describes which directories are writable vs. read-only
Evidence

Memory prompt builder (search for "read-only — do not write there" in new memory prompt logic)

Bug Fixes

5 items
  • Shell redirect parser no longer misses content between children in test commands — the gap-byte accounting check is now applied to test_command nodes (search for "Test command comparison is missing its right-hand side")
  • The set_permission_mode engine control now validates the mode value and returns a descriptive error for unrecognized modes instead of silently failing (search for "[engine] set_permission_mode rejected — unrecognized mode", "Cannot set permission mode: must be one of")
  • GCP environment variable values containing URL metacharacters (:, /, \, ?, #, @, whitespace) now raise a clear error instead of silently corrupting the request path (search for "GCP path-segment env var failed the charset gate")
  • Error codes ENODEV, ENOMEM, EUNKNOWN, UNKNOWN, and Unknown system error * are now treated as retryable I/O errors (previously only EDEADLK, EINTR, ENXIO, ECANCELED, ENEEDAUTH, ESTALE were) (search for "ENODEV" in retryable error check)
  • Frontmatter parser now detects ambiguous --- closing delimiters (a value containing "---" could cause part of the block to be read as body) and reports a rewriteHazard warning instead of silently truncating (search for "the closing --- is ambiguous")

Removals

1 item

Morning Brief Feature Removed #

Dev

The morning brief feature (CLAUDE_CODE_ENABLE_MORNING_BRIEF, CLAUDE_CODE_MORNING_BRIEF_PROMPT) has been removed. The environment variables no longer have any effect. This was a limited-availability feature that has been deprecated.

Evidence

Removal of CLAUDE_CODE_ENABLE_MORNING_BRIEF and CLAUDE_CODE_MORNING_BRIEF_PROMPT from environment variable registry (confirmed absent in new version, confirmed present in old version via string diff).