# Claude Code v2.1.207

> Claude Code v2.1.207, released 10 Jul 2026 (2026-07-10). 24 entries read out of the shipped bundle. Unofficial, and not affiliated with Anthropic.

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

Version 2.1.207 upgrades the default model to Claude Opus 4.8 (`claude-opus-4-8`), introduces a Morning Brief skill for cowork sessions, and significantly hardens security around symlink traversal, autoMode settings source trust, and Remote Control unsigned-request handling. The `/auto-mode-setup` command gains smarter analysis of destructive and classifier-bypassing allow-rules, and the ScheduleWakeup tool now gives cache-TTL-aware delay guidance.

## New Features

### Morning Brief Skill (`/morning`)

**What**

A new `/morning` slash command that produces a styled HTML artifact daily brief, or sets up a recurring weekday scheduled task. Triggers on phrases like "morning brief", "daily brief", "what's my day look like".

**Details**

- Renders today's brief as a timed HTML artifact covering "Your day at a glance" and "Needs your attention" by default; a `Sections:` list overrides the table of contents.
- Accepts a setup request ("set up a recurring morning brief at 9 AM") — creates the scheduled task then renders today's brief as a preview.
- Custom prompt overridable via `CLAUDE_CODE_MORNING_BRIEF_PROMPT` env var.
- The flag `CLAUDE_CODE_ENABLE_MORNING_BRIEF` forces the skill on regardless of cowork entrypoint.

**Status**

Feature-flagged — controlled by `tengu_morning_brief_skill`. Currently only surfaces in cowork/remote-trigger entrypoints (`CLAUDE_CODE_IS_COWORK` or remote entrypoints) unless the env var override is set.

**Evidence**

Morning brief skill registration with description "Render the user's morning brief as a styled HTML artifact, or set it up as a recurring weekday task." (search for `"tengu_morning_brief_skill"`)

- Flag `tengu_morning_brief_skill`: Not enough to say (read for one account on one subscription tier against v2.1.207; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.

### /auto-mode-setup: Expanded Rule Audit

**What**

The `/auto-mode-setup` command now audits two additional categories of permission rules, replacing the old "over-broad interpreter-prefix" check with more targeted categories.

**Details**

- New section: **"Classifier-bypassing entries"** — rules that auto mode ignores at runtime even though they appear in `permissions.allow`. Lists them explicitly so users can review or remove them.
- New section: **"Destructive entries"** — allow-rules that auto-approve destructive operations without a prompt. Shown separately so users understand which rules carry higher risk.
- When `classifyAllShell` is active, a note warns that auto mode ignores all Bash/PowerShell allow rules (a superset of the flagged entries).
- If the list is capped at the display limit, a note instructs re-running `/auto-mode-setup` after cleanup to see the rest.
- Also now reads and reports `autoMode` keys from the project's `.claude/settings.local.json` with security checks (symlink gate, link-count-1 requirement, and git-tracking status).

**Evidence**

New audit output with headings "Classifier-bypassing entries" and "Destructive permissions.allow entries" (search for `"classifier-bypassing"` and `"Destructive permissions.allow entries"`)

### Sibling Org Repo Docs in Auto-Mode Setup

**What**

`/auto-mode-setup` now fetches CLAUDE.md and README.md from up to 3 sibling repositories in the same GitHub org via `gh`, providing Claude with additional context about your org's conventions.

**Details**

- Uses `gh repo list <org> --limit 5 --json name,pushedAt` sorted by most recently pushed, skipping the current repo.
- Fetches CLAUDE.md or README.md (first match) for each; README is truncated to first 40 lines.
- Content is marked with "unverified provenance" since it comes from sibling repos.
- Gracefully skipped when `gh` is unavailable, unauthenticated, or the origin is not github.com.

**Evidence**

Sibling repo docs fetcher (search for `"Sibling repo docs (via gh"` and `"name,pushedAt"`)

### Claude Design: Auto-Refresh on 401

**What**

When a Claude Design request returns HTTP 401, the client now automatically attempts a token refresh and retries once before surfacing an error.

**Details**

- If the access token has a refresh token available, a single retry with the refreshed credential is attempted.
- Specific error messages depending on credential type: remote CCR sessions, OAuth token env vars, and interactive sessions each get tailored guidance.
- The new `DesignAuth401Error` type carries a `wasRetried` flag to prevent retry loops.
- Token values are scrubbed from error messages and response data before surfacing to the user.

**Evidence**

Auto-refresh retry in Design client (search for `"Claude Design authentication failed (HTTP 401)"` and `"DesignAuth401Error"`)

### ScheduleWakeup: Cache-TTL-Aware Delay Guidance

**What**

The `ScheduleWakeup` tool's `## Picking delaySeconds` instructions are now context-aware, giving different guidance based on the session's prompt-cache TTL.

**Details**

- Sessions with a 1-hour TTL (Claude.ai subscriber sessions) receive guidance that ignores cache-window considerations — any delay in [60, 3600] is warm, so just pick based on what you're polling.
- Sessions with the default 5-minute TTL receive the classic "don't pick 300s" guidance.
- Sessions where the TTL is unknown receive a combined explanation covering both regimes.

**Evidence**

Context-aware delay guidance (search for `"1-hour Anthropic prompt-cache TTL"`)

## Improvements

### Default Model Upgraded to Claude Opus 4.8

The model constant has changed from `opus47` to `opus48` (`claude-opus-4-8`). This applies to the primary model slot across all providers.

Additionally, for Bedrock and Vertex sessions where only `ANTHROPIC_DEFAULT_SONNET_MODEL` has been customized (but not `ANTHROPIC_DEFAULT_OPUS_MODEL`), the system now intelligently falls back to Sonnet as the main model rather than forcing Opus — better matching admin intent when they configured only one model.

**Evidence**

Model constant `opus48` added (search for `"opus48"`) and provider-aware model selection (search for `"CLAUDE_CODE_3P_PROBE_WROTE_SONNET_DEFAULT"`)

### Auto Mode No Longer Requires Separate Interactive Disclaimer

The permission-mode downgrade message was changed from "bypass/auto requires accepting the disclaimer interactively first" to "bypass requires accepting the disclaimer interactively first". Auto mode's own opt-in dialog was also removed from the non-interactive code path, simplifying the startup flow.

**Evidence**

Updated disclaimer message (search for `"bypass requires accepting the disclaimer interactively first"`)

### Auto Mode Settings Locked to Trusted Sources

Auto mode rules (`autoMode.*`) from `projectSettings` and `localSettings` are now silently ignored with a warning, since those files are repo-controlled and could be authored by untrusted parties. Only `userSettings`, `flagSettings`, and `policySettings` may set auto mode classifier rules.

**Evidence**

Source-trust guard in autoMode config loader (search for `"only user/flag/managed settings may set classifier rules"`)

### Remote Control: Unsigned Request Rejection Feedback

When Remote Control receives a remote command or permission response without a valid device signature, it now:

- Logs the rejection to stderr with details including attestation status and actionable hints.
- Sends an explicit error `control_response` back to the sender, so the remote device knows the request was refused (previously the rejection was silent).
- Rate-limits burst warnings: after a threshold, further warnings for the same burst are suppressed with a note.
- Provides specific re-enrollment hints based on the attestation failure type (absent key, keyless device, etc.).

**Evidence**

Rejection notifier and response writer (search for `"Remote Control is rejecting a burst of unsigned remote activity"` and `"[remote-io] refusal write failed"`)

### TeammateMailbox: Invalid Entry Pruning and Detailed Logging

The teammate mailbox now actively prunes schema-invalid inbox entries when it reads the file, instead of silently dropping them only at read time. Detailed error logs are emitted per-entry with the field that failed validation, and a summary of pruned entries is logged.

**Evidence**

Mailbox pruning functions (search for `"[TeammateMailbox] pruned"` and `"TeammateMailbox: dropped inbox entry"`)

### extensions.worktreeConfig Automatically Restored After Last Worktree Removal

When the last linked worktree is removed (either via `/exit` from a worktree or when an agent worktree is cleaned up), Claude Code now checks whether `extensions.worktreeConfig` was enabled by Claude and restores the git config to its pre-worktree state automatically.

**Evidence**

Worktree config cleanup (search for `"Restored extensions.worktreeConfig in"` and `"enabledWorktreeConfigExtension"`)

### Symlink Path Safety Hardening

Path resolution across file tools and git pointer parsing now validates symlinks more carefully: network automount paths are flagged, cross-filesystem symlinks outside the project root are rejected, and git `.git` pointer files that are themselves symlinks or point outside the project are blocked.

**Evidence**

Symlink-aware path resolver (search for `"is a network automount path"` and `".git pointer file is a symlink"`)

### AWS Credential Validation in MCP Server Config

MCP server definitions using AWS auth now validate that:

- `aws_access_key_id` and `aws_secret_access_key` must be set together (not one without the other).
- `aws_session_token` requires `aws_access_key_id` and `aws_secret_access_key` to be present.

Empty-string values are also now rejected (fields require `min(1)` length). Clear error messages are surfaced on config parse.

**Evidence**

AWS credential pair refinements (search for `"aws_access_key_id and aws_secret_access_key must be set together"`)

### AWS Default-Chain Credential Resolve Timeout

Bedrock sessions now enforce a timeout on the AWS default credential provider chain resolution. The default is 60 seconds, configurable via `CLAUDE_CODE_AWS_CHAIN_RESOLVE_TIMEOUT_MS`.

**Evidence**

Credential chain timeout wrapper (search for `"AWS default-chain credential resolve timed out"` and `"CLAUDE_CODE_AWS_CHAIN_RESOLVE_TIMEOUT_MS"`)

### Native Launcher Auto-Update: Externally Managed Launchers Skipped

When running the native version cleanup after an update, Claude Code now checks whether the launcher at the executable path is a native-installer-managed symlink. If the launcher is externally managed (not a symlink into the `claude/versions/` directory and not an npm shim), version cleanup is skipped with a clear message rather than potentially interfering with the external manager.

**Evidence**

Launcher ownership check (search for `"Skipping native version cleanup: the launcher at"` and `"not created by the native installer"`)

### Streaming Markdown Renderer: Long-Output Chunking

The streaming markdown renderer (`StreamingMarkdown`) was rewritten to chunk large outputs into frozen segments rather than keeping everything in a single growing string. Open code fences are tracked across chunks so streaming inside a code block is handled correctly. This improves rendering performance and token-cache efficiency for very long streamed responses.

**Evidence**

Chunked streaming renderer (search for `"openFence"` and `"gapAfterChunks"` in the renderer)

### Payment Amount Input: Validated Text Field

The credit purchase amount input has been redesigned from a filtered numeric text field to a validated text field with inline error feedback. Amounts must be entered as `20` or `20.50`; a separate "Confirm amount" dialog now requires typing `yes` to confirm a billing action.

**Evidence**

Amount validator returning `"Enter an amount like 20 or 20.50"` (search for `"Enter an amount like 20 or 20.50"`) and new confirmation dialog (search for `"Confirm amount"`)

### DeferredToolPlaceholder: Keeps Deferred Tool Loading Active

A new placeholder tool named `DeferredToolPlaceholder` is registered with the description "Reserved placeholder that keeps deferred tool loading active; never call this tool." This internal mechanism ensures the deferred tool loading system remains armed across turn boundaries.

**Evidence**

Placeholder tool registration (search for `"DeferredToolPlaceholder"`)

### Cowritten Artifact HTML: Security Labeling

Artifacts that include content published by other co-writers are now tagged with `cowritten-artifact-html` and Claude is instructed to treat the tag's contents as untrusted data — not instructions. A co-writer cannot escalate permissions or modify settings through artifact content.

**Evidence**

Co-written artifact security annotation (search for `"cowritten-artifact-html"`)

### Model Env Var Whitespace Trimming

Values of `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_OPUS_MODEL`, and similar model env vars are now trimmed before use. This prevents subtle mismatches when env vars are set with trailing newlines or spaces (common when set via `export VAR=$(command)`).

**Evidence**

`.trim()` applied to model env var reads (search for `"ANTHROPIC_DEFAULT_SONNET_MODEL"` in context of `.trim()`)

### /auto-mode-setup: project settings.local.json Audit

The `/auto-mode-setup` recon now reads and reports `autoMode` keys from the project's `.claude/settings.local.json`, subject to strict security checks: the file must be a regular file (not a symlink) with link count 1 inside a real `.claude` directory. The output also notes whether the file is tracked in git (`yes — repo-authored` vs `no — but untracked does not prove user-authored`).

**Evidence**

Local settings autoMode reader (search for `"Project \`.claude/settings.local.json\` — autoMode keys"` and `"Tracked in git"`)

## Bug Fixes

- Fixed permission hook `canUseTool` callback: when it returns a schema-invalid result (ZodError), Claude now logs the validation error at the `error` level and surfaces a clear message ("The canUseTool callback returned an invalid permission result") rather than crashing or passing raw error text. (search for `"canUseTool returned a schema-invalid permission result"`)

- Fixed worktreeinclude gitignore patterns: patterns that fail to compile are now warned and filtered out rather than causing a crash, with a telemetry event recorded per invalid pattern. (search for `"gitignore-style pattern failed to compile"`)

- Fixed permission result handling when `updatedInput` is empty: the resolver now correctly checks `Object.keys(e.updatedInput).length > 0` only when `updatedInput` is defined, avoiding a crash on `undefined`. (search for `"updatedInput"` in permission result handling)

- Fixed Remote Control session reset on login: re-authenticating now clears `replBridgeSessionGroupingId` and `replBridgeInitialName` from app state, preventing stale session grouping data from persisting after sign-out. (search for `"replBridgeSessionGroupingId"`)

- Improved fs error categorization: additional POSIX error codes (`EDEADLK`, `EINTR`, `ENXIO`, `ECANCELED`, `ENEEDAUTH`, `ESTALE`) are now classified as retryable filesystem errors rather than hard failures. (search for `"EDEADLK"`)

## In Development

### Morning Brief for Non-Cowork Sessions [In Development]

**What**

The Morning Brief skill (`/morning`) exists in the codebase but is currently only enabled in cowork/remote-trigger entrypoints. Regular interactive sessions will see the skill once `tengu_morning_brief_skill` is enabled more broadly.

**Details**

- The `eSb()` enablement guard evaluates four conditions in sequence: (1) sessions that are neither `CLAUDE_CODE_IS_COWORK` nor a `remote_cowork`/`remote_trigger` `CLAUDE_CODE_ENTRYPOINT` are unconditionally disabled; (2) `CLAUDE_CODE_ENABLE_MORNING_BRIEF` (any truthy value) overrides all other conditions and forces the skill on; (3) remote-cowork and remote-trigger entrypoints return `false` unless the env-var override fires first — they do **not** consult the feature flag at all; (4) only non-remote cowork sessions (`CLAUDE_CODE_IS_COWORK=1` with a non-remote entrypoint) reach the `tengu_morning_brief_skill` flag check, which defaults to `false`.
- Custom skill prompt resolution follows its own three-step chain in `nSb()`: `CLAUDE_CODE_MORNING_BRIEF_PROMPT` env var is checked first (clamped to 500–50 000 characters); for non-remote sessions only, `tengu_morning_brief_config` feature flag (a JSON object with a `skillPrompt` string field) is checked second; the built-in prompt is the final fallback. Remote entrypoints always skip the feature-flag config and jump straight to the fallback.
- When not enabled, the `/morning` command is simply absent from the skill registry — no help text or invocation trigger is registered, so users see no trace of it.
- The skill's `menuDescription` is "Your morning brief — run it now, or set it up as a recurring weekday task", and its invocation trigger list includes "morning brief", "daily brief", "set up my morning brief", "what's my day look like", and "run my brief".

**Status**

Feature-flagged — `tengu_morning_brief_skill` defaults to `false`. Can be forced on with `CLAUDE_CODE_ENABLE_MORNING_BRIEF=1`.

**Evidence**

Enablement guard `eSb()` (lines 839865–839871) — four-path conditional ending with `Qe("tengu_morning_brief_skill", !1)`; prompt resolver `nSb()` (lines 839878–839887) reads `tengu_morning_brief_config.skillPrompt` only on non-remote sessions; prompt length bounds `tSb = 500` / `rSb = 50000` (lines 839971–839972) (search for `"tengu_morning_brief_skill"`)

- Flag `tengu_morning_brief_skill`: Not enough to say (read for one account on one subscription tier against v2.1.207; this account: no value returned, anonymous baseline: no value returned, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
- Flag `tengu_morning_brief_config`: Not enough to say (read for one account on one subscription tier against v2.1.207; this account: no value returned, anonymous baseline: no value returned, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.

### Walnut Spire (`plugin eval` General Availability) [In Development]

**What**

The `plugin eval` CLI subcommand (for evaluating plugins against test cases) was previously hard-gated behind `tengu_walnut_spire`. The gate is still present but is now also unlockable via the `CLAUDE_CODE_WALNUT_SPIRE` environment variable.

**Details**

- When `mvc()` returns `false` (both `tengu_walnut_spire` flag and `CLAUDE_CODE_WALNUT_SPIRE` env var absent), invoking `claude plugin eval` or `claude plugin eval init` immediately aborts with the message "`plugin eval` is currently in early access" — no command logic runs.
- `claude plugin eval [target]` discovers eval cases from `evals/**/case.yaml` or `evals/**/prompt.md` + `graders/*.md` under the target directory. The target may be a file-system path, an installed plugin name, or a `plugin@marketplace` id; skills-dir plugins also resolve and automatically add a no-plugin baseline arm for comparison.
- The command exposes a full suite of options: `--case <glob>` (filter cases by name), `--tag <tag...>` (filter by tag, repeatable), `--runs <n>` (default from `case.runs ?? 3`), `--model` (override model), `--judge-model` (LLM grader model, default Haiku), `--max-cost-usd` (hard budget ceiling — breaching it exits with code 2 and reports partial results; the overrunning agent skips paid graders but free graders still score), `--output-dir` (default `./evals/results/<timestamp>/`), `--json` (emit `aggregate-result.json` to stdout for CI), `--threshold <0..1>` (exit 1 if any case score falls below this value, default 1.0), `--allow-tools <tools...>` (operator grant for gated tools: `Bash`, `Write`, `Edit`, `WebFetch`, `mcp__*`; supports `Tool(pattern:*)` syntax), `--scaffold`/`--no-scaffold` (run `scaffold_script` from case files, off by default), `--ablation` (`none` | `with-without`, automatically `with-without` when targeting a plugin by name), `--keep-temp` (preserve scaffold dirs for debugging), `--verbose` (stream trace as it runs).
- `claude plugin eval init [name]` authors an eval suite under `evals/` via an interactive interview (`--interactive`/`--interview`) or writes a blank single-case template (`--bare`).
- Model-trigger evaluation (the "would the model route to this skill?" check) is still incomplete: when the model callback returns `null`, the case receives verdict `skipped` with reason "Model evaluation not yet wired up — tracks the plugin evaluation framework." All other eval machinery (grading, scoring, reporting) does execute.

**Status**

Feature-flagged via `tengu_walnut_spire`; also enabled by `CLAUDE_CODE_WALNUT_SPIRE` env var.

**Evidence**

Gate helper `mvc()` (line 184017) with check `if (!mvc()) ms(...)` at lines 780193–780194 (eval) and line 780275 (eval init); full command definition lines 780196–780284; partial-results `skipped` verdict at lines 672882–672889 (search for `"CLAUDE_CODE_WALNUT_SPIRE"` and `"Model evaluation not yet wired up"`)

- Flag `tengu_walnut_spire`: Off in both readings (read for one account on one subscription tier against v2.1.207; this account: off, anonymous baseline: off, compiled default: on) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.
