# Claude Code v2.1.200

> Claude Code v2.1.200, released 3 Jul 2026 (2026-07-03). 21 entries read out of the shipped bundle. Unofficial, and not affiliated with Anthropic.

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

Version 2.1.200 ships full infrastructure for background observer agents — a new experimental capability where a second agent silently watches a main agent's activity and can send one-way advisory reports via a new `ObserverReport` tool. It also adds a programmatic `set_cwd` mechanism for SDK hosts, a new `askUserQuestionTimeout` setting for auto-continuing idle questions, `manual` as an accepted alias for the `default` permission mode, and expanded Claude Design tool operations. Claude Tag (Claude in Slack) documentation is now bundled into the `/claude-code` skill.

## New Features

### Observer Agents [Gradual Rollout]

**What**

A background observer agent can now be paired with any running subagent. The observer receives read-only activity digests of the observed agent's turns and can report back via the new `ObserverReport` tool. It never participates in the task directly — its only output channel is the report tool.

**Details**

- Declared in an agent definition with two new fields: `observer` (the agent type to spawn as observer) and `observerMessage` (supplemental postamble to append to each digest)
- The observer receives digests wrapped in `<agentName-activity>` tags after each of the observed agent's turns
- Observers report via `ObserverReport` with a concise message; the observed agent receives it as a one-way meta message
- The system enforces no chaining: an observer cannot itself declare an observer
- Observer agents start fresh mid-task if their context is lost (with a note indicating the restart)
- Controlled by three gates: `CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS` env var, `CLAUDE_CODE_DISABLE_BACKGROUND_TASKS` env var (disables), and `tengu_observer_agents_enabled` feature flag (default true)
- Permission gate runs at arm time and on each delivery — if denied, the pairing is retired

**Status**

Feature-flagged — requires `CLAUDE_CODE_EXPERIMENTAL_OBSERVER_AGENTS=1` to enable.

**Evidence**

Observer spawn system (search for `"[agentObserver] arm-time permission denied"`, `"observer-gate-"`, `"ObserverReport"`) — `fWn()` at ~line 351131 checks all three gates

- Flag `tengu_observer_agents_enabled`: Not enough to say (read for one account on one subscription tier against v2.1.200; this account: no value returned, anonymous baseline: no value returned, compiled default: off) 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.

### ObserverReport Tool

**What**

New tool available exclusively to observer agents for sending one-way advisory reports to the agent they are observing.

**Details**

- Takes a single `report` string parameter
- Target is resolved from the observer's pairing — no recipient to name
- Delivers to the observed agent's task queue as a meta message
- Returns an error if called outside an observer context, if the pairing is not armed, or if the observed agent is not running
- Expected usage pattern is silence: only report when something genuinely warrants it

**Evidence**

Tool implementation (search for `"ObserverReport is only available to an observer agent"`, `"Your observer pairing is not armed"`)

### `set_cwd` SDK Tool

**What**

New programmatic working-directory change mechanism for SDK hosts (e.g. Claude Desktop) — the headless twin of the interactive `/cd` command.

**Details**

- Accepts `path` (required), `trust_accepted` (boolean), and `trusted_directory` (required if `trust_accepted` is true)
- Runs the same validation, `Cd(...)` permission rules, and relocation path as the interactive `/cd`
- Returns structured responses: `ok` (with `cwd`, `changed`, `transcript_relocated`), `needs_trust` (when the directory requires a trust dialog), or `rejected` (with reason: `busy`, `not_found`, `not_a_directory`, `blocked_by_rule`, `unsafe_path`)
- Rejects requests while a turn is in progress with a clear "busy" reason
- The `trust_accepted` flow requires echoing back the exact directory string from the `needs_trust` response to pin the attestation
- Paths containing invisible or non-printing characters are rejected as unsafe

**Evidence**

New set_cwd handler (search for `"A turn is in progress — the working directory can only change"`, `"set_cwd: invalid request — path must be a non-empty string"`, `"set_cwd: invalid request — trust_accepted requires trusted_directory"`)

### Question Auto-Continue Timeout (`askUserQuestionTimeout`)

**What**

New setting that auto-continues Claude's questions after a configurable idle period, using whichever answers are selected so far.

**Usage**

`{ "askUserQuestionTimeout": "5m" }` **Details** - Accepted values: `"60s"`, `"5m"`, `"10m"`, `"never"` (default) - Only activates when explicitly set — defaults to never auto-continuing - Applies to questions Claude poses to the user during a session **Evidence** New settings field (search for `"Idle time before Claude's questions auto-continue with any answers"`, `"askUserQuestionTimeout"`)

### `manual` as Alias for `default` Permission Mode

**What**

The string `"manual"` is now accepted wherever `"default"` is accepted as a permission mode value.

**Usage**

`claude --permission-mode manual` **Details** - `manual` maps to `default` behavior internally - Works in CLI flags, settings JSON, and agent definitions - The settings schema now preprocesses the value to normalize `manual` → `default` - Allows configs that used the informal term "manual" to continue working without changes **Evidence** New alias function (search for `"Default permission mode when Claude Code needs access ('manual' is accepted as an alias for 'default')"`) — `y_()` at ~line 63398

### Remote Workflow via Environment Variables

**What**

Server-launched remote sessions (CCR) can now receive and execute a workflow script delivered through environment variables, enabling fully server-initiated workflow runs without interactive invocation.

**Details**

- `CLAUDE_REMOTE_WORKFLOW_SCRIPT`: The workflow script content (as a string)
- `CLAUDE_REMOTE_WORKFLOW_ARGS`: Optional JSON-encoded args to pass to the script
- `CLAUDE_WORKFLOW_NAME_ONLY`: Restricts workflow execution to named bundled workflows only
- Gated to sessions where `CLAUDE_CODE_REMOTE` is set; emits an error if called in a local session
- Validates the script is deterministic (no `Date.now()`, `Math.random()`, or `new Date()`)
- Compiles and runs via the same workflow engine as the interactive `Workflow` tool
- Returns JSON-encoded results or structured error codes back through the session

**Status**

Only active in remote CCR sessions; the internal slash command is hidden with no interactive use.

**Evidence**

Remote workflow handler (search for `"CLAUDE_REMOTE_WORKFLOW_SCRIPT"`, `"this command only runs inside a remote (CCR) session"`, `"workflow scripts must be deterministic"`)

## Improvements

### Claude Design Tool — Expanded Operations

The Claude Design tool gained a substantial set of new operations for managing design projects:

- `finalize_plan` — Finalizes a plan for writing to claude.ai/design; approval also grants prompt-free writes to plan paths for 15 minutes
- `write_files` — Write files to the design project
- `copy_files` — Copy files within the project
- `delete_files` — Delete files from the project
- `render_preview` — Render a design preview
- `create_support_js` — Create a support.js file
- `add_member` — Add a project member
- `update_member_role` — Change a member's role
- `remove_member` — Remove a project member
- `update_sharing` — Update project sharing settings

The `project_write` tool also gained a `present_to_user` parameter (boolean, default false) to mark a document as the user-facing deliverable. Setting it to true on routine saves is explicitly discouraged to avoid unnecessary cache busting.

**Evidence**

New operation dispatch table (search for `"Finalize plan"`, `"finalize_plan — the human is the path-review boundary"`, `"false; leave it unset for routine saves"`)

### Plan-Gated Write Permissions (15-Minute Window)

When a `finalize_plan` operation is approved, writes and deletes to the exact paths listed in the plan are automatically permitted for up to 15 minutes without additional prompts. The approval dialog now shows:

> "Approving also lets writes and deletes to exactly these paths run without another prompt for up to 15 minutes (file contents are not shown again; anything to any other path will still ask)."

**Evidence**

Plan token authorization system (search for `"Approving also lets writes and deletes to exactly these paths"`, `"approved plan expired"`, `"path not in approved plan:"`)

### Claude Tag (Claude in Slack) Documentation Added to /claude-code Skill

The `/claude-code` skill (which answers questions about Claude Code itself) now covers Claude Tag — Anthropic's Slack-native teammate surface. Its description was updated to include "and Claude Tag (Claude in Slack)." A new bundled reference file (`references/claude-tag.md`) provides offline documentation for Claude Tag, and the live-sources reference now maps Claude Tag topics to their docs URLs at `claude.com/docs/claude-tag/`.

Key points bundled:

- Claude Tag replaces the earlier per-user "Claude in Slack" app
- Users `@Claude` in a thread; an org-managed remote Claude Code session handles the task
- Configuration (repos, tools, spend limit) is an org-owner action at `claude.ai/admin-settings/claude-tag`
- The `recent-changes.md` reference now notes: "Claude in Slack (the earlier Slack app)" → "Claude Tag"

**Evidence**

Updated skill description (search for `"and Claude Tag (Claude in Slack). Verifies against the running build"`) and new bundled reference (search for `"claude-tag/overview.md"`)

### mTLS Certificate Hot-Reload

The mTLS client certificate implementation was refactored to support hot-reloading. Previously, certificates were loaded once at startup (via a singleton). Now:

- Certificates are re-read from disk whenever `CLAUDE_CODE_CLIENT_CERT` or `CLAUDE_CODE_CLIENT_KEY` changes
- An async reload function queues sequential refreshes (no concurrent reloads)
- The HTTPS agent is rebuilt only when the certificate content actually changes
- Path and content are both tracked to detect file replacement vs. content changes

Error messages are now more descriptive, reporting the certificate role (e.g., "client certificate from CLAUDE_CODE_CLIENT_CERT") rather than the file path.

**Evidence**

Refactored mTLS module (search for `"mTLS: Loaded client certificate from CLAUDE_CODE_CLIENT_CERT"`, `"mTLS: Creating HTTPS agent with custom certificates"`)

### Diff Panel: Shows Staged Files in Repos Without Commits

The diff panel now handles new git repositories that have staged files but no commits yet:

- Shows "Staged and new files" as the panel title (instead of "Branch changes")
- Shows "(no commits yet)" in the subtitle

**Evidence**

Diff panel source state handling (search for `"Staged and new files"`, `"(no commits yet)"`)

### Model ID Error Messages Now Suggest Alternatives

When an unrecognized model ID is passed (e.g., via `/model` or `--model`), the error message now:

- Checks if the input looks like a display name and suggests the correct model ID
- Uses fuzzy matching to find the closest valid model ID if available
- Falls back to "Run /model to see available models." when no good match is found

Example output: `Model "claude4" is not a recognized model id. Did you mean 'claude-opus-4-5'?`

**Evidence**

Model ID validator (search for `"is not a recognized model id."`, `"Run /model to see available models."`)

### Memory Sync Error Classification Improvements

The HTTP error handler for memory operations now parses the server error body and maps specific server error messages to typed error codes:

- `"memory store has reached its memory limit"` → `store_full`
- `"content must be at most 102400 bytes"` → `content_too_large`
- `"memory content appears to contain a credential or API key"` → `content_secret`
- Path validation failures (`"path must be at most 1024 bytes"`, `"path must be NFC-normalized"`, etc.) → `invalid_path`
- `"cannot modify archived resource"` → `store_archived`

Users will see more specific notifications when memory writes fail for these reasons, rather than generic HTTP error messages.

**Evidence**

Error classification map (search for `"memory store has reached its memory limit"`, `"cannot modify archived resource"`, `"content must be at most 102400 bytes"`)

### `/plugin` Command (Singular) Now Used in Error Messages

Error messages that previously said "Run /plugins to refresh the plugin cache" now say "Run /plugin to refresh the plugin cache" — matching the actual command name.

**Evidence**

Updated error string (search for `"Run /plugin to refresh the plugin cache"`)

### Verify Skill: Now Bootstraps Project Verify Skill

The bundled `/verify` skill description was updated to note that it "bootstraps this repo's project verify skill if none exists yet." It will create `.claude/skills/verify/SKILL.md` in the appropriate location if the project doesn't have one. The guidance was also refined: verify corrections that are project-specific should go in the closest-scoped skill file and should never be duplicated at broader scopes.

**Evidence**

Updated verify skill description (search for `"bootstraps this repo's project verify skill if none exists yet"`)

### Feedback Memory Skill Correction: Never Create New Skills (Except `verify`)

The guidance for the `feedback` memory (when Claude corrects a repeatable step) was tightened:

- Previously: "Edit existing skill files rather than creating new ones (a new project skill shadows a same-named built-in skill), with one exception: if the correction is about how to verify changes in this repo and `.claude/skills/verify/SKILL.md` does not exist, create it."
- Now: "Edit existing skill files **only**; never create one — a new project skill silently shadows a same-named built-in skill. The single exception is verify..."

The verify exception also gained guidance about scoping: the correction goes in the closest-scoped `verify/SKILL.md` (repo root vs. subproject), never duplicated.

**Evidence**

Updated feedback memory string (search for `"Edit existing skill files only; never create one"`, `"Each correction lives in exactly one skill file"`)

### `gh` CLI Detection Expanded

The regex for detecting potentially destructive `gh` CLI operations was updated to use the `gh` subcommand format (e.g., `gh pr create`, `gh issue comment`) matching the actual `gh` CLI syntax. The regex now covers: `gh pr create`, `gh pr merge`, `gh issue create`, `gh issue comment`, `gh release create`, `gh repo fork`

**Evidence**

Updated gh detection regex (search for `"ghs+(prs+create|prs+merge|issues+create|issues+comment|releases+create|repos+fork)"`)

### Background Agent Markers: `isBackgroundAgent` Field

Agent context objects for background (sidecar) agents now carry an `isBackgroundAgent: true` field. This enables the system to distinguish background agents from in-process subagents without relying on `agentType` alone.

**Evidence**

Background agent context update (search for `"isBackgroundAgent: !0"` near `"isMainSession: !0"`)

### Session History Prefetch Filters Stale Control Requests

When replaying session history from disk, the history parser now filters out any `control_request` events whose matching `control_response` or `control_cancel_request` never arrived in the recorded log. This prevents stale pending permission dialogs from re-appearing when a session is resumed.

**Evidence**

History event filter (search for `"queryWithObserverTap: missing terminal after completion"`) — `DXm()` at ~line 875907

## Bug Fixes

- `isDirEmptySync` was replaced with an async `opendir`-based empty-check, removing a synchronous I/O call from the directory scan path (search for `"isDirEmptySync"` is now absent)
- TeammateTool member removal now guards against stale removals: if a member re-joined between when a removal was initiated and when it executes, the removal is skipped with a log message `"Skipped stale removal"` (search for `"re-added after removal was initiated"`)
- Observer pairing is now retired when a session resumes (`lir()` called on session start), preventing a stale observer from a previous run from being reused across sessions
- `plansDirectory` validation now correctly handles the case where the configured path resolves to exactly the project root (previously the check `!s.startsWith(o + sep)` would incorrectly reject root-equal paths)
- The `Cd(...)` rule check for paths containing control or invisible characters now suppresses the path from the error message to avoid terminal injection (search for `"The rule text contains control or invisible characters, so it is not echoed here"`)

## In Development

### Remote Control Session Resume Improvements [In Development]

New error messages and recovery flows for Remote Control session resume failures were added, including clearer messages when a session cannot be found or has expired:

- "Couldn't reconnect to your Remote Control session. Retry, or start a fresh session without --resume."
- "Error: No recent session found in this directory or its worktrees. Run `claude remote-control` to start a new one."
- Better handling of the "environment expired" case: creates a fresh session instead of failing

**Evidence**

Updated Remote Control error strings (search for `"Couldn't reconnect to your Remote Control session"`, `"its environment has expired. Creating a fresh session instead"`)
