# Claude Code v2.1.203

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

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

This release tightens break reminder defaults to 30-minute intervals (down from 2 hours), improves proxy URL validation with actionable error messages, and adds detailed diagnostics for `E2BIG` spawn failures — especially when accumulated git worktrees grow the Bash sandbox deny list. The artifact tool gains first-session listing confirmation, smarter `url` parameter guidance, and shared-version warnings. EnterWorktree now resolves paths across repos nested in a multi-repo workspace.

## New Features

### ANTHROPIC_FOUNDRY_AUTH_TOKEN Environment Variable

Token-based authentication is now supported for Amazon Bedrock Foundry alongside the existing `ANTHROPIC_FOUNDRY_API_KEY`. When `ANTHROPIC_FOUNDRY_AUTH_TOKEN` is set, it is used directly as a bearer token instead of deriving credentials from the API key.

**Usage**

`export ANTHROPIC_FOUNDRY_AUTH_TOKEN="my-bearer-token" claude` **Details** - Token-based auth is checked first; API key auth is used as fallback - Useful when a bearer token is injected by infrastructure (e.g. IAM credential vending) - Both variables are now shown in `/doctor` **Evidence** Auth provider selection (search for `"ANTHROPIC_FOUNDRY_AUTH_TOKEN"`)

### CLAUDE_CODE_RELAUNCH_TERMINAL_SIZE Environment Variable

A new internal env var preserves terminal dimensions across session relaunches. When Claude Code spawns a replacement process (upgrade self-respawn, background detach), it captures the current terminal size as `COLUMNSxROWS` and passes it forward so the new process renders at the correct width and height even when the TTY reports wrong dimensions.

**Details**

- Set automatically by Claude Code before relaunching; not intended for manual use
- Applies terminal size from the env var only when stdout is a TTY and the OS hasn't already reported a real size
- The env var is deleted from the process environment after being consumed

**Evidence**

Terminal size preservation (search for `"CLAUDE_CODE_RELAUNCH_TERMINAL_SIZE"`)

### Fleet View Past Sessions [Gradual Rollout]

Past sessions from earlier work can now appear in the fleet/sessions view alongside active ones. When enabled, previously completed sessions are loaded from transcript history and interleaved with live sessions in modification-time order.

**Details**

- Controlled by feature flag `tengu_fleet_past_sessions` (GrowthBook) or `CLAUDE_CODE_FLEET_PAST_SESSIONS=true`; activates only on the local tab — suppressed on the remote tab and in single-session views
- Past sessions are loaded by scanning all local transcripts from the current transcript directory; sessions already present as live jobs are excluded by matching on `sessionId`
- Each past-session card shows: title (extracted from the transcript summary, falling back to the first 8 characters of the session ID), cwd (resolved as `relocatedCwd` → `projectPath` → launch directory), and last-modified time
- Cards appear as `earlier`-kind rows interleaved into the "done" group in strict modification-time order — a past session is inserted immediately above any active/done job whose terminal timestamp is older than the past session's `modified` value
- When any active filter is set (template, PR, URL, output, state, or text), past sessions are hidden entirely; the text-search (`/`) filter does propagate to past-session titles via `title.toLowerCase().includes(query)`
- Sessions whose `sessionId` is already tracked by a live job (including recently-kicked sessions held in a 30-second dedup window) are excluded from the past-sessions list
- If the result set exceeds the available vertical budget, entries beyond the computed `doneFoldAt` limit collapse into a `fold` row the user can expand; the overflow count is reported in `tengu_fleetview_fold_shown` telemetry
- Results are cached in a module-level variable (`icn`) across re-renders and reused on re-mount; the cache is invalidated only on a full module reset (e.g., `_resetRemountCachesForTesting`)
- On successful load, fires `tengu_fleetview_earlier_loaded` telemetry with the session count; expected (`oi`) errors are logged as `[fleetview] past-session enumeration failed: <reason>` and return `null`, which the fleet view handles gracefully without blocking; unexpected errors are re-thrown

**Evidence**

Past-session loader (search for `"tengu_fleet_past_sessions"` and `"fleet_view_earlier_load"`)

- Flag `tengu_fleet_past_sessions`: Off in both readings (read for one account on one subscription tier against v2.1.203; 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.

## Improvements

### Break Reminder Defaults Shortened

The break reminder interval defaults have been significantly reduced. The reminder now fires every 30 minutes of continuous use (down from 120 minutes), and 10 minutes of inactivity resets the timer (down from 15 minutes). New short intervals (5 min, 15 min) are available and the longer 2/3/4-hour options have been removed.

Before:

- Default interval: Every 2 hours; inactivity reset: 15 minutes
- Available: Off, 1h, 2h (default), 3h, 4h

After:

- Default interval: Every 30 minutes; inactivity reset: 10 minutes
- Available: Off, 5m, 15m, 30m (default), 1h

**Evidence**

Break reminder interval options (search for `"Every 30 minutes"` and `"Minutes of continuous use before the reminder fires (default 30)"`)

### Proxy URL Validation with Clear Error Messages

Invalid proxy env vars (`https_proxy`, `HTTPS_PROXY`, `http_proxy`, `HTTP_PROXY`) are now detected and reported clearly at startup and in `/doctor`.

- At startup: logs `Invalid proxy URL in https_proxy: "<value>" cannot be parsed as a URL. Proxy settings must be a complete URL including the scheme, e.g. "http://proxy.example.com:8080". Fix or unset https_proxy and restart Claude Code.`
- In `/doctor`'s connection section: shows `(invalid — ignored; fix or unset the proxy env var)` next to the bad value
- Previously, bare hostnames or partial URLs were passed directly to the HTTP client and could cause confusing failures

**Evidence**

Proxy URL validator (search for `"Proxy settings must be a complete URL including the scheme"`)

### E2BIG Spawn Failure Diagnostics

When Claude Code cannot start a command because the OS argument/environment limit is exceeded (`E2BIG`), it now surfaces a detailed diagnostic instead of a generic spawn error:

`Could not start bash: the command line plus environment exceed the OS exec argument limit (E2BIG). At spawn: command line 12.3 KB across 47 args (largest single arg 4.1 KB); environment 38.9 KB across 312 vars (largest: MY_VAR at 2.1 KB). The Bash sandbox profile adds 2847 filesystem deny paths to every command, 87 of them for registered git worktrees, which grow this list without bound. From another terminal, remove worktrees you no longer need (git worktree remove <path>; git worktree prune for already-deleted checkouts), then restart Claude Code so the profile is rebuilt without them — or relax the Bash sandbox for this session with /sandbox.` The message reports command-line size, arg count, largest arg, environment size, var count, and largest env var. If the Bash sandbox deny list is a factor, it identifies how many paths come from accumulated git worktrees and gives remediation steps.

**Evidence**

E2BIG diagnostic builder (search for `"the command line plus environment exceed the OS exec argument limit (E2BIG)"`)

### Cybersecurity Block Message Updated

When Claude is blocked on a cybersecurity topic, the message now links to the Cyber Verification Program help article and adds a feedback prompt:

Before: pointed to `https://claude.com/form/cyber-use-case`

After: "…has safety measures that flagged this message for a cybersecurity topic. To learn about the Cyber Verification Program and apply for access, visit our help center: https://support.claude.com/en/articles/14604842-real-time-cyber-safeguards-on-claude." If the user was not engaging in a cybersecurity topic, the message now adds: "If you were not engaging in a cybersecurity topic, please send feedback via /feedback."

**Evidence**

Cybersecurity block handler (search for `"real-time-cyber-safeguards-on-claude"`)

### Artifact Tool: Smarter url Parameter Guidance

The description for the `url` parameter in the Artifact tool has been rewritten to cover more update scenarios:

Before: "Pass when the user gives you a URL for an artifact not published in this session."

After: "Pass whenever the user wants to update an artifact this conversation did not publish — 'update my artifact', 'keep the same link', a pasted artifact URL — and find the URL with `action: 'list'` if you don't have it; without this, a conversation that didn't publish the artifact always mints a new URL."

This teaches Claude to proactively use `action: "list"` to locate the URL rather than waiting for the user to paste it.

**Evidence**

Artifact tool `url` param description (search for `"find it with \`action: \"list\"\` if you don't have it"`)

### Artifact Listing: First-Session Confirmation Required

The first `action: "list"` call within any session now always requires user confirmation, even if the user has previously allowed artifact listing. A permission prompt appears: "Claude wants to list your published artifacts (titles and links from your earlier sessions)."

**Details**

- `suppressAlwaysAllowRule` is set, so "always allow" rules do not bypass this first-listing ask
- Subsequent listings in the same session proceed without an additional prompt
- Results are now formatted as `"N published artifact(s) (most recent first):"` with title, URL, and last-updated date per entry
- A note is appended if the result set was truncated: "(More may exist — pass a higher `limit` (up to 50); artifacts not updated recently can be beyond the listing window.)"

**Evidence**

First-listing confirmation (search for `"First artifact listing this session requires confirmation"`)

### Artifact Listing: Strict Input Validation

`action: "list"` now enforces that no publish-related fields are present:

- If any field other than `action` or `limit` is set, the tool returns an error: `` action "list" takes only `limit` — remove <fields>. To publish or update an artifact, omit `action`. ``
- Passing `limit` with a publish action now returns an error: `` `limit` applies only to action "list" ``

**Evidence**

Artifact list validation (search for `'action "list" takes only \`limit\`'`)

### Artifact Publishing: Shared Version Warning

When updating an artifact that has been shared (via the claude.ai share menu) but the shared version is not the latest, Claude now surfaces a warning in the tool result:

"This artifact is shared, and viewers are pinned to an older version — they will not see this update until the user moves the shared version forward from the page's share menu."

**Evidence**

Shared artifact notice (search for `"viewers are pinned to an older version"`)

### Artifact Favicon Validation: Clearer Error Message

The favicon validation error message is now more specific:

Before: `"favicon must be one or two emoji — no markup"`

After: `"favicon must be the literal emoji character(s) — not an HTML entity, quoted string, or markup (send 📊, not '&#x1F4CA;' or '<svg/>')"`

**Evidence**

Favicon validator (search for `"favicon must be the literal emoji character(s)"`)

### EnterWorktree: Multi-Repo Workspace Support

The `path` parameter now resolves worktrees from repositories nested inside the launch directory, not just the exact current repo. This enables entering an existing worktree that belongs to a sub-repo in a multi-repo workspace.

**Details**

- On first entry from the launch directory, the target path is checked against both the current repo and any git repo nested inside it
- From within an already-entered worktree or from an agent with a pinned cwd, the target must still be under `.claude/worktrees/` of the same repository
- The parameter description now reads: "Path to an existing worktree to enter instead of creating one — of the current repository, or (on first entry from the launch directory) of a repository nested inside it."

**Evidence**

EnterWorktree multi-repo support (search for `"multi-repo workspace"`)

### Worktree: Improved Lock Safety and Error Reporting

Several worktree operations now handle lock-state edge cases more carefully:

- Stale-lock self-heal failures are now logged: `[worktree] skipped the stale-lock self-heal for <path>: <reason>`
- When the worktree registry is unreadable, operations log `[worktree] left the lock on <path> — cannot read the worktree registry to verify ownership`
- `cleanupWorktree` logs when it keeps a worktree because the registry is unreadable, instead of silently skipping cleanup
- `cleanupStaleAgentWorktrees` logs each kept worktree with the lock reason

**Evidence**

Worktree lock diagnostics (search for `"cannot read the worktree registry to verify lock ownership"`)

### Agent Isolation: Refuses to Run After Worktree Removed

When an isolated agent's worktree has been removed externally and the only fallback would be running in the parent session's shared checkout, the agent now refuses to run and reports the problem:

"This agent is isolated in the worktree `<path>`, but its working directory `<cwd>` no longer exists and the only recovery target is the parent session's shared checkout. Refusing to run there — the isolation worktree appears to have been removed. Report this instead of retrying."

Previously the agent might silently run commands in the parent directory.

**Evidence**

Isolation safety check (search for `"Refusing to run there — the isolation worktree appears to have been removed"`)

### IDE Bridge: File Upload Errors Now Surface to Claude

When a file attachment upload fails in the IDE bridge (VS Code / JetBrains), the failure is now returned as a structured error object to Claude rather than silently dropped. Claude can then inform the user of the specific failure reason:

- `"upload failed: no OAuth token available"`
- `"upload failed: could not read file (<reason>)"`
- `"upload failed: server returned <status>"`
- `"upload failed: unexpected server response"`
- `"upload failed: network error (<reason>)"`
- `"upload aborted"` (when the request was cancelled)

**Evidence**

Bridge upload error reporting (search for `"upload failed: no OAuth token available"`)

### Auto Mode Consent Asks: Improved Batching and Formatting Instructions

When auto mode blocks an action, Claude now receives clearer guidance on how to handle the situation:

- First try an alternative that no rule blocks (feature branch instead of default branch, synthetic data instead of real data, narrower scope).
- If a consent ask must be raised, hold it and batch it with other outstanding asks rather than ending the turn immediately.
- Format each consent item as a single concise sentence with the affected item in **bold**.
- If the block seems wrong, say so directly: "auto mode blocked X because Y — is that wrong?"

**Evidence**

Auto mode consent instructions (search for `"batch it with your other outstanding asks"`)

### /code-review Tip Description Updated

The tip that appears in Claude Code now accurately describes what `/code-review` does:

Before: "/code-review runs three review agents on your changes — reuse, quality, efficiency — and fixes what they find before you commit."

After: "/code-review checks your diff for correctness bugs and cleanup opportunities before you commit — add --fix to apply what it finds."

**Evidence**

Code-review tip text (search for `"/code-review checks your diff for correctness bugs"`)

### Sonnet Model Reference Updated to Sonnet 5

The advisory shown to Pro-plan users running Opus who have consumed more than half their weekly limit now refers to Sonnet 5:

Before: "Sonnet 4.6 handles most coding tasks and uses your weekly limit roughly half as fast as Opus."

After: "Sonnet 5 handles most coding tasks and uses your weekly limit much more slowly than Opus."

**Evidence**

Opus usage advisory (search for `"Sonnet 5 handles most coding tasks and uses your weekly limit much more slowly than Opus"`)

### claude.com/docs Added to WebFetch Pre-Approved Domains

The domain `claude.com/docs` is now in the set of pre-approved domains that can be fetched without a permission prompt. This includes Claude Tag pages and other documentation at the claude.com docs domain.

**Details**

- Previously only `platform.claude.com`, `code.claude.com`, `modelcontextprotocol.io`, `github.com/anthropics`, and `agentskills.io` were pre-approved
- Claude Tag pages at `https://claude.com/docs/claude-tag/overview.md` and similar paths are now reachable without extra approval

**Evidence**

WebFetch domain allowlist (search for `"claude.com/docs"`)

### Renderer Setting Confirmation Shows Renderer Name

When saving the TUI renderer setting, the confirmation message now includes the name of the renderer that was chosen:

Before: "Background sessions always use the fullscreen renderer so scrolling and mouse work when attached. The tui setting applies to sessions started directly with `claude`."

After: "Saved. Background sessions always use the fullscreen renderer while attached; the `<renderer>` renderer will apply to sessions started directly with `claude`."

**Evidence**

Renderer save confirmation (search for `"renderer will apply to sessions started directly with"`)

### Stdin Unreadable: Helpful Warning Instead of Silent Failure

When stdin is unreadable (e.g., the process was launched without a proper stdin pipe), Claude Code now emits a clear warning and continues rather than failing silently:

"Warning: stdin is unreadable (`<reason>`), proceeding without piped input. If you piped input, it was not received — pass it as a prompt argument, or check that the process launching Claude Code wires stdin to a pipe or /dev/null."

**Evidence**

Stdin error handler (search for `"pass it as a prompt argument, or check that the process launching Claude Code wires stdin to a pipe or /dev/null"`)

### Tmux Option Probes Now Cached

The tmux option queries (mouse mode and focus-events state) are now performed once and cached per session. Previously each check that needed the tmux mouse or focus-events status spawned a new `tmux show` subprocess. The cached results are shared across all callers within the session.

**Details**

- Two queries are cached: `tmux show -Av mouse` (detects mouse support) and `tmux show -gv focus-events` (detects focus-event state); each subprocess runs with a 2-second timeout
- Cache keys `tmuxMouseOptionProbe` and `tmuxFocusOptionProbe` live on the session-scoped probe-state object; each is initialized to `undefined` and populated lazily on first access via a stored Promise using `??=` assignment, so concurrent callers share the same in-flight subprocess
- Both probes are eagerly pre-warmed at startup via an early call when `$TMUX` is set and iTerm.app control-mode is not active, so the results are already resolved by the time hint-display checks run
- Mouse hint fires when the probe returns anything other than `"on"`: "tmux detected · scroll with PgUp/PgDn · or add 'set -g mouse on' to ~/.tmux.conf for wheel scroll"; only shown once per session via a `checkedTmuxMouseHint` boolean flag
- Focus-events hint fires when the probe returns anything other than `"on"`: "tmux focus-events off · add 'set -g focus-events on' to ~/.tmux.conf and reattach for focus tracking"; similarly gated by `checkedTmuxFocusHint`
- A `null` result from either probe (tmux binary not found, spawn failure, or non-zero exit code) suppresses that hint silently

**Evidence**

Tmux probe cache (search for `"tmuxMouseOptionProbe"` and `"tmuxFocusOptionProbe"`)

## Bug Fixes

- Worktree `deleteJob` now correctly detects live-process locks when deciding whether to remove an owned worktree (search for `"locked by a live Claude Code process, or with a reason we did not write"`)
- `reapJobWorktreeIfSafe` now logs why it kept a worktree that had a non-owned lock, instead of silently skipping it (search for `"reapJobWorktreeIfSafe: kept"`)
- Transcript retention cleanup is now skipped (with a logged reason) when settings contain parse errors that prevent reading `cleanupPeriodDays`, to avoid deleting transcripts with an unknown retention period (search for `"Transcript retention cleanup is paused until the settings errors above are fixed"`)
- `stream-json` stdin errors now produce a proper diagnostic message instead of a generic failure (search for `"getInputPrompt: stream-json stdin unreadable"`)
