# Claude Code v2.1.208

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

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

Version 2.1.208 introduces Vim INSERT-mode key remaps, a new `CLAUDE_CODE_PROCESS_WRAPPER` environment variable for wrapping Claude Code process launches, shell history context integration, and Linux sandbox violation monitoring. On the Windows sandbox side, `binShell` now accepts an object form and a custom `srtWin.path` setting is available. The MCP archive-skill distribution mechanism (tar/zip via MCP) was removed, and the auto-mode opt-in dialog is gone.

## New Features

### Vim INSERT-mode key sequence remaps

**What**

Users who enable vim mode can now define custom two-character key sequences that trigger actions in INSERT mode, similar to the classic `jj → <Esc>` mapping from Vim configurations.

**Usage**

Add to `~/.claude/settings.json`:

`{ "editorMode": "vim", "vimInsertModeRemaps": { "jj": "<Esc>", "jk": "<Esc>" } }` **Details** - Each key is exactly two printable characters typed in sequence - `"<Esc>"` (return to NORMAL mode) is the only supported target value - Only active when `editorMode` is set to `"vim"` - Multiple remaps can be configured simultaneously **Evidence** New `vimInsertModeRemaps` setting schema (search for `"Vim INSERT-mode key-sequence remaps"`)

### CLAUDE_CODE_PROCESS_WRAPPER environment variable

**What**

A new environment variable that wraps every Claude Code process launch through a custom launcher binary. All background sessions, daemon-spawned sessions, and self-exec restarts will be run through the configured wrapper.

**Usage**

`# Point at an absolute path to your launcher script export CLAUDE_CODE_PROCESS_WRAPPER="/usr/local/bin/my-launcher" # Or pass as a JSON array for launchers with fixed arguments export CLAUDE_CODE_PROCESS_WRAPPER='["/usr/local/bin/my-launcher", "--profile", "claude"]'` **Details** - Must be an absolute path (bare names resolved via PATH are not accepted) - On Windows, the wrapper is not supported — sessions run unwrapped and a warning is logged - The launcher must exec into Claude Code rather than daemonize; a launcher that daemonizes is detected and rejected - If the configured launcher path is deleted or becomes non-executable, new background sessions are refused rather than started unwrapped - Project-scoped settings files (`.claude/settings.json` and `.claude/settings.local.json`) cannot configure `CLAUDE_CODE_PROCESS_WRAPPER`; it must be in user settings or managed settings - Run `claude status` to see the current wrapper configuration and any errors **Evidence** New `CLAUDE_CODE_PROCESS_WRAPPER` constant (search for `"CLAUDE_CODE_PROCESS_WRAPPER"`)

### Shell history context integration (with opt-in)

**What**

When a user opts in at the context-gathering prompt, Claude now reads shell command history from common history files and includes a filtered view (command words only, no arguments that might carry secrets) in the system prompt context.

**Details**

- Supported history files: `~/.bash_history`, `~/.zsh_history`, `~/.local/share/fish/fish_history`, `~/.local/share/powershell/PSReadLine/ConsoleHost_history.txt` (Linux/macOS), and `%APPDATA%\...\PSReadLine\ConsoleHost_history.txt` (Windows)
- Only command words are included — raw history lines with inline arguments (which may contain secrets) are never read into the transcript
- If the home directory is a network path (UNC share or automount), history is skipped to avoid unintended network authentication
- The feature is gated by an explicit user opt-in at the Q3 context question; if not asked, history is marked "NOT GATHERED"

**Evidence**

History file paths (search for `"~/.bash_history"` and `"PSReadLine"`)

### GitHub repo visibility and branch protection context

**What**

Claude now gathers repository visibility (public/private), branch protection rules, and rulesets from GitHub via `gh` when working in a git repository. This gives Claude better context for decisions about pushing, branching, and code review workflows.

**Details**

- Uses `gh` CLI to query `/rulesets?per_page=100` and `/branches?protected=true&per_page=100`
- Includes org-level sibling repo docs (top 50 by `pushedAt`)
- Degrades gracefully when `gh` is unavailable, unauthenticated, or the token lacks org scope — each section shows a "not queryable here" marker rather than failing
- Org/repo docs are candidates only — Claude filters to those whose org already appears in known repo facts

**Evidence**

New repo context gathering (search for `"Repo visibility & branch protection (via gh)"` and `"/rulesets?per_page=100"`)

### Linux sandbox violation monitor

**What**

When running with the Linux sandbox enabled, Claude now starts a Unix-socket observer that monitors for filesystem violations (writes to paths that should be denied). Violations are reported in real time rather than only being caught after the fact.

**Details**

- Creates a temporary socket file under `/tmp/srt-obs-*`
- Receives structured violation events (syscall name, path, command) from the sandbox kernel module
- Applies `ignoreViolations` filters (by path prefix and by command name)
- The monitor socket path is passed to the sandbox so it can report outbound writes
- If the socket fails to start, violation monitoring is disabled but the sandbox itself continues running

**Evidence**

Linux sandbox monitor (search for `"Started Linux seccomp violation monitor"` and `"[Sandbox Linux Monitor]"`)

### Permission rule label filtering

**What**

The `/permissions` command (and related CLI output) now accepts a `--label <prefix>` option to filter displayed rules to only those whose label starts with the given prefix.

**Usage**

`/permissions --label bash /permissions --label read:` **Details** - The filter is case-insensitive - Matching is prefix-based (not substring) - Useful for navigating large permission sets created by hooks or plugins **Evidence** New `--label` flag (search for `"--label <prefix>"` and `"Show only rules whose label starts with this prefix"`)

## Improvements

### Windows sandbox: binShell now accepts object form and custom srt-win path

**What**

Two improvements to the Windows sandbox configuration.

First, `binShell` can now be specified as an object `{"exe": "...", "args": [...]}` instead of only as a string token. This allows passing absolute paths to shells with custom argument arrays. The object form is Windows-only and is rejected on macOS/Linux.

Second, a new `windows.srtWin.path` setting allows pointing the sandbox at a custom `srt-win.exe` binary instead of the packaged one.

**Details**

- `binShell` string form: bare token (`cmd`, `powershell`, `pwsh`) or absolute path to `bash.exe`/`sh.exe`/`pwsh.exe`/`powershell.exe`
- `binShell` object form: `{"exe": "<absolute path>", "args": ["..."]}`
- Error message updated: now accepts `pwsh.exe` and `powershell.exe` in addition to the previous `bash.exe`/`sh.exe`
- `windows.srtWin.path`: if set, the file must exist; remove the key to fall back to the packaged binary
- CA cert path is now passed to sandbox commands, enabling custom CA trust in Windows sandbox mode

**Evidence**

`binShell` object form (search for `"binShell object form is Windows-only"`) and srtWin path (search for `"windows.srtWin.path is set to"`)

### set_max_thinking_tokens: null or omitted now resets to session default

**What**

When calling `set_max_thinking_tokens` with `max_thinking_tokens` omitted or null, thinking now resets to the session default rather than keeping the previously-set mid-session override. This makes it possible to undo a thinking budget adjustment without restarting the session.

**Details**

- Previously, `max_thinking_tokens: null` had ambiguous behavior
- Now: omitting or setting to null clears any mid-session budget override back to the spawn-time budget
- For sessions where thinking is disabled, this keeps thinking disabled
- `max_thinking_tokens` must be an integer (or null); non-integer numbers are now rejected

**Evidence**

Updated `set_max_thinking_tokens` description (search for `"When max_thinking_tokens is omitted or null, thinking resets to the session default"`)

### Monitor tool description adapts to interactive vs non-interactive context

**What**

The Monitor tool's guidance text now varies based on whether the session is interactive. In interactive sessions (where the user is present at a terminal), Claude is now told to use a foreground Bash `until` loop for single-notification "tell me when ready" cases. In non-interactive/background sessions, the previous `run_in_background` recommendation is kept.

**Details**

- For single-notification use cases in interactive sessions: "run the command in the foreground with Bash, exiting when the condition is true"
- For single-notification use cases in non-interactive sessions: "use Bash with `run_in_background`"
- The "don't use unbounded command for a single notification" warning likewise adapts its phrasing to the context

**Evidence**

Monitor tool description function (search for `"run the command in the **foreground with Bash**"`)

### Credential masking: extract patterns with onExtractNoMatch control

**What**

The `credentials.envVars` credential masking feature now supports an `extract` regex pattern to pull a sub-token out of an environment variable's value before masking. A new `onExtractNoMatch` option controls what happens when the pattern doesn't match.

**Details**

- `extract`: a regex applied to the env var value; only the first capture group is masked
- `onExtractNoMatch`:
- `"warn"` (default): variable is left unprotected, a console warning is emitted
- `"deny"`: variable is unset entirely from the sandbox environment
- `"error"`: an error is thrown and the sandbox refuses to start
- A runtime warning is logged when `"warn"` leaves a variable unprotected, making the risk visible in the log

**Evidence**

Credential extract pattern (search for `"credentials.envVars entry"` and `"onExtractNoMatch"`)

### GitHub App check now returns default branch and transient status

**What**

The internal GitHub App preflight check now returns the repository's default branch (when available from the API response) and a `transient` flag distinguishing permanent failures from those that might succeed on retry.

**Details**

- `defaultBranch`: populated from `repo.default_branch` in the API response; used by the remote agent to avoid reusing the default branch as its work branch
- `transient: true`: network errors, timeouts (408, 429), and null-response profile fetches
- `transient: false`: deterministic failures like missing token scopes or 4xx non-rate-limit responses
- Improved log message when org UUID is missing: distinguishes between "profile fetch null (possibly transient)" and "token lacks user:profile scope (deterministic)"

**Evidence**

GitHub App check refactor (search for `"checkGithubAppInstalled: No org UUID found (token lacks user:profile scope"`)

### Official plugin prompt overrides via server-side feature flag

**What**

Anthropic can now push prompt overrides for official (first-party) plugins via the `tengu_official_plugin_prompt_overrides` GrowthBook feature flag. This allows updating plugin instructions server-side without requiring a CLI release.

**Details**

- Applies only to plugins from Anthropic's marketplace or known official plugin names
- Overridable fields: `server_instructions`, `server_instructions_by_server`, `tools`, `search_hints`, `param_descriptions`, `prompts`, `skills`
- If the GrowthBook payload fails schema validation, the baked-in plugin text is used and an error is logged
- Per-server instruction overrides via `server_instructions_by_server` let different MCP servers within the same plugin get different instructions

**Evidence**

Plugin prompt override (search for `"tengu_official_plugin_prompt_overrides"`)

### Ripgrep null byte protection

**What**

Ripgrep (used by the Grep tool) now refuses to spawn if any argument, the target path, or the session working directory contains a null byte (`\0`). Previously, this could produce confusing failures deep in process spawning.

**Details**

- Throws `RipgrepNullByteError` with a specific message identifying which argument contains the null byte
- Checked in order: session cwd, target path, caller arguments
- The check happens before spawning, so the error is surfaced at the tool level rather than as a cryptic OS error

**Evidence**

Null byte guard (search for `"ripgrep spawn blocked: null byte in session cwd"`)

### New structured error types

**What**

Three new error classes are introduced for cleaner error handling and telemetry:

- `RipgrepNullByteError`: thrown when ripgrep is called with a null byte in its arguments
- `RipgrepUsageError`: thrown when ripgrep rejects the pattern, glob, or file type filter without searching (previously these were untyped failures)
- `SelectedRangeTooLargeError`: thrown when a requested line range exceeds the readable limit; the error message now names the limit and suggests searching for specific content instead
- `BedrockUnexpectedContentTypeError`: thrown when a Bedrock streaming response has an unexpected content-type (not `application/vnd.amazon.eventstream`); includes guidance to set `CLAUDE_CODE_DISABLE_BEDROCK_CONTENT_TYPE_GUARD=1` to suppress while a gateway is being fixed

**Evidence**

New error classes (search for `"RipgrepNullByteError"`, `"RipgrepUsageError"`, `"SelectedRangeTooLargeError"`, `"BedrockUnexpectedContentType"`)

### MCP server bearer credential rejection: clearer error and automatic retry

**What**

When an MCP server rejects Claude's session credential with an HTTP 401, the connection is now tagged with a dedicated `CLI_OWNED_BEARER_REJECTED` error code and the error message explicitly states the credential will be retried on the next refresh cycle. Previously, bearer rejection was handled identically to other connection failures.

**Evidence**

New bearer rejection handler (search for `"CLI_OWNED_BEARER_REJECTED"`)

### Engine log prefix renamed from [shoji-engine] to [engine]

**What**

Debug log messages from the session engine now use the prefix `[engine]` instead of the old `[shoji-engine]` prefix. Similarly, `[shoji]` prefixes on other wire-layer messages have been updated. This affects diagnostic output in `claude --debug` and log files.

**Evidence**

Prefix rename (removed: `"[shoji-engine]"`, added: `"[engine]"`)

## Bug Fixes

- File deny rules now block edits, not just reads. A new clear error message is shown when a file is covered by a Read deny rule and the user attempts to edit it: "File is covered by a Read deny rule in your permission settings and cannot be edited." (search for `"File is covered by a Read deny rule"`)

- Ripgrep usage errors (invalid patterns, unsupported glob syntax, unknown file types) are now caught and reported as `RipgrepUsageError` rather than surfacing as raw subprocess failures. The error message includes the rejection reason: "Search failed — ripgrep rejected the pattern, glob, or file type without searching" (search for `"Search failed — ripgrep rejected the pattern"`)

- The `apiKeyHelper` script failure notification is now a clear user-facing message: "Your apiKeyHelper script is failing · This usually means you need to re-authenticate with your provider · Run /status to see the script's error output" (search for `"Your apiKeyHelper script is failing"`)

- Symlink resolution in the Linux sandbox deny-path logic was improved: deny paths are now resolved through symlinks before enforcement to avoid false positives when a deny path target is accessed via a symlink (search for `"[Sandbox Linux] Resolve symlinked deny path"`)

## Removed

### MCP archive skill distribution removed

MCP skills can no longer be distributed as `.tar.gz` or `.zip` archives via the `mcp-skill-archive:` URI scheme. The entire archive download, extraction, validation, and caching pipeline has been removed.

If you were distributing skills this way, you must now distribute them as direct MCP server resources or as local directory skills. Skills already cached from previous versions may remain on disk in the extraction directory but will no longer be updated or loaded.

**Evidence**

All tar/zip archive parsing functions removed (search for `"mcp-skill-archive:"`, `"Downloading skill archive from"` — these strings are absent from v2.1.208)

### Auto-mode opt-in dialog removed

The interactive "Enable auto mode?" prompt that appeared for some users has been removed. The strings "Enable auto mode?", "Yes, enable auto mode", "Yes, and make it my default mode", and "No, don't ask again" no longer appear in the codebase. Auto mode is now configured via settings rather than through an in-session dialog.

**Evidence**

Removed auto-mode opt-in strings (search for `"showAutoModeOptIn"` — absent from v2.1.208)

### Plan artifact HTML template unbundled

The full Anthropic CDS design token CSS block and plan artifact HTML template that were previously embedded inline in the CLI bundle have been removed. The plan artifact generation still works, but the template is no longer shipped inside the CLI binary.

**Evidence**

Large CDS token block and `u0s` / `Jvd` template variables removed from bundle
