Follow Discord
Sweep 28 Sep 2026 · 18:16Z Build v2.1.284 505 read Stable v2.1.277 Latest v2.1.284 Next v2.1.284 Feeds RSS JSON llms.txt llms-full.txt Unofficial
One capture · claude-code

One read of Claude Code CLIclaude-code-20260928T233702Z

154 pages moved out of 210 read.

Pages moved 154 significant first
Pages read 210 in this capture
Captured 23:37 UTC
Corpus hash 82a8d4497843 corpus-hash

What this read moved

26-50 of 154, page 2 of 7

This capture is too large to show at once. Changes 26-50 of 154 are below, significant first; the rest are on the following screens.

agent-sdk/tool-search Changed · +7 / -7 lines

from line 34
3434 
3535The SDK also disables tool search when `ANTHROPIC_BASE_URL` points to a non-first-party host, since most proxies don't forward `tool_reference` blocks. You can override that default with the `ENABLE_TOOL_SEARCH` environment variable:
3636 
37| Value | Behavior |
38| :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
39| (unset) | Tool search is on. Tool definitions are deferred and discovered on demand. Falls back to loading upfront on Google Cloud's Agent Platform models earlier than the Claude 4.5 generation, a non-first-party `ANTHROPIC_BASE_URL`, or a Microsoft Foundry deployment hosted on Azure. |
40| `true` | Tool search is always on, except on a Microsoft Foundry deployment hosted on Azure, where the server-side rejection still forces upfront loading, and on Google Cloud's Agent Platform models earlier than the Claude 4.5 generation, where the SDK keeps loading tool definitions upfront. The SDK sends the beta header through proxies, and requests fail on proxies that don't support `tool_reference` blocks. |
41| `auto` | Counts the tokens in the tool definitions that tool search can defer and compares the total against the model's context window. When the total reaches 10% of the window, tool search activates. Below that, the SDK loads every tool definition into context upfront. |
42| `auto:N` | Same as `auto` with a custom percentage. `auto:5` activates when those definitions reach 5% of the context window. Lower values activate sooner. |
43| `false` | Tool search is off. All tool definitions are loaded into context on every turn. |
37| Value | Behavior |
38| :- | :- |
39| (unset) | Tool search is on. Tool definitions are deferred and discovered on demand. Falls back to loading upfront on Google Cloud's Agent Platform models earlier than the Claude 4.5 generation, a non-first-party `ANTHROPIC_BASE_URL`, or a Microsoft Foundry deployment hosted on Azure. |
40| `true` | Tool search is always on, except on a Microsoft Foundry deployment hosted on Azure, where the server-side rejection still forces upfront loading, and on Google Cloud's Agent Platform models earlier than the Claude 4.5 generation, where the SDK keeps loading tool definitions upfront. The SDK sends the beta header through proxies, and requests fail on proxies that don't support `tool_reference` blocks. |
41| `auto` | Counts the tokens in the tool definitions that tool search can defer and compares the total against the model's context window. When the total reaches 10% of the window, tool search activates. Below that, the SDK loads every tool definition into context upfront. |
42| `auto:N` | Same as `auto` with a custom percentage. `auto:5` activates when those definitions reach 5% of the context window. Lower values activate sooner. |
43| `false` | Tool search is off. All tool definitions are loaded into context on every turn. |
4444 
4545Setting [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS`](/docs/en/env-vars) keeps tool search off. You can't override it by setting `ENABLE_TOOL_SEARCH` yourself. Your organization can keep tool search on through [managed settings](/docs/en/managed-settings), on Claude Code v2.1.227 or later. [Disable pre-release capabilities](/docs/en/llm-gateway-protocol#disable-pre-release-capabilities) covers where the override applies and what the variable strips.
4646 

agent-sdk/troubleshooting Changed · +16 / -16 lines

from line 6
66 
77Symptoms tied to a feature, such as a hook not firing or a skill not being used, have a troubleshooting section on that feature's page. The table names the section or page that covers each symptom:
88 
9| Symptom | Go to |
10| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------- |
11| Skills not found, a skill not being used, `Invalid skill name` error | [Skills troubleshooting](/docs/en/agent-sdk/skills#troubleshooting) |
12| MCP server shows `failed` status, tools not being called, connection timeouts, tool output that exceeds the maximum allowed tokens | [MCP troubleshooting](/docs/en/agent-sdk/mcp#troubleshooting) |
13| Plugin not loading, plugin skills not appearing | [Plugins troubleshooting](/docs/en/agent-sdk/plugins#troubleshooting) |
14| Claude not delegating to subagents, filesystem-based agents not loading | [Subagents troubleshooting](/docs/en/agent-sdk/subagents#troubleshooting) |
15| Checkpointing options not recognized, user messages without UUIDs, `No file checkpoint found`, `File rewinding is not enabled`, `ProcessTransport is not ready for writing` | [File checkpointing troubleshooting](/docs/en/agent-sdk/file-checkpointing#troubleshooting) |
16| Hook not firing, matcher not filtering as expected, hook timeout, tool blocked unexpectedly, modified input not applied, session hooks not available in Python, subagent permission prompts multiplying, recursive hook loops with subagents, `systemMessage` not appearing in output | [Fix common issues](/docs/en/agent-sdk/hooks#fix-common-issues) on the hooks page |
17| An agent that works on your machine fails in a deployed service or container | [Troubleshoot deployment failures](/docs/en/agent-sdk/hosting#troubleshoot-deployment-failures) |
18| `Not logged in`, `Invalid API key`, `API Error`, `429`, `There's an issue with the selected model` | [Error reference](/docs/en/errors#find-your-error) |
19| `CLINotFoundError`, `CLIConnectionError`, `ProcessError`, `Claude Code process exited with code N`, `Claude Code returned an error result`, `structured_output` is `None` | [CLI startup](#cli-startup), [CLI process exit](#cli-process-exit), and [Structured outputs](#structured-outputs) on this page |
9| Symptom | Go to |
10| :- | :- |
11| Skills not found, a skill not being used, `Invalid skill name` error | [Skills troubleshooting](/docs/en/agent-sdk/skills#troubleshooting) |
12| MCP server shows `failed` status, tools not being called, connection timeouts, tool output that exceeds the maximum allowed tokens | [MCP troubleshooting](/docs/en/agent-sdk/mcp#troubleshooting) |
13| Plugin not loading, plugin skills not appearing | [Plugins troubleshooting](/docs/en/agent-sdk/plugins#troubleshooting) |
14| Claude not delegating to subagents, filesystem-based agents not loading | [Subagents troubleshooting](/docs/en/agent-sdk/subagents#troubleshooting) |
15| Checkpointing options not recognized, user messages without UUIDs, `No file checkpoint found`, `File rewinding is not enabled`, `ProcessTransport is not ready for writing` | [File checkpointing troubleshooting](/docs/en/agent-sdk/file-checkpointing#troubleshooting) |
16| Hook not firing, matcher not filtering as expected, hook timeout, tool blocked unexpectedly, modified input not applied, session hooks not available in Python, subagent permission prompts multiplying, recursive hook loops with subagents, `systemMessage` not appearing in output | [Fix common issues](/docs/en/agent-sdk/hooks#fix-common-issues) on the hooks page |
17| An agent that works on your machine fails in a deployed service or container | [Troubleshoot deployment failures](/docs/en/agent-sdk/hosting#troubleshoot-deployment-failures) |
18| `Not logged in`, `Invalid API key`, `API Error`, `429`, `There's an issue with the selected model` | [Error reference](/docs/en/errors#find-your-error) |
19| `CLINotFoundError`, `CLIConnectionError`, `ProcessError`, `Claude Code process exited with code N`, `Claude Code returned an error result`, `structured_output` is `None` | [CLI startup](#cli-startup), [CLI process exit](#cli-process-exit), and [Structured outputs](#structured-outputs) on this page |
2020 
2121## CLI startup
2222 
from line 68
6868 
6969The SDK found a file at the resolved path but couldn't launch it. Python raises these failures as a `CLIConnectionError`. TypeScript rejects the message iteration with an error carrying no SDK class. The table below maps each message to what it tells you. Match the message you see:
7070 
71| Message | SDK | What it tells you |
72| ----------------------------------------------------------------- | ---------- | -------------------------------------------------------------------- |
73| `Failed to start Claude Code: <detail>` | Python | The rest of the message is the operating system's own error |
74| `Claude Code executable at <path> exists but failed to launch` | TypeScript | The script at the configured path can't run |
71| Message | SDK | What it tells you |
72| - | - | - |
73| `Failed to start Claude Code: <detail>` | Python | The rest of the message is the operating system's own error |
74| `Claude Code executable at <path> exists but failed to launch` | TypeScript | The script at the configured path can't run |
7575| `Claude Code native binary at <path> exists but failed to launch` | TypeScript | The binary can't run, with a libc suggestion appended to the message |
76| `Failed to spawn Claude Code process: <detail>` | TypeScript | Any other launch failure |
76| `Failed to spawn Claude Code process: <detail>` | TypeScript | Any other launch failure |
7777 
7878In both SDKs, the usual cause is a resolved path that points at something that can't run, such as a text file, a directory, or a file without execute permission. Read the native-binary message's libc suggestion as one possible cause.
7979 

agent-sdk/typescript Changed · +390 / -390 lines

This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.

The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.

from line 72
7272 
7373#### Parameters
7474 
75| Parameter | Type | Description |
76| :-------- | :--------------------------------------------------------------- | :---------------------------------------------------------------- |
77| `prompt` | `string \| AsyncIterable<`[`SDKUserMessage`](#sdkusermessage)`>` | The input prompt as a string or async iterable for streaming mode |
78| `options` | [`Options`](#options) | Optional configuration object (see Options type below) |
75| Parameter | Type | Description |
76| :- | :- | :- |
77| `prompt` | `string \| AsyncIterable<`[`SDKUserMessage`](#sdkusermessage)`>` | The input prompt as a string or async iterable for streaming mode |
78| `options` | [`Options`](#options) | Optional configuration object (see Options type below) |
7979 
8080#### Returns
8181 
from line 94
9494 
9595#### Parameters
9696 
97| Parameter | Type | Description |
98| :-------------------- | :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
99| `options` | [`Options`](#options) | Optional configuration object. Same as the `options` parameter to `query()` |
100| `initializeTimeoutMs` | `number` | Maximum time in milliseconds to wait for subprocess initialization. Defaults to `60000`. If initialization does not complete in time, the promise rejects with a timeout error |
97| Parameter | Type | Description |
98| :- | :- | :- |
99| `options` | [`Options`](#options) | Optional configuration object. Same as the `options` parameter to `query()` |
100| `initializeTimeoutMs` | `number` | Maximum time in milliseconds to wait for subprocess initialization. Defaults to `60000`. If initialization does not complete in time, the promise rejects with a timeout error |
101101 
102102#### Returns
103103 
from line 177
177177 
178178#### Parameters
179179 
180| Parameter | Type | Description |
181| :------------ | :----------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
182| `name` | `string` | The name of the tool |
183| `description` | `string` | A description of what the tool does |
184| `inputSchema` | `Schema extends AnyZodRawShape` | Zod schema defining the tool's input parameters (supports both Zod 3 and Zod 4) |
185| `handler` | `(args, extra) => Promise<`[`CallToolResult`](#calltoolresult)`>` | Async function that executes the tool logic |
186| `extras` | `{ annotations?: `[`ToolAnnotations`](#toolannotations)`; searchHint?: string; alwaysLoad?: boolean }` | Optional extras. `annotations` provides MCP behavioral hints to clients. `searchHint` is a one-line capability phrase shown in the deferred-tool list when [tool search](/docs/en/agent-sdk/tool-search) is active. `alwaysLoad: true` keeps this tool's full schema in the initial prompt instead of deferring it |
180| Parameter | Type | Description |
181| :- | :- | :- |
182| `name` | `string` | The name of the tool |
183| `description` | `string` | A description of what the tool does |
184| `inputSchema` | `Schema extends AnyZodRawShape` | Zod schema defining the tool's input parameters (supports both Zod 3 and Zod 4) |
185| `handler` | `(args, extra) => Promise<`[`CallToolResult`](#calltoolresult)`>` | Async function that executes the tool logic |
186| `extras` | `{ annotations?: `[`ToolAnnotations`](#toolannotations)`; searchHint?: string; alwaysLoad?: boolean }` | Optional extras. `annotations` provides MCP behavioral hints to clients. `searchHint` is a one-line capability phrase shown in the deferred-tool list when [tool search](/docs/en/agent-sdk/tool-search) is active. `alwaysLoad: true` keeps this tool's full schema in the initial prompt instead of deferring it |
187187 
188188#### `ToolAnnotations`
189189 
190190Defined in `@modelcontextprotocol/sdk/types.js`. All fields are optional hints; clients should not rely on them for security decisions.
191191 
192| Field | Type | Default | Description |
193| :---------------- | :-------- | :---------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- |
194| `title` | `string` | `undefined` | Human-readable title for the tool |
195| `readOnlyHint` | `boolean` | `false` | If `true`, the tool does not modify its environment |
196| `destructiveHint` | `boolean` | `true` | If `true`, the tool may perform destructive updates (only meaningful when `readOnlyHint` is `false`) |
197| `idempotentHint` | `boolean` | `false` | If `true`, repeated calls with the same arguments have no additional effect (only meaningful when `readOnlyHint` is `false`) |
198| `openWorldHint` | `boolean` | `true` | If `true`, the tool interacts with external entities (for example, web search). If `false`, the tool's domain is closed (for example, a memory tool) |
192| Field | Type | Default | Description |
193| :- | :- | :- | :- |
194| `title` | `string` | `undefined` | Human-readable title for the tool |
195| `readOnlyHint` | `boolean` | `false` | If `true`, the tool does not modify its environment |
196| `destructiveHint` | `boolean` | `true` | If `true`, the tool may perform destructive updates (only meaningful when `readOnlyHint` is `false`) |
197| `idempotentHint` | `boolean` | `false` | If `true`, repeated calls with the same arguments have no additional effect (only meaningful when `readOnlyHint` is `false`) |
198| `openWorldHint` | `boolean` | `true` | If `true`, the tool interacts with external entities (for example, web search). If `false`, the tool's domain is closed (for example, a memory tool) |
199199 
200200```typescript theme={null}
201201import { tool } from "@anthropic-ai/claude-agent-sdk";
from line 229
229229 
230230#### Parameters
231231 
232| Parameter | Type | Description |
233| :--------------------- | :---------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
234| `options.name` | `string` | The name of the MCP server |
235| `options.version` | `string` | Optional version string |
236| `options.instructions` | `string` | Optional server instructions, returned from `initialize` and surfaced to the model as an MCP instructions block |
237| `options.tools` | `Array<SdkMcpToolDefinition>` | Array of tool definitions created with [`tool()`](#tool) |
238| `options.alwaysLoad` | `boolean` | When `true`, every tool from this server stays in the initial prompt and is never deferred behind [tool search](/docs/en/agent-sdk/tool-search). Combines with per-tool `alwaysLoad` in [`tool()`](#tool) |
239| `options.timeout` | `number` | Timeout in milliseconds for this server's tool calls. Claude Code applies it to this server in place of [`MCP_TOOL_TIMEOUT`](/docs/en/env-vars). Pass a whole number of at least 1000. Claude Code ignores other values. Requires TypeScript Agent SDK v0.3.248 or later |
232| Parameter | Type | Description |
233| :- | :- | :- |
234| `options.name` | `string` | The name of the MCP server |
235| `options.version` | `string` | Optional version string |
236| `options.instructions` | `string` | Optional server instructions, returned from `initialize` and surfaced to the model as an MCP instructions block |
237| `options.tools` | `Array<SdkMcpToolDefinition>` | Array of tool definitions created with [`tool()`](#tool) |
238| `options.alwaysLoad` | `boolean` | When `true`, every tool from this server stays in the initial prompt and is never deferred behind [tool search](/docs/en/agent-sdk/tool-search). Combines with per-tool `alwaysLoad` in [`tool()`](#tool) |
239| `options.timeout` | `number` | Timeout in milliseconds for this server's tool calls. Claude Code applies it to this server in place of [`MCP_TOOL_TIMEOUT`](/docs/en/env-vars). Pass a whole number of at least 1000. Claude Code ignores other values. Requires TypeScript Agent SDK v0.3.248 or later |
240240 
241241### `listSessions()`
242242 
from line 248
248248 
249249#### Parameters
250250 
251| Parameter | Type | Default | Description |
252| :------------------------- | :-------- | :---------- | :--------------------------------------------------------------------------------- |
253| `options.dir` | `string` | `undefined` | Directory to list sessions for. When omitted, returns sessions across all projects |
254| `options.limit` | `number` | `undefined` | Maximum number of sessions to return |
255| `options.includeWorktrees` | `boolean` | `true` | When `dir` is inside a git repository, include sessions from all worktree paths |
251| Parameter | Type | Default | Description |
252| :- | :- | :- | :- |
253| `options.dir` | `string` | `undefined` | Directory to list sessions for. When omitted, returns sessions across all projects |
254| `options.limit` | `number` | `undefined` | Maximum number of sessions to return |
255| `options.includeWorktrees` | `boolean` | `true` | When `dir` is inside a git repository, include sessions from all worktree paths |
256256 
257257#### Return type: `SDKSessionInfo`
258258 
259| Property | Type | Description |
260| :------------- | :-------------------- | :--------------------------------------------------------------------------------------- |
261| `sessionId` | `string` | Unique session identifier (UUID) |
262| `summary` | `string` | Display title: custom title, most recent prompt, auto-generated summary, or first prompt |
263| `lastModified` | `number` | Last modified time in milliseconds since epoch |
264| `fileSize` | `number \| undefined` | Session file size in bytes. Only populated for local JSONL storage |
265| `customTitle` | `string \| undefined` | User-set session title (via `/rename`) |
266| `firstPrompt` | `string \| undefined` | First meaningful user prompt in the session |
267| `gitBranch` | `string \| undefined` | Git branch at the end of the session |
268| `cwd` | `string \| undefined` | Working directory for the session |
269| `tag` | `string \| undefined` | User-set session tag (see [`tagSession()`](#tagsession)) |
270| `createdAt` | `number \| undefined` | Creation time in milliseconds since epoch, from the first entry's timestamp |
259| Property | Type | Description |
260| :- | :- | :- |
261| `sessionId` | `string` | Unique session identifier (UUID) |
262| `summary` | `string` | Display title: custom title, most recent prompt, auto-generated summary, or first prompt |
263| `lastModified` | `number` | Last modified time in milliseconds since epoch |
264| `fileSize` | `number \| undefined` | Session file size in bytes. Only populated for local JSONL storage |
265| `customTitle` | `string \| undefined` | User-set session title (via `/rename`) |
266| `firstPrompt` | `string \| undefined` | First meaningful user prompt in the session |
267| `gitBranch` | `string \| undefined` | Git branch at the end of the session |
268| `cwd` | `string \| undefined` | Working directory for the session |
269| `tag` | `string \| undefined` | User-set session tag (see [`tagSession()`](#tagsession)) |
270| `createdAt` | `number \| undefined` | Creation time in milliseconds since epoch, from the first entry's timestamp |
271271 
272272#### Example
273273 
from line 296
296296 
297297#### Parameters
298298 
299| Parameter | Type | Default | Description |
300| :--------------- | :------- | :---------- | :---------------------------------------------------------------------------- |
301| `sessionId` | `string` | required | Session UUID to read (see `listSessions()`) |
302| `options.dir` | `string` | `undefined` | Project directory to find the session in. When omitted, searches all projects |
303| `options.limit` | `number` | `undefined` | Maximum number of messages to return |
304| `options.offset` | `number` | `undefined` | Number of messages to skip from the start |
299| Parameter | Type | Default | Description |
300| :- | :- | :- | :- |
301| `sessionId` | `string` | required | Session UUID to read (see `listSessions()`) |
302| `options.dir` | `string` | `undefined` | Project directory to find the session in. When omitted, searches all projects |
303| `options.limit` | `number` | `undefined` | Maximum number of messages to return |
304| `options.offset` | `number` | `undefined` | Number of messages to skip from the start |
305305 
306306#### Return type: `SessionMessage`
307307 
308| Property | Type | Description |
309| :------------------- | :---------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
310| `type` | `"user" \| "assistant"` | Message role |
311| `uuid` | `string` | Unique message identifier |
312| `session_id` | `string` | Session this message belongs to |
313| `message` | `unknown` | Raw message payload from the transcript |
314| `parent_tool_use_id` | `string \| null` | For subagent messages, the `tool_use_id` of the `Agent` or `Skill` tool call that started the subagent. `null` for main-session messages and older sessions |
315| `parent_agent_id` | `string \| null` | For messages from a [nested subagent](/docs/en/sub-agents#let-subagents-spawn-their-own-subagents), the `agentId` of the subagent that spawned it. `null` for main-session messages, messages from top-level subagents, and older sessions. Requires Claude Code v2.1.202 or later |
308| Property | Type | Description |
309| :- | :- | :- |
310| `type` | `"user" \| "assistant"` | Message role |
311| `uuid` | `string` | Unique message identifier |
312| `session_id` | `string` | Session this message belongs to |
313| `message` | `unknown` | Raw message payload from the transcript |
314| `parent_tool_use_id` | `string \| null` | For subagent messages, the `tool_use_id` of the `Agent` or `Skill` tool call that started the subagent. `null` for main-session messages and older sessions |
315| `parent_agent_id` | `string \| null` | For messages from a [nested subagent](/docs/en/sub-agents#let-subagents-spawn-their-own-subagents), the `agentId` of the subagent that spawned it. `null` for main-session messages, messages from top-level subagents, and older sessions. Requires Claude Code v2.1.202 or later |
316316 
317317#### Example
318318 
from line 346
346346 
347347#### Parameters
348348 
349| Parameter | Type | Default | Description |
350| :------------ | :------- | :---------- | :--------------------------------------------------------------------- |
351| `sessionId` | `string` | required | UUID of the session to look up |
349| Parameter | Type | Default | Description |
350| :- | :- | :- | :- |
351| `sessionId` | `string` | required | UUID of the session to look up |
352352| `options.dir` | `string` | `undefined` | Project directory path. When omitted, searches all project directories |
353353 
354354Returns [`SDKSessionInfo`](#return-type-sdksessioninfo), or `undefined` if the session is not found.
from line 367
367367 
368368#### Parameters
369369 
370| Parameter | Type | Default | Description |
371| :------------ | :------- | :---------- | :--------------------------------------------------------------------- |
372| `sessionId` | `string` | required | UUID of the session to rename |
373| `title` | `string` | required | New title. Must be non-empty after trimming whitespace |
370| Parameter | Type | Default | Description |
371| :- | :- | :- | :- |
372| `sessionId` | `string` | required | UUID of the session to rename |
373| `title` | `string` | required | New title. Must be non-empty after trimming whitespace |
374374| `options.dir` | `string` | `undefined` | Project directory path. When omitted, searches all project directories |
375375 
376376### `tagSession()`
from line 387
387387 
388388#### Parameters
389389 
390| Parameter | Type | Default | Description |
391| :------------ | :--------------- | :---------- | :--------------------------------------------------------------------- |
392| `sessionId` | `string` | required | UUID of the session to tag |
393| `tag` | `string \| null` | required | Tag string, or `null` to clear |
394| `options.dir` | `string` | `undefined` | Project directory path. When omitted, searches all project directories |
390| Parameter | Type | Default | Description |
391| :- | :- | :- | :- |
392| `sessionId` | `string` | required | UUID of the session to tag |
393| `tag` | `string \| null` | required | Tag string, or `null` to clear |
394| `options.dir` | `string` | `undefined` | Project directory path. When omitted, searches all project directories |
395395 
396396### `resolveSettings()`
397397 
from line 417
417417 
418418`resolveSettings()` accepts a single options object. All fields are optional.
419419 
420| Parameter | Type | Default | Description |
421| :------------------------------ | :------------------------------------ | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
422| `options.cwd` | `string` | `process.cwd()` | Directory to resolve project and local settings relative to |
423| `options.settingSources` | [`SettingSource`](#settingsource)`[]` | All sources | Which filesystem sources to load. Pass `[]` to skip user, project, and local settings. [Endpoint-managed policy](/docs/en/managed-settings#delivery-mechanisms) loads in all cases. `resolveSettings()` includes server-managed settings only when you pass `options.serverManagedSettings` |
424| `options.managedSettings` | `Settings` | `undefined` | Policy-tier settings supplied by the embedding host. Follows the same rules as [`managedSettings` in `Options`](#options), except that `resolveSettings()` doesn't execute a configured [`policyHelper`](/docs/en/settings-reference#policyhelper), so the snapshot can include settings that a live session drops |
425| `options.serverManagedSettings` | `Settings` | `undefined` | Server-managed settings payload from `/api/claude_code/settings`. Non-restrictive keys pass through unfiltered |
420| Parameter | Type | Default | Description |
421| :- | :- | :- | :- |
422| `options.cwd` | `string` | `process.cwd()` | Directory to resolve project and local settings relative to |
423| `options.settingSources` | [`SettingSource`](#settingsource)`[]` | All sources | Which filesystem sources to load. Pass `[]` to skip user, project, and local settings. [Endpoint-managed policy](/docs/en/managed-settings#delivery-mechanisms) loads in all cases. `resolveSettings()` includes server-managed settings only when you pass `options.serverManagedSettings` |
424| `options.managedSettings` | `Settings` | `undefined` | Policy-tier settings supplied by the embedding host. Follows the same rules as [`managedSettings` in `Options`](#options), except that `resolveSettings()` doesn't execute a configured [`policyHelper`](/docs/en/settings-reference#policyhelper), so the snapshot can include settings that a live session drops |
425| `options.serverManagedSettings` | `Settings` | `undefined` | Server-managed settings payload from `/api/claude_code/settings`. Non-restrictive keys pass through unfiltered |
426426 
427427#### Return type: `ResolvedSettings`
428428 
429429`resolveSettings()` returns an object describing the merged settings and the source that contributed each key.
430430 
431| Property | Type | Description |
432| :----------- | :-------------------------------------------------- | :--------------------------------------------------------------------- |
433| `effective` | `Settings` | Merged settings after applying all enabled sources in precedence order |
434| `provenance` | `Partial<Record<keyof Settings, ProvenanceEntry>>` | For each top-level key in `effective`, which source supplied the value |
435| `sources` | `Array<{ source, settings, path?, policyOrigin? }>` | Per-source raw settings, ordered from lowest to highest precedence |
431| Property | Type | Description |
432| :- | :- | :- |
433| `effective` | `Settings` | Merged settings after applying all enabled sources in precedence order |
434| `provenance` | `Partial<Record<keyof Settings, ProvenanceEntry>>` | For each top-level key in `effective`, which source supplied the value |
435| `sources` | `Array<{ source, settings, path?, policyOrigin? }>` | Per-source raw settings, ordered from lowest to highest precedence |
436436 
437437#### Example
438438 
from line 456
456456 
457457Configuration object for the `query()` function.
458458 
459| Property | Type | Default | Description |
460| :-------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
461| `abortController` | `AbortController` | `new AbortController()` | Controller for cancelling operations |
462| `additionalDirectories` | `string[]` | `[]` | Additional directories Claude can access. The SDK passes each entry to Claude Code as `--add-dir`, so with the `project` setting source Claude Code also [loads the directory's skills, commands, and subagents](/docs/en/permissions#additional-directories-grant-file-access-not-configuration) |
463| `agent` | `string` | `undefined` | Agent name for the main thread. The agent must be defined in the `agents` option or in settings |
464| `agents` | `Record<string, [`AgentDefinition`](#agentdefinition)>` | `undefined` | Programmatically define subagents |
465| `agentProgressSummaries` | `boolean` | `false` | When `true`, generate one-line progress summaries for subagents and forward them on [`task_progress`](#sdktaskprogressmessage) events via the `summary` field. Applies to foreground and background subagents |
466| `allowDangerouslySkipPermissions` | `boolean` | `false` | Enable bypassing permissions. Required when using `permissionMode: 'bypassPermissions'`, at startup or later through `setPermissionMode()`. See [plan mode](/docs/en/agent-sdk/permissions#plan-mode-plan) for how it interacts with `permissionMode: 'plan'` |
467| `allowedTools` | `string[]` | `[]` | Tools to auto-approve without prompting. This does not restrict Claude to only these tools. If you name one of the [task-tracking tools](/docs/en/agent-sdk/todo-tracking#model-availability) here, Claude Code also opts the session in. Other unlisted tools fall through to `permissionMode` and `canUseTool`. Use `disallowedTools` to block tools. See [Permissions](/docs/en/agent-sdk/permissions#allow-and-deny-rules) |
468| `betas` | [`SdkBeta`](#sdkbeta)`[]` | `[]` | Enable beta features |
469| `canUseTool` | [`CanUseTool`](#canusetool) | `undefined` | Custom permission function, invoked only when the [permission flow](/docs/en/agent-sdk/permissions#how-permissions-are-evaluated) falls through to a prompt. Not invoked for calls auto-approved by `allowedTools`, allow rules, or `permissionMode`. An allow rule doesn't pre-approve the [actions no mode auto-approves](/docs/en/permission-modes#actions-no-mode-auto-approves). See [`CanUseTool`](#canusetool) for details |
470| `continue` | `boolean` | `false` | Continue the most recent conversation |
471| `cwd` | `string` | `process.cwd()` | Current working directory |
472| `debug` | `boolean` | `false` | Enable debug mode for the Claude Code process |
473| `debugFile` | `string` | `undefined` | Write debug logs to a specific file path. Implicitly enables debug mode |
474| `disallowedTools` | `string[]` | `[]` | Tools to deny. A bare name such as `"Bash"` removes the tool from Claude's context. A scoped rule such as `"Bash(rm *)"` leaves the tool available and denies matching calls in every permission mode, including `bypassPermissions`, for the command [as written](/docs/en/permissions#bash-rule-limits). See [Permissions](/docs/en/agent-sdk/permissions#allow-and-deny-rules) |
475| `effort` | `'low' \| 'medium' \| 'high' \| 'xhigh' \| 'max'` | `undefined` | Controls how much effort Claude puts into its response. Works with adaptive thinking to guide thinking depth. See [adjust the effort level](/docs/en/model-config#adjust-effort-level) |
476| `enableFileCheckpointing` | `boolean` | `false` | Enable file change tracking for rewinding. See [File checkpointing](/docs/en/agent-sdk/file-checkpointing) |
477| `env` | `Record<string, string \| undefined>` | `process.env` | Environment variables. When set, this replaces the subprocess environment instead of merging with `process.env`, so pass `{ ...process.env, YOUR_VAR: 'value' }` to keep inherited variables like `PATH`. See [Handle slow or stalled API responses](#handle-slow-or-stalled-api-responses) for an example of this pattern, and [Environment variables](/docs/en/env-vars) for variables the underlying CLI reads. Set `CLAUDE_AGENT_SDK_CLIENT_APP` to identify your app in the User-Agent header |
478| `executable` | `'bun' \| 'deno' \| 'node'` | Auto-detected | JavaScript runtime to use |
479| `executableArgs` | `string[]` | `[]` | Arguments to pass to the executable |
480| `extraArgs` | `Record<string, string \| null>` | `{}` | Additional arguments |
481| `fallbackModel` | `string` | `undefined` | Model to use if the primary model fails. Accepts a comma-separated list. For the order and the cap, see [Fallback model chains](/docs/en/model-config#fallback-model-chains). For guidance, see [Choose a model](/docs/en/agent-sdk/configuration#choose-a-model) |
482| `forkSession` | `boolean` | `false` | When resuming with `resume`, fork to a new session ID instead of continuing the original session |
483| `forwardSubagentText` | `boolean` | `false` | Forward subagent text and thinking blocks as assistant and user messages with `parent_tool_use_id` set, so consumers can render a nested transcript. Without this option, Claude Code emits subagent `tool_use` and `tool_result` blocks but not text or thinking. Messages from subagents at every nesting depth are forwarded on Claude Code v2.1.219 and later; before v2.1.219, only messages from depth-1 subagents appeared. Messages of subagents that a forked skill spawns, and of nested forked skills, require v2.1.275 or later |
484| `hooks` | `Partial<Record<`[`HookEvent`](#hookevent)`, `[`HookCallbackMatcher`](#hookcallbackmatcher)`[]>>` | `{}` | Hook callbacks for events |
485| `includeHookEvents` | `boolean` | `false` | Include hook lifecycle events in the message stream as [`SDKHookStartedMessage`](#sdkhookstartedmessage), [`SDKHookProgressMessage`](#sdkhookprogressmessage), and [`SDKHookResponseMessage`](#sdkhookresponsemessage). Lifecycle events for `SessionStart` and `Setup` hooks are always included and don't need this option. Some hook events, such as `Notification`, `SessionEnd`, `PreCompact`, and `PostCompact`, never produce an `SDKHookStartedMessage`, even with this option. For those events, Claude Code still emits an `SDKHookProgressMessage` while a command hook that runs for more than a second produces output, and emits an `SDKHookResponseMessage` only when a hook [that runs in the background](/docs/en/hooks#run-hooks-in-the-background) finishes |
486| `includePartialMessages` | `boolean` | `false` | Include partial message events |
487| `loadTimeoutMs` | `number` | `60000` | *Alpha.* Timeout in milliseconds for each `sessionStore.load()` and `sessionStore.listSubkeys()` call during resume materialization. If the adapter doesn't settle within this window, the query fails instead of hanging. Ignored when `sessionStore` is not set |
488| `managedSettings` | `Settings` | `undefined` | Policy-tier settings your host process supplies to the spawned session. On machines with admin-deployed managed settings, Claude Code ignores these unless the admin's highest-priority managed source sets `parentSettingsBehavior: 'merge'`, and never merges them while a [`policyHelper`](/docs/en/settings-reference#policyhelper) supplies managed settings. Merged values pass through a restrictive-only filter; [Restrict parent settings](/docs/en/claude-apps-gateway#restrict-parent-settings) covers what the filter admits and the `allowManaged*Only` locks. A host that sets [`CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`](/docs/en/env-vars) has three keys read straight from this payload instead: its [model configuration](/docs/en/model-config#restrict-model-selection) on Claude Code v2.1.222 or later, [`modelPricing`](/docs/en/settings-reference#modelpricing) when no managed source sets it on v2.1.246 or later, and its `ENABLE_TOOL_SEARCH` env entry on v2.1.247 or later |
489| `maxBudgetUsd` | `number` | `undefined` | Stop the query when the client-side cost estimate reaches this USD value. Counts only the call's own spend; totals restored from a resumed session don't count. For accuracy caveats and reset behavior, see [Track cost and usage](/docs/en/agent-sdk/cost-tracking) |
490| `maxThinkingTokens` | `number` | `undefined` | *Deprecated:* Use `thinking` instead. Maximum tokens for thinking process |
491| `maxTurns` | `number` | `undefined` | Maximum agentic turns (tool-use round trips) |
492| `mcpServers` | `Record<string, [`McpServerConfig`](#mcpserverconfig)>` | `{}` | MCP server configurations |
493| `model` | `string` | Default from CLI | Claude model alias or full model name. See [accepted values and provider-specific IDs](/docs/en/model-config#available-models) |
494| `onElicitation` | `(request: ElicitationRequest, options: { signal: AbortSignal }) => Promise<ElicitationResult>` | `undefined` | Callback for handling MCP elicitation requests. Called when an MCP server requests user input and no hook handles it first. When not provided, unhandled elicitation requests are declined automatically |
495| `outputFormat` | `{ type: 'json_schema', schema: JSONSchema }` | `undefined` | Define output format for agent results. See [Structured outputs](/docs/en/agent-sdk/structured-outputs) for details |
496| `outputStyle` | `string` | `undefined` | Not an `Options` field. Set `outputStyle` in the inline [`settings`](/docs/en/settings) object or a settings file instead. See [Activate an output style](/docs/en/agent-sdk/modifying-system-prompts#activate-an-output-style) |
497| `pathToClaudeCodeExecutable` | `string` | Auto-resolved from bundled native binary | Path to Claude Code executable. Only needed if optional dependencies were skipped during install or your platform isn't in the supported set |
498| `permissionMode` | [`PermissionMode`](#permissionmode) | `'default'` | Permission mode for the session |
499| `permissionPromptToolName` | `string` | `undefined` | MCP tool name for permission prompts |
500| `permissionPrompts` | `'host' \| 'none'` | `'host'` | Who answers permission prompts: `'host'` routes them to your [`canUseTool`](#canusetool) callback or the `permissionPromptToolName` tool, and `'none'` [denies the calls that would have prompted](/docs/en/agent-sdk/permissions#how-permissions-are-evaluated). Requires Claude Code v2.1.259 or later |
501| `persistSession` | `boolean` | `true` | When `false`, disables session persistence to disk. Sessions cannot be resumed later |
502| `planModeInstructions` | `string` | `undefined` | Custom workflow instructions for plan mode. When `permissionMode` is `'plan'`, this string replaces the default plan-mode workflow body. The CLI still wraps it with the read-only enforcement preamble and the ExitPlanMode protocol footer |
503| `plugins` | [`SdkPluginConfig`](#sdkpluginconfig)`[]` | `[]` | Load custom plugins from local paths. See [Plugins](/docs/en/agent-sdk/plugins) for details |
504| `projectConfigRoot` | `string` | `undefined` | Absolute path of the trusted checkout that `cwd` is a worktree of. Claude Code reads project settings, `.mcp.json`, and the project's `.claude/` commands, agents, skills, workflows, routines, and output styles from this directory instead of `cwd`, and sets `CLAUDE_PROJECT_DIR` to it. Hooks, helper scripts such as `apiKeyHelper`, and stdio MCP servers start with this directory as their working directory. `CLAUDE.md` files and `.claude/rules/` still load from `cwd`. Requires Claude Code v2.1.275 or later |
505| `promptSuggestions` | `boolean` | `false` | Enable prompt suggestions. After a turn, Claude Code emits a `prompt_suggestion` message carrying a predicted next user prompt. Claude Code generates no suggestion for some turns, such as while your account is close to or at its usage limit. See [When Claude Code skips suggestions](/docs/en/interactive-mode#when-claude-code-skips-suggestions) |
506| `resume` | `string` | `undefined` | Session ID to resume |
507| `resumeDropsTurn` | `string` | `undefined` | With `resumeSessionAt`: the prompt UUID of the turn the truncating resume intends to discard. Claude Code refuses the resume when the discarded range contains anything not attributable to that turn, such as absorbed queued messages or task notifications, and names the `--resume-drops-turn` flag in the rejection message. Only the Agent SDK and print-mode resumes read the pair. Requires Claude Code v2.1.223 or later |
508| `resumeSessionAt` | `string` | `undefined` | Resume session at a specific message UUID |
509| `sandbox` | [`SandboxSettings`](#sandboxsettings) | `undefined` | Configure sandbox behavior programmatically. See [Sandbox settings](#sandboxsettings) for details |
510| `sessionId` | `string` | Auto-generated | Use a specific UUID for the session instead of auto-generating one |
511| `sessionStore` | [`SessionStore`](/docs/en/agent-sdk/session-storage#the-sessionstore-interface) | `undefined` | Mirror session transcripts to an external backend so another host can resume them. See [Persist sessions to external storage](/docs/en/agent-sdk/session-storage) |
512| `sessionStoreFlush` | `'batched' \| 'eager'` | `'batched'` | *Alpha.* Flush mode for `sessionStore`. Ignored when `sessionStore` is not set |
513| `settings` | `string \| Settings` | `undefined` | Inline [settings](/docs/en/settings) object, a settings file path, or an inline JSON string. Populates the flag-settings layer in the [precedence order](/docs/en/settings#settings-precedence). Change at runtime with [`applyFlagSettings()`](#applyflagsettings) |
514| `settingSources` | [`SettingSource`](#settingsource)`[]` | CLI defaults (all sources) | Control which filesystem settings to load. Pass `[]` to disable user, project, and local settings. [Endpoint-managed policy](/docs/en/managed-settings#delivery-mechanisms) loads regardless; server-managed settings are fetched when the session authenticates with an organization credential on an [eligible configuration](/docs/en/server-managed-settings#platform-availability). See [Use Claude Code features](/docs/en/agent-sdk/claude-code-features#what-settingsources-does-not-control) |
515| `skills` | `string[] \| 'all'` | `undefined` | Skills available to the session. Pass `'all'` to enable every discovered skill, or a list of skill names. Pass exact names only. On Agent SDK v0.3.221 or later, the SDK rejects malformed and wildcard-form names with an error before starting the Claude Code process. When set, the SDK adds the Skill tool to `allowedTools` automatically. If you also pass `tools`, include `'Skill'` in that list. See [Skills](/docs/en/agent-sdk/skills) |
516| `spawnClaudeCodeProcess` | `(options: SpawnOptions) => SpawnedProcess` | `undefined` | Custom function to spawn the Claude Code process. Use to run Claude Code in VMs, containers, or remote environments |
517| `stderr` | `(data: string) => void` | `undefined` | Callback for stderr output |
518| `strictMcpConfig` | `boolean` | `false` | Use only the servers passed in `mcpServers` and ignore project `.mcp.json`, user settings, plugin-provided MCP servers, and [claude.ai connectors](/docs/en/mcp#use-mcp-servers-from-claude-ai) |
519| `systemPrompt` | `string \| string[] \| { type: 'custom'; prompt: string \| string[]; snapshot?: boolean } \| { type: 'preset'; preset: 'claude_code'; append?: string; excludeDynamicSections?: boolean; snapshot?: boolean }` | `undefined` (minimal prompt) | System prompt configuration. Pass a string for a custom prompt, or `{ type: 'preset', preset: 'claude_code' }` to use Claude Code's system prompt. Pass an array of strings with the exported `SYSTEM_PROMPT_DYNAMIC_BOUNDARY` constant between the static and per-request parts to [cache the static part of a custom prompt](/docs/en/agent-sdk/modifying-system-prompts#cache-the-static-part-of-a-custom-prompt). When using the preset object form, add `append` to extend it with additional instructions, and set `excludeDynamicSections: true` to move per-session context into the first user message for [better prompt-cache reuse across machines](/docs/en/agent-sdk/modifying-system-prompts#improve-prompt-caching-across-users-and-machines). Set `snapshot: false` to rebuild the prompt on every request instead of [reusing the prompt the session recorded on its first request](/docs/en/agent-sdk/modifying-system-prompts#change-the-prompt-of-an-existing-session). To set `snapshot` on a custom prompt, pass the `{ type: 'custom', prompt }` form. The `{ type: 'custom' }` form and the `snapshot` field require TypeScript Agent SDK v0.3.257 or later |
520| `taskBudget` | `{ total: number }` | `undefined` | *Alpha.* API-side task budget in tokens. When set, the model is told its remaining token budget so it can pace tool use and wrap up before the limit |
521| `thinking` | [`ThinkingConfig`](#thinkingconfig) | `{ type: 'adaptive' }` for supported models | Controls Claude's thinking/reasoning behavior. See [`ThinkingConfig`](#thinkingconfig) for options |
522| `title` | `string` | `undefined` | Display title for the session. When resuming via `resume` or `continue`, the resumed session's persisted title takes precedence; use [`renameSession()`](#renamesession) to retitle an existing session |
523| `toolAliases` | `Record<string, string>` | `undefined` | Map built-in tool names to MCP tool names so Claude calls your MCP implementation in place of the built-in. For example, `{ Bash: 'mcp__workspace__bash' }` |
524| `toolConfig` | [`ToolConfig`](#toolconfig) | `undefined` | Configuration for built-in tool behavior. See [`ToolConfig`](#toolconfig) for details |
525| `tools` | `string[] \| { type: 'preset'; preset: 'claude_code' }` | `undefined` | Tool configuration. Pass an array of tool names or use the preset to get Claude Code's default tools |
526| `verbatimPrompts` | `boolean` | `false` | Deliver every prompt as written. The SDK sends each user message with `client_composed: true`. See [`client_composed`](#sdkusermessage) for what Claude Code skips on those messages. Use this option when your prompt text includes content the end user didn't type. For per-turn control, leave it off and set `client_composed` on individual streamed messages instead. Requires TypeScript Agent SDK v0.3.280 or later and Claude Code v2.1.248 or later; the Claude Code version bundled with those SDK versions satisfies the Claude Code requirement |
459| Property | Type | Default | Description |
460| :- | :- | :- | :- |
461| `abortController` | `AbortController` | `new AbortController()` | Controller for cancelling operations |
462| `additionalDirectories` | `string[]` | `[]` | Additional directories Claude can access. The SDK passes each entry to Claude Code as `--add-dir`, so with the `project` setting source Claude Code also [loads the directory's skills, commands, and subagents](/docs/en/permissions#additional-directories-grant-file-access-not-configuration) |
463| `agent` | `string` | `undefined` | Agent name for the main thread. The agent must be defined in the `agents` option or in settings |
464| `agents` | `Record<string, [`AgentDefinition`](#agentdefinition)>` | `undefined` | Programmatically define subagents |
465| `agentProgressSummaries` | `boolean` | `false` | When `true`, generate one-line progress summaries for subagents and forward them on [`task_progress`](#sdktaskprogressmessage) events via the `summary` field. Applies to foreground and background subagents |
466| `allowDangerouslySkipPermissions` | `boolean` | `false` | Enable bypassing permissions. Required when using `permissionMode: 'bypassPermissions'`, at startup or later through `setPermissionMode()`. See [plan mode](/docs/en/agent-sdk/permissions#plan-mode-plan) for how it interacts with `permissionMode: 'plan'` |
467| `allowedTools` | `string[]` | `[]` | Tools to auto-approve without prompting. This does not restrict Claude to only these tools. If you name one of the [task-tracking tools](/docs/en/agent-sdk/todo-tracking#model-availability) here, Claude Code also opts the session in. Other unlisted tools fall through to `permissionMode` and `canUseTool`. Use `disallowedTools` to block tools. See [Permissions](/docs/en/agent-sdk/permissions#allow-and-deny-rules) |
468| `betas` | [`SdkBeta`](#sdkbeta)`[]` | `[]` | Enable beta features |
469| `canUseTool` | [`CanUseTool`](#canusetool) | `undefined` | Custom permission function, invoked only when the [permission flow](/docs/en/agent-sdk/permissions#how-permissions-are-evaluated) falls through to a prompt. Not invoked for calls auto-approved by `allowedTools`, allow rules, or `permissionMode`. An allow rule doesn't pre-approve the [actions no mode auto-approves](/docs/en/permission-modes#actions-no-mode-auto-approves). See [`CanUseTool`](#canusetool) for details |
470| `continue` | `boolean` | `false` | Continue the most recent conversation |
471| `cwd` | `string` | `process.cwd()` | Current working directory |
472| `debug` | `boolean` | `false` | Enable debug mode for the Claude Code process |
473| `debugFile` | `string` | `undefined` | Write debug logs to a specific file path. Implicitly enables debug mode |
474| `disallowedTools` | `string[]` | `[]` | Tools to deny. A bare name such as `"Bash"` removes the tool from Claude's context. A scoped rule such as `"Bash(rm *)"` leaves the tool available and denies matching calls in every permission mode, including `bypassPermissions`, for the command [as written](/docs/en/permissions#bash-rule-limits). See [Permissions](/docs/en/agent-sdk/permissions#allow-and-deny-rules) |
475| `effort` | `'low' \| 'medium' \| 'high' \| 'xhigh' \| 'max'` | `undefined` | Controls how much effort Claude puts into its response. Works with adaptive thinking to guide thinking depth. See [adjust the effort level](/docs/en/model-config#adjust-effort-level) |
476| `enableFileCheckpointing` | `boolean` | `false` | Enable file change tracking for rewinding. See [File checkpointing](/docs/en/agent-sdk/file-checkpointing) |
477| `env` | `Record<string, string \| undefined>` | `process.env` | Environment variables. When set, this replaces the subprocess environment instead of merging with `process.env`, so pass `{ ...process.env, YOUR_VAR: 'value' }` to keep inherited variables like `PATH`. See [Handle slow or stalled API responses](#handle-slow-or-stalled-api-responses) for an example of this pattern, and [Environment variables](/docs/en/env-vars) for variables the underlying CLI reads. Set `CLAUDE_AGENT_SDK_CLIENT_APP` to identify your app in the User-Agent header |
478| `executable` | `'bun' \| 'deno' \| 'node'` | Auto-detected | JavaScript runtime to use |
479| `executableArgs` | `string[]` | `[]` | Arguments to pass to the executable |
480| `extraArgs` | `Record<string, string \| null>` | `{}` | Additional arguments |
481| `fallbackModel` | `string` | `undefined` | Model to use if the primary model fails. Accepts a comma-separated list. For the order and the cap, see [Fallback model chains](/docs/en/model-config#fallback-model-chains). For guidance, see [Choose a model](/docs/en/agent-sdk/configuration#choose-a-model) |
482| `forkSession` | `boolean` | `false` | When resuming with `resume`, fork to a new session ID instead of continuing the original session |
483| `forwardSubagentText` | `boolean` | `false` | Forward subagent text and thinking blocks as assistant and user messages with `parent_tool_use_id` set, so consumers can render a nested transcript. Without this option, Claude Code emits subagent `tool_use` and `tool_result` blocks but not text or thinking. Messages from subagents at every nesting depth are forwarded on Claude Code v2.1.219 and later; before v2.1.219, only messages from depth-1 subagents appeared. Messages of subagents that a forked skill spawns, and of nested forked skills, require v2.1.275 or later |
484| `hooks` | `Partial<Record<`[`HookEvent`](#hookevent)`, `[`HookCallbackMatcher`](#hookcallbackmatcher)`[]>>` | `{}` | Hook callbacks for events |
485| `includeHookEvents` | `boolean` | `false` | Include hook lifecycle events in the message stream as [`SDKHookStartedMessage`](#sdkhookstartedmessage), [`SDKHookProgressMessage`](#sdkhookprogressmessage), and [`SDKHookResponseMessage`](#sdkhookresponsemessage). Lifecycle events for `SessionStart` and `Setup` hooks are always included and don't need this option. Some hook events, such as `Notification`, `SessionEnd`, `PreCompact`, and `PostCompact`, never produce an `SDKHookStartedMessage`, even with this option. For those events, Claude Code still emits an `SDKHookProgressMessage` while a command hook that runs for more than a second produces output, and emits an `SDKHookResponseMessage` only when a hook [that runs in the background](/docs/en/hooks#run-hooks-in-the-background) finishes |
486| `includePartialMessages` | `boolean` | `false` | Include partial message events |
487| `loadTimeoutMs` | `number` | `60000` | *Alpha.* Timeout in milliseconds for each `sessionStore.load()` and `sessionStore.listSubkeys()` call during resume materialization. If the adapter doesn't settle within this window, the query fails instead of hanging. Ignored when `sessionStore` is not set |
488| `managedSettings` | `Settings` | `undefined` | Policy-tier settings your host process supplies to the spawned session. On machines with admin-deployed managed settings, Claude Code ignores these unless the admin's highest-priority managed source sets `parentSettingsBehavior: 'merge'`, and never merges them while a [`policyHelper`](/docs/en/settings-reference#policyhelper) supplies managed settings. Merged values pass through a restrictive-only filter; [Restrict parent settings](/docs/en/claude-apps-gateway#restrict-parent-settings) covers what the filter admits and the `allowManaged*Only` locks. A host that sets [`CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST`](/docs/en/env-vars) has three keys read straight from this payload instead: its [model configuration](/docs/en/model-config#restrict-model-selection) on Claude Code v2.1.222 or later, [`modelPricing`](/docs/en/settings-reference#modelpricing) when no managed source sets it on v2.1.246 or later, and its `ENABLE_TOOL_SEARCH` env entry on v2.1.247 or later |
489| `maxBudgetUsd` | `number` | `undefined` | Stop the query when the client-side cost estimate reaches this USD value. Counts only the call's own spend; totals restored from a resumed session don't count. For accuracy caveats and reset behavior, see [Track cost and usage](/docs/en/agent-sdk/cost-tracking) |
490| `maxThinkingTokens` | `number` | `undefined` | *Deprecated:* Use `thinking` instead. Maximum tokens for thinking process |
491| `maxTurns` | `number` | `undefined` | Maximum agentic turns (tool-use round trips) |
492| `mcpServers` | `Record<string, [`McpServerConfig`](#mcpserverconfig)>` | `{}` | MCP server configurations |
493| `model` | `string` | Default from CLI | Claude model alias or full model name. See [accepted values and provider-specific IDs](/docs/en/model-config#available-models) |
494| `onElicitation` | `(request: ElicitationRequest, options: { signal: AbortSignal }) => Promise<ElicitationResult>` | `undefined` | Callback for handling MCP elicitation requests. Called when an MCP server requests user input and no hook handles it first. When not provided, unhandled elicitation requests are declined automatically |
495| `outputFormat` | `{ type: 'json_schema', schema: JSONSchema }` | `undefined` | Define output format for agent results. See [Structured outputs](/docs/en/agent-sdk/structured-outputs) for details |
496| `outputStyle` | `string` | `undefined` | Not an `Options` field. Set `outputStyle` in the inline [`settings`](/docs/en/settings) object or a settings file instead. See [Activate an output style](/docs/en/agent-sdk/modifying-system-prompts#activate-an-output-style) |
497| `pathToClaudeCodeExecutable` | `string` | Auto-resolved from bundled native binary | Path to Claude Code executable. Only needed if optional dependencies were skipped during install or your platform isn't in the supported set |
498| `permissionMode` | [`PermissionMode`](#permissionmode) | `'default'` | Permission mode for the session |
499| `permissionPromptToolName` | `string` | `undefined` | MCP tool name for permission prompts |
500| `permissionPrompts` | `'host' \| 'none'` | `'host'` | Who answers permission prompts: `'host'` routes them to your [`canUseTool`](#canusetool) callback or the `permissionPromptToolName` tool, and `'none'` [denies the calls that would have prompted](/docs/en/agent-sdk/permissions#how-permissions-are-evaluated). Requires Claude Code v2.1.259 or later |
501| `persistSession` | `boolean` | `true` | When `false`, disables session persistence to disk. Sessions cannot be resumed later |
502| `planModeInstructions` | `string` | `undefined` | Custom workflow instructions for plan mode. When `permissionMode` is `'plan'`, this string replaces the default plan-mode workflow body. The CLI still wraps it with the read-only enforcement preamble and the ExitPlanMode protocol footer |
503| `plugins` | [`SdkPluginConfig`](#sdkpluginconfig)`[]` | `[]` | Load custom plugins from local paths. See [Plugins](/docs/en/agent-sdk/plugins) for details |
504| `projectConfigRoot` | `string` | `undefined` | Absolute path of the trusted checkout that `cwd` is a worktree of. Claude Code reads project settings, `.mcp.json`, and the project's `.claude/` commands, agents, skills, workflows, routines, and output styles from this directory instead of `cwd`, and sets `CLAUDE_PROJECT_DIR` to it. Hooks, helper scripts such as `apiKeyHelper`, and stdio MCP servers start with this directory as their working directory. `CLAUDE.md` files and `.claude/rules/` still load from `cwd`. Requires Claude Code v2.1.275 or later |
505| `promptSuggestions` | `boolean` | `false` | Enable prompt suggestions. After a turn, Claude Code emits a `prompt_suggestion` message carrying a predicted next user prompt. Claude Code generates no suggestion for some turns, such as while your account is close to or at its usage limit. See [When Claude Code skips suggestions](/docs/en/interactive-mode#when-claude-code-skips-suggestions) |
506| `resume` | `string` | `undefined` | Session ID to resume |
507| `resumeDropsTurn` | `string` | `undefined` | With `resumeSessionAt`: the prompt UUID of the turn the truncating resume intends to discard. Claude Code refuses the resume when the discarded range contains anything not attributable to that turn, such as absorbed queued messages or task notifications, and names the `--resume-drops-turn` flag in the rejection message. Only the Agent SDK and print-mode resumes read the pair. Requires Claude Code v2.1.223 or later |
508| `resumeSessionAt` | `string` | `undefined` | Resume session at a specific message UUID |
509| `sandbox` | [`SandboxSettings`](#sandboxsettings) | `undefined` | Configure sandbox behavior programmatically. See [Sandbox settings](#sandboxsettings) for details |
510| `sessionId` | `string` | Auto-generated | Use a specific UUID for the session instead of auto-generating one |
511| `sessionStore` | [`SessionStore`](/docs/en/agent-sdk/session-storage#the-sessionstore-interface) | `undefined` | Mirror session transcripts to an external backend so another host can resume them. See [Persist sessions to external storage](/docs/en/agent-sdk/session-storage) |
512| `sessionStoreFlush` | `'batched' \| 'eager'` | `'batched'` | *Alpha.* Flush mode for `sessionStore`. Ignored when `sessionStore` is not set |
513| `settings` | `string \| Settings` | `undefined` | Inline [settings](/docs/en/settings) object, a settings file path, or an inline JSON string. Populates the flag-settings layer in the [precedence order](/docs/en/settings#settings-precedence). Change at runtime with [`applyFlagSettings()`](#applyflagsettings) |
514| `settingSources` | [`SettingSource`](#settingsource)`[]` | CLI defaults (all sources) | Control which filesystem settings to load. Pass `[]` to disable user, project, and local settings. [Endpoint-managed policy](/docs/en/managed-settings#delivery-mechanisms) loads regardless; server-managed settings are fetched when the session authenticates with an organization credential on an [eligible configuration](/docs/en/server-managed-settings#platform-availability). See [Use Claude Code features](/docs/en/agent-sdk/claude-code-features#what-settingsources-does-not-control) |
515| `skills` | `string[] \| 'all'` | `undefined` | Skills available to the session. Pass `'all'` to enable every discovered skill, or a list of skill names. Pass exact names only. On Agent SDK v0.3.221 or later, the SDK rejects malformed and wildcard-form names with an error before starting the Claude Code process. When set, the SDK adds the Skill tool to `allowedTools` automatically. If you also pass `tools`, include `'Skill'` in that list. See [Skills](/docs/en/agent-sdk/skills) |
516| `spawnClaudeCodeProcess` | `(options: SpawnOptions) => SpawnedProcess` | `undefined` | Custom function to spawn the Claude Code process. Use to run Claude Code in VMs, containers, or remote environments |
517| `stderr` | `(data: string) => void` | `undefined` | Callback for stderr output |
518| `strictMcpConfig` | `boolean` | `false` | Use only the servers passed in `mcpServers` and ignore project `.mcp.json`, user settings, plugin-provided MCP servers, and [claude.ai connectors](/docs/en/mcp#use-mcp-servers-from-claude-ai) |
519| `systemPrompt` | `string \| string[] \| { type: 'custom'; prompt: string \| string[]; snapshot?: boolean } \| { type: 'preset'; preset: 'claude_code'; append?: string; excludeDynamicSections?: boolean; snapshot?: boolean }` | `undefined` (minimal prompt) | System prompt configuration. Pass a string for a custom prompt, or `{ type: 'preset', preset: 'claude_code' }` to use Claude Code's system prompt. Pass an array of strings with the exported `SYSTEM_PROMPT_DYNAMIC_BOUNDARY` constant between the static and per-request parts to [cache the static part of a custom prompt](/docs/en/agent-sdk/modifying-system-prompts#cache-the-static-part-of-a-custom-prompt). When using the preset object form, add `append` to extend it with additional instructions, and set `excludeDynamicSections: true` to move per-session context into the first user message for [better prompt-cache reuse across machines](/docs/en/agent-sdk/modifying-system-prompts#improve-prompt-caching-across-users-and-machines). Set `snapshot: false` to rebuild the prompt on every request instead of [reusing the prompt the session recorded on its first request](/docs/en/agent-sdk/modifying-system-prompts#change-the-prompt-of-an-existing-session). To set `snapshot` on a custom prompt, pass the `{ type: 'custom', prompt }` form. The `{ type: 'custom' }` form and the `snapshot` field require TypeScript Agent SDK v0.3.257 or later |
520| `taskBudget` | `{ total: number }` | `undefined` | *Alpha.* API-side task budget in tokens. When set, the model is told its remaining token budget so it can pace tool use and wrap up before the limit |
521| `thinking` | [`ThinkingConfig`](#thinkingconfig) | `{ type: 'adaptive' }` for supported models | Controls Claude's thinking/reasoning behavior. See [`ThinkingConfig`](#thinkingconfig) for options |
522| `title` | `string` | `undefined` | Display title for the session. When resuming via `resume` or `continue`, the resumed session's persisted title takes precedence; use [`renameSession()`](#renamesession) to retitle an existing session |
523| `toolAliases` | `Record<string, string>` | `undefined` | Map built-in tool names to MCP tool names so Claude calls your MCP implementation in place of the built-in. For example, `{ Bash: 'mcp__workspace__bash' }` |
524| `toolConfig` | [`ToolConfig`](#toolconfig) | `undefined` | Configuration for built-in tool behavior. See [`ToolConfig`](#toolconfig) for details |
525| `tools` | `string[] \| { type: 'preset'; preset: 'claude_code' }` | `undefined` | Tool configuration. Pass an array of tool names or use the preset to get Claude Code's default tools |
526| `verbatimPrompts` | `boolean` | `false` | Deliver every prompt as written. The SDK sends each user message with `client_composed: true`. See [`client_composed`](#sdkusermessage) for what Claude Code skips on those messages. Use this option when your prompt text includes content the end user didn't type. For per-turn control, leave it off and set `client_composed` on individual streamed messages instead. Requires TypeScript Agent SDK v0.3.280 or later and Claude Code v2.1.248 or later; the Claude Code version bundled with those SDK versions satisfies the Claude Code requirement |
527527 
528528#### Handle slow or stalled API responses
529529 
from line 608
608608 
609609#### Methods
610610 
611| Method | Description |
612| :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
613| `interrupt()` | Interrupts the query. Only available in streaming input mode. When the CLI advertises the `interrupt_receipt_v1` capability in [`SDKSystemMessage.capabilities`](#sdksystemmessage), resolves with an [`SDKControlInterruptResponse`](#sdkcontrolinterruptresponse) listing the messages that were pending when the interrupt arrived. Resolves `undefined` on CLIs before v2.1.205 |
614| `rewindFiles(userMessageId, options?)` | Restores files to their state at the specified user message. Pass `{ dryRun: true }` to preview changes. Requires `enableFileCheckpointing: true`. See [File checkpointing](/docs/en/agent-sdk/file-checkpointing) |
615| `setPermissionMode()` | Changes the permission mode (only available in streaming input mode) |
616| `setModel()` | Changes the model (only available in streaming input mode). Passing `undefined` or the string `"default"` resets to [Claude Code's default model](/docs/en/model-config) |
617| `setMaxThinkingTokens()` | *Deprecated:* Use the `thinking` option instead. Changes the maximum thinking tokens. Passing `null` resets thinking to the session default: a mid-session override is cleared, and thinking stays off for sessions that have it disabled |
618| `applyFlagSettings(settings)` | Merges settings into the session's flag settings layer at runtime (only available in streaming input mode). See [`applyFlagSettings()`](#applyflagsettings) |
619| `updateSettings(source, settings)` | Writes one allowlisted key to the project's local settings file or your user settings file, so the value persists for later sessions. See [`updateSettings()`](#updatesettings). Requires TypeScript SDK v0.3.257 or later, which bundles Claude Code v2.1.257 |
620| `initializationResult()` | Returns the full initialization result including supported commands, models, account info, and output style configuration |
621| `reinitialize()` | Re-sends the `initialize` control request to the running CLI and returns a fresh result instead of the cached first-connect result. Use it after a transport gap, such as reattaching to a session after a disconnect, so pending permission requests reach your `canUseTool` callback again. Make the callback idempotent per request ID, because a request whose response was lost is dispatched again. Requires Claude Code v2.1.195 or later |
622| `supportedCommands()` | Returns available commands. From Agent SDK v0.3.216 the list reflects mid-session command changes; see [`SDKCommandsChangedMessage`](#sdkcommandschangedmessage) |
623| `supportedModels()` | Returns available models with display info |
624| `supportedAgents()` | Returns available subagents as [`AgentInfo`](#agentinfo)`[]` |
625| `mcpServerStatus()` | Returns the status of connected MCP servers as [`McpServerStatus`](#mcpserverstatus)`[]` |
626| `getContextUsage(opts?)` | Returns an [`SDKControlGetContextUsageResponse`](#sdkcontrolgetcontextusageresponse) breaking down the session's context window usage by category, skill, and tool. With the default `detail`, it is the same data `/context` shows in an interactive session. The [`detail` option](#sdkcontrolgetcontextusageresponse) requires Agent SDK v0.3.257 or later |
627| `readFile(path, options?)` | Reads a file from the session's filesystem. Claude Code resolves the path against `cwd`; [What `readFile()` can read](#what-readfile-can-read) lists the files it serves. Pass `{ maxBytes }` to change the read cap (default 1 MB, ceiling 10 MB) and `{ encoding: 'base64' }` for binary files such as images. Resolves with an [`SDKControlReadFileResponse`](#sdkcontrolreadfileresponse), or `null` on permission denial, a missing file, or a transport error. Requires TypeScript SDK v0.2.121 or later |
628| `reloadPlugins(options?)` | Reloads plugins from disk, so plugins you install or edit mid-session reach the running session. Resolves with an [`SDKControlReloadPluginsResponse`](#sdkcontrolreloadpluginsresponse) listing the session's commands, subagents, plugins, and MCP server status. Requires Agent SDK v0.2.85 or later. The [`holdOnCacheImpact` option](#sdkcontrolreloadpluginsresponse) requires Agent SDK v0.3.268 or later |
629| `reloadSkills()` | Reloads skills from disk, so skills you add or edit mid-session become available to the running session. Resolves with an [`SDKControlReloadSkillsResponse`](#sdkcontrolreloadskillsresponse) listing the skills available after the reload. Requires Agent SDK v0.3.163 or later |
630| `reloadOutputStyles()` | Re-reads [output styles](/docs/en/output-styles) from disk, so a style file you add or edit mid-session becomes available to the running session. Resolves with an [`SDKControlReloadOutputStylesResponse`](#sdkcontrolreloadoutputstylesresponse) listing the style names available after the reload. Requires Agent SDK v0.3.261 or later |
631| `accountInfo()` | Returns account information |
632| `reconnectMcpServer(serverName)` | Reconnect an MCP server by name. If the name also matches an entry in a settings file such as `.mcp.json` or `~/.claude.json`, Claude Code reconnects the server you configured through [`mcpServers`](#options) or `setMcpServers()`, not the settings-file entry. That resolution order requires Claude Code v2.1.257 or later |
633| `toggleMcpServer(serverName, enabled)` | Enable or disable an MCP server by name, with the same name resolution as `reconnectMcpServer()`. Disabling disconnects the server |
634| `setMcpServers(servers)` | Dynamically replace the set of MCP servers for this session. Resolves with an [`McpSetServersResult`](#mcpsetserversresult) naming which servers were added and removed, and any errors |
635| `readMcpResource(serverName, uri)` | *Alpha.* Reads one MCP Apps `ui://` resource from a connected MCP server so your application can render a tool's widget. Resolves with an [`SDKControlMcpReadResourceResponse`](#sdkcontrolmcpreadresourceresponse). Requires TypeScript Agent SDK v0.3.280 or later |
636| `streamInput(stream)` | Stream input messages to the query for multi-turn conversations |
637| `stopTask(taskId)` | Stop a running background task by ID |
638| `close()` | Close the query and terminate the underlying process. Forcefully ends the query and cleans up all resources |
611| Method | Description |
612| :- | :- |
613| `interrupt()` | Interrupts the query. Only available in streaming input mode. When the CLI advertises the `interrupt_receipt_v1` capability in [`SDKSystemMessage.capabilities`](#sdksystemmessage), resolves with an [`SDKControlInterruptResponse`](#sdkcontrolinterruptresponse) listing the messages that were pending when the interrupt arrived. Resolves `undefined` on CLIs before v2.1.205 |
614| `rewindFiles(userMessageId, options?)` | Restores files to their state at the specified user message. Pass `{ dryRun: true }` to preview changes. Requires `enableFileCheckpointing: true`. See [File checkpointing](/docs/en/agent-sdk/file-checkpointing) |
615| `setPermissionMode()` | Changes the permission mode (only available in streaming input mode) |
616| `setModel()` | Changes the model (only available in streaming input mode). Passing `undefined` or the string `"default"` resets to [Claude Code's default model](/docs/en/model-config) |
617| `setMaxThinkingTokens()` | *Deprecated:* Use the `thinking` option instead. Changes the maximum thinking tokens. Passing `null` resets thinking to the session default: a mid-session override is cleared, and thinking stays off for sessions that have it disabled |
618| `applyFlagSettings(settings)` | Merges settings into the session's flag settings layer at runtime (only available in streaming input mode). See [`applyFlagSettings()`](#applyflagsettings) |
619| `updateSettings(source, settings)` | Writes one allowlisted key to the project's local settings file or your user settings file, so the value persists for later sessions. See [`updateSettings()`](#updatesettings). Requires TypeScript SDK v0.3.257 or later, which bundles Claude Code v2.1.257 |
620| `initializationResult()` | Returns the full initialization result including supported commands, models, account info, and output style configuration |
621| `reinitialize()` | Re-sends the `initialize` control request to the running CLI and returns a fresh result instead of the cached first-connect result. Use it after a transport gap, such as reattaching to a session after a disconnect, so pending permission requests reach your `canUseTool` callback again. Make the callback idempotent per request ID, because a request whose response was lost is dispatched again. Requires Claude Code v2.1.195 or later |
622| `supportedCommands()` | Returns available commands. From Agent SDK v0.3.216 the list reflects mid-session command changes; see [`SDKCommandsChangedMessage`](#sdkcommandschangedmessage) |
623| `supportedModels()` | Returns available models with display info |
624| `supportedAgents()` | Returns available subagents as [`AgentInfo`](#agentinfo)`[]` |
625| `mcpServerStatus()` | Returns the status of connected MCP servers as [`McpServerStatus`](#mcpserverstatus)`[]` |
626| `getContextUsage(opts?)` | Returns an [`SDKControlGetContextUsageResponse`](#sdkcontrolgetcontextusageresponse) breaking down the session's context window usage by category, skill, and tool. With the default `detail`, it is the same data `/context` shows in an interactive session. The [`detail` option](#sdkcontrolgetcontextusageresponse) requires Agent SDK v0.3.257 or later |
627| `readFile(path, options?)` | Reads a file from the session's filesystem. Claude Code resolves the path against `cwd`; [What `readFile()` can read](#what-readfile-can-read) lists the files it serves. Pass `{ maxBytes }` to change the read cap (default 1 MB, ceiling 10 MB) and `{ encoding: 'base64' }` for binary files such as images. Resolves with an [`SDKControlReadFileResponse`](#sdkcontrolreadfileresponse), or `null` on permission denial, a missing file, or a transport error. Requires TypeScript SDK v0.2.121 or later |
628| `reloadPlugins(options?)` | Reloads plugins from disk, so plugins you install or edit mid-session reach the running session. Resolves with an [`SDKControlReloadPluginsResponse`](#sdkcontrolreloadpluginsresponse) listing the session's commands, subagents, plugins, and MCP server status. Requires Agent SDK v0.2.85 or later. The [`holdOnCacheImpact` option](#sdkcontrolreloadpluginsresponse) requires Agent SDK v0.3.268 or later |
629| `reloadSkills()` | Reloads skills from disk, so skills you add or edit mid-session become available to the running session. Resolves with an [`SDKControlReloadSkillsResponse`](#sdkcontrolreloadskillsresponse) listing the skills available after the reload. Requires Agent SDK v0.3.163 or later |
630| `reloadOutputStyles()` | Re-reads [output styles](/docs/en/output-styles) from disk, so a style file you add or edit mid-session becomes available to the running session. Resolves with an [`SDKControlReloadOutputStylesResponse`](#sdkcontrolreloadoutputstylesresponse) listing the style names available after the reload. Requires Agent SDK v0.3.261 or later |
631| `accountInfo()` | Returns account information |
632| `reconnectMcpServer(serverName)` | Reconnect an MCP server by name. If the name also matches an entry in a settings file such as `.mcp.json` or `~/.claude.json`, Claude Code reconnects the server you configured through [`mcpServers`](#options) or `setMcpServers()`, not the settings-file entry. That resolution order requires Claude Code v2.1.257 or later |
633| `toggleMcpServer(serverName, enabled)` | Enable or disable an MCP server by name, with the same name resolution as `reconnectMcpServer()`. Disabling disconnects the server |
634| `setMcpServers(servers)` | Dynamically replace the set of MCP servers for this session. Resolves with an [`McpSetServersResult`](#mcpsetserversresult) naming which servers were added and removed, and any errors |
635| `readMcpResource(serverName, uri)` | *Alpha.* Reads one MCP Apps `ui://` resource from a connected MCP server so your application can render a tool's widget. Resolves with an [`SDKControlMcpReadResourceResponse`](#sdkcontrolmcpreadresourceresponse). Requires TypeScript Agent SDK v0.3.280 or later |
636| `streamInput(stream)` | Stream input messages to the query for multi-turn conversations |
637| `stopTask(taskId)` | Stop a running background task by ID |
638| `close()` | Close the query and terminate the underlying process. Forcefully ends the query and cleans up all resources |
639639 
640640#### `applyFlagSettings()`
641641 
from line 703
703703 
704704#### Methods
705705 
706| Method | Description |
707| :-------------- | :------------------------------------------------------------------------------------------------------------------------ |
706| Method | Description |
707| :- | :- |
708708| `query(prompt)` | Send a prompt to the pre-warmed subprocess and return a [`Query`](#query-object). Can only be called once per `WarmQuery` |
709| `close()` | Close the subprocess without sending a prompt. Use this to discard a warm query that is no longer needed |
709| `close()` | Close the subprocess without sending a prompt. Use this to discard a warm query that is no longer needed |
710710 
711711`WarmQuery` implements `AsyncDisposable`, so it can be used with `await using` for automatic cleanup.
712712 
from line 728
728728 
729729#### Members
730730 
731| Member | Description |
732| :--------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
733| `claim({ prompt, options })` | Bind the spare to a session in `options.cwd` and send its first message. Returns a [`Query`](#query-object) synchronously, as `query()` does. Can only be called once |
734| `claimed` | Resolves with the session's working directory and ID once Claude Code accepts the claim. Rejects when Claude Code refuses the claim, when the process exited or was closed first, and, with a message that starts with `option_not_applied`, when the session is running without the `model` or `maxThinkingTokens` you asked for |
735| `exited` | Settles when the process exits, claimed or not. Replace a spare that exits before you claim it |
736| `close()` | Terminate the process. Before a claim this discards the spare and rejects `claimed` |
731| Member | Description |
732| :- | :- |
733| `claim({ prompt, options })` | Bind the spare to a session in `options.cwd` and send its first message. Returns a [`Query`](#query-object) synchronously, as `query()` does. Can only be called once |
734| `claimed` | Resolves with the session's working directory and ID once Claude Code accepts the claim. Rejects when Claude Code refuses the claim, when the process exited or was closed first, and, with a message that starts with `option_not_applied`, when the session is running without the `model` or `maxThinkingTokens` you asked for |
735| `exited` | Settles when the process exits, claimed or not. Replace a spare that exits before you claim it |
736| `close()` | Terminate the process. Before a claim this discards the spare and rejects `claimed` |
737737 
738738`options.cwd` is required. A claim can also set `additionalDirectories`, `model`, `permissionMode`, `maxThinkingTokens`, a flag-settings overlay in `settings`, `appendSystemPrompt`, `title`, `agents`, and per-session tokens in `env`.
739739 
from line 1052
10521052};
10531053```
10541054 
1055| Field | Required | Description |
1056| :------------------------------------ | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1057| `description` | Yes | Natural language description of when to use this agent |
1058| `tools` | No | Array of allowed tool names. If omitted, inherits every [tool available to subagents](/docs/en/sub-agents#available-tools). To preload Skills into the agent's context, use the `skills` field rather than listing `'Skill'` here |
1059| `disallowedTools` | No | Array of tool names to explicitly disallow for this agent. MCP server-level patterns are also accepted: `mcp__server` or `mcp__server__*` removes every tool from that server, and `mcp__*` removes every MCP tool from any server |
1060| `prompt` | Yes | The agent's system prompt |
1061| `model` | No | Model override for this agent. Accepts an alias such as `'fable'`, `'opus'`, `'sonnet'`, `'haiku'`, `'inherit'`, or a full model ID. `'inherit'` uses the main model. When you omit it, Claude Code picks the model in the [subagent model order](/docs/en/sub-agents#choose-a-model) |
1062| `mcpServers` | No | MCP server specifications for this agent |
1063| `skills` | No | Array of skill names to preload into the agent context |
1064| `initialPrompt` | No | Auto-submitted as the first user turn when this agent runs as the main thread agent |
1065| `maxTurns` | No | Maximum number of agentic turns (API round-trips) before stopping |
1066| `background` | No | Run this agent as a non-blocking background task when invoked |
1067| `omitClaudeMd` | No | Run this agent without the user, project, and local CLAUDE.md files when it runs as a subagent; managed policy files still load. Use it for agents that take everything they need from the Agent tool prompt. Ignored when this agent runs as the main thread agent. Requires TypeScript Agent SDK v0.3.271 or later |
1068| `memory` | No | Memory source for this agent: `'user'`, `'project'`, or `'local'` |
1069| `effort` | No | Reasoning effort level for this agent. Accepts a named level or an integer |
1070| `permissionMode` | No | Permission mode for tool execution within this agent. The [subagent inheritance rules](/docs/en/agent-sdk/permissions#available-modes) decide when it applies. See [`PermissionMode`](#permissionmode) |
1071| `criticalSystemReminder_EXPERIMENTAL` | No | Experimental: Critical reminder added to the system prompt |
1055| Field | Required | Description |
1056| :- | :- | :- |
1057| `description` | Yes | Natural language description of when to use this agent |
1058| `tools` | No | Array of allowed tool names. If omitted, inherits every [tool available to subagents](/docs/en/sub-agents#available-tools). To preload Skills into the agent's context, use the `skills` field rather than listing `'Skill'` here |
1059| `disallowedTools` | No | Array of tool names to explicitly disallow for this agent. MCP server-level patterns are also accepted: `mcp__server` or `mcp__server__*` removes every tool from that server, and `mcp__*` removes every MCP tool from any server |
1060| `prompt` | Yes | The agent's system prompt |
1061| `model` | No | Model override for this agent. Accepts an alias such as `'fable'`, `'opus'`, `'sonnet'`, `'haiku'`, `'inherit'`, or a full model ID. `'inherit'` uses the main model. When you omit it, Claude Code picks the model in the [subagent model order](/docs/en/sub-agents#choose-a-model) |
1062| `mcpServers` | No | MCP server specifications for this agent |
1063| `skills` | No | Array of skill names to preload into the agent context |
1064| `initialPrompt` | No | Auto-submitted as the first user turn when this agent runs as the main thread agent |
1065| `maxTurns` | No | Maximum number of agentic turns (API round-trips) before stopping |
1066| `background` | No | Run this agent as a non-blocking background task when invoked |
1067| `omitClaudeMd` | No | Run this agent without the user, project, and local CLAUDE.md files when it runs as a subagent; managed policy files still load. Use it for agents that take everything they need from the Agent tool prompt. Ignored when this agent runs as the main thread agent. Requires TypeScript Agent SDK v0.3.271 or later |
1068| `memory` | No | Memory source for this agent: `'user'`, `'project'`, or `'local'` |
1069| `effort` | No | Reasoning effort level for this agent. Accepts a named level or an integer |
1070| `permissionMode` | No | Permission mode for tool execution within this agent. The [subagent inheritance rules](/docs/en/agent-sdk/permissions#available-modes) decide when it applies. See [`PermissionMode`](#permissionmode) |
1071| `criticalSystemReminder_EXPERIMENTAL` | No | Experimental: Critical reminder added to the system prompt |
10721072 
10731073### `AgentMcpServerSpec`
10741074 
from line 1088
10881088type SettingSource = "user" | "project" | "local";
10891089```
10901090 
1091| Value | Description | Location |
1092| :---------- | :------------------------------------------------------------------------ | :---------------------------- |
1093| `'user'` | Global user settings | `~/.claude/settings.json` |
1094| `'project'` | Shared project settings (version controlled) | `.claude/settings.json` |
1095| `'local'` | Local project settings, gitignored when Claude Code saves a setting to it | `.claude/settings.local.json` |
1091| Value | Description | Location |
1092| :- | :- | :- |
1093| `'user'` | Global user settings | `~/.claude/settings.json` |
1094| `'project'` | Shared project settings (version controlled) | `.claude/settings.json` |
1095| `'local'` | Local project settings, gitignored when Claude Code saves a setting to it | `.claude/settings.local.json` |
10961096 
10971097#### Default behavior
10981098 
from line 1177
11771177) => Promise<PermissionResult | null>;
11781178```
11791179 
1180| Option | Type | Description |
1181| :------------------------ | :------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1182| `signal` | `AbortSignal` | Signaled if the operation should be aborted |
1183| `suggestions` | [`PermissionUpdate`](#permissionupdate)`[]` | Suggested permission updates so the user is not prompted again for this tool. Bash prompts include a suggestion with the `localSettings` [destination](#permissionupdatedestination), so returning it in `updatedPermissions` writes the rule to `.claude/settings.local.json` and persists across sessions. |
1184| `blockedPath` | `string` | The file path that triggered the permission request, if applicable |
1185| `mcpServer` | `{ name: string; source: string }` | For an `mcp__*` tool, the MCP server that serves it and where that server's definition came from, with the fields of [`McpServerProvenance`](#mcpserverprovenance). Absent for other tools. Requires Agent SDK v0.3.274 or later |
1186| `decisionReason` | `string` | Explains why this permission request was triggered |
1187| `defaultToNo` | `boolean` | When `true`, a single stray keystroke must not approve this request: open your prompt on its decline option, don't pre-select approve, and offer no one-key approve shortcut. Requires Agent SDK v0.3.268 or later |
1188| `suppressAlwaysAllowRule` | `boolean` | When `true`, don't offer a persistent always-allow choice for this request, because the rule it would write grants more than the request's own action. Requires Agent SDK v0.3.268 or later |
1189| `toolUseID` | `string` | Unique identifier for this specific tool call within the assistant message |
1190| `agentID` | `string` | If running within a sub-agent, the sub-agent's ID |
1191| `requestId` | `string` | The `control_request` envelope's `request_id`. A `control_response` your application sends outside the SDK, such as a signed HTTP POST, must echo this value so the Claude Code process can match the reply to the request |
1180| Option | Type | Description |
1181| :- | :- | :- |
1182| `signal` | `AbortSignal` | Signaled if the operation should be aborted |
1183| `suggestions` | [`PermissionUpdate`](#permissionupdate)`[]` | Suggested permission updates so the user is not prompted again for this tool. Bash prompts include a suggestion with the `localSettings` [destination](#permissionupdatedestination), so returning it in `updatedPermissions` writes the rule to `.claude/settings.local.json` and persists across sessions. |
1184| `blockedPath` | `string` | The file path that triggered the permission request, if applicable |
1185| `mcpServer` | `{ name: string; source: string }` | For an `mcp__*` tool, the MCP server that serves it and where that server's definition came from, with the fields of [`McpServerProvenance`](#mcpserverprovenance). Absent for other tools. Requires Agent SDK v0.3.274 or later |
1186| `decisionReason` | `string` | Explains why this permission request was triggered |
1187| `defaultToNo` | `boolean` | When `true`, a single stray keystroke must not approve this request: open your prompt on its decline option, don't pre-select approve, and offer no one-key approve shortcut. Requires Agent SDK v0.3.268 or later |
1188| `suppressAlwaysAllowRule` | `boolean` | When `true`, don't offer a persistent always-allow choice for this request, because the rule it would write grants more than the request's own action. Requires Agent SDK v0.3.268 or later |
1189| `toolUseID` | `string` | Unique identifier for this specific tool call within the assistant message |
1190| `agentID` | `string` | If running within a sub-agent, the sub-agent's ID |
1191| `requestId` | `string` | The `control_request` envelope's `request_id`. A `control_response` your application sends outside the SDK, such as a signed HTTP POST, must echo this value so the Claude Code process can match the reply to the request |
11921192 
11931193The callback normally resolves the request by returning a [`PermissionResult`](#permissionresult), which the SDK writes back over its transport as the `control_response`. Return `null` only when your application has already sent the `control_response` for this request over its own channel, echoing `requestId`; the SDK then skips writing the response to its transport. Returning `null` in any other case leaves the tool call blocked indefinitely, because no `control_response` is ever sent and permission prompts don't time out.
11941194 
from line 1226
12261226};
12271227```
12281228 
1229| Field | Type | Description |
1230| :------------------------------ | :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1229| Field | Type | Description |
1230| :- | :- | :- |
12311231| `askUserQuestion.previewFormat` | `'markdown' \| 'html'` | Opts into the `preview` field on [`AskUserQuestion`](/docs/en/agent-sdk/user-input#question-format) options and sets its content format. When unset, Claude does not emit previews |
12321232 
12331233### `McpServerConfig`
from line 1306
13061306};
13071307```
13081308 
1309| Field | Type | Description |
1310| :----------------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1311| `type` | `'local'` | Must be `'local'` (only local plugins currently supported) |
1312| `path` | `string` | Absolute or relative path to the plugin directory |
1309| Field | Type | Description |
1310| :- | :- | :- |
1311| `type` | `'local'` | Must be `'local'` (only local plugins currently supported) |
1312| `path` | `string` | Absolute or relative path to the plugin directory |
13131313| `skipMcpDiscovery` | `boolean` | When `true`, the SDK loads skills, hooks, agents, and commands from this plugin but does not read its `.mcp.json` or manifest `mcpServers`. Set this when your application owns the plugin's MCP connections. |
13141314 
13151315**Example:**
from line 1562
15621562 
15631563Use the reason code to explain why fast mode is off in your own UI instead of re-deriving availability. Each code names the check that blocked fast mode:
15641564 
1565| Reason code | Meaning |
1566| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
1567| `free` | The account doesn't have the paid subscription or usage credits fast mode requires |
1568| `preference` | The organization has disabled fast mode |
1569| `extra_usage_disabled` | Usage credits are turned off for the account |
1570| `network_error` | The [availability check](/docs/en/fast-mode#use-fast-mode-behind-proxies-and-llm-gateways) couldn't reach `api.anthropic.com` |
1571| `unknown` | Claude Code couldn't determine availability |
1572| `not_first_party` | The session uses a provider other than the Anthropic API |
1573| `disabled_by_env` | [`CLAUDE_CODE_DISABLE_FAST_MODE`](/docs/en/env-vars) is set |
1574| `model_not_allowed` | The fast mode Opus model isn't in the organization's [`availableModels`](/docs/en/model-config#restrict-model-selection) allowlist |
1575| `sdk_opt_in_required` | The session hasn't opted in to fast mode: pass `fastMode: true` in the [`settings`](#options) option or through [`applyFlagSettings()`](#applyflagsettings) |
1576| `pending` | The availability check hasn't completed yet |
1565| Reason code | Meaning |
1566| - | - |
1567| `free` | The account doesn't have the paid subscription or usage credits fast mode requires |
1568| `preference` | The organization has disabled fast mode |
1569| `extra_usage_disabled` | Usage credits are turned off for the account |
1570| `network_error` | The [availability check](/docs/en/fast-mode#use-fast-mode-behind-proxies-and-llm-gateways) couldn't reach `api.anthropic.com` |
1571| `unknown` | Claude Code couldn't determine availability |
1572| `not_first_party` | The session uses a provider other than the Anthropic API |
1573| `disabled_by_env` | [`CLAUDE_CODE_DISABLE_FAST_MODE`](/docs/en/env-vars) is set |
1574| `model_not_allowed` | The fast mode Opus model isn't in the organization's [`availableModels`](/docs/en/model-config#restrict-model-selection) allowlist |
1575| `sdk_opt_in_required` | The session hasn't opted in to fast mode: pass `fastMode: true` in the [`settings`](#options) option or through [`applyFlagSettings()`](#applyflagsettings) |
1576| `pending` | The availability check hasn't completed yet |
15771577 
15781578The same pair of fields appears on [`SDKSystemMessage`](#sdksystemmessage) and on the [`SDKControlInitializeResponse`](#sdkcontrolinitializeresponse), so you can read the fast mode state before the first turn.
15791579 
from line 1670
16701670 
16711671Each value names one refusal:
16721672 
1673| Value | What stopped the session |
1674| :------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1675| `org_pin_api_key_conflict` | Managed settings [require a first-party or Cloud gateway sign-in](/docs/en/authentication#restrict-login-to-your-organization), and an Anthropic API key, auth token, or `apiKeyHelper` is configured instead |
1676| `org_verify_failed` | The sign-in's organization couldn't be verified against the pin, for example because of a network failure or a revoked token |
1677| `org_pin_mismatch` | The sign-in belongs to an organization the pin doesn't allow |
1678| `managed_settings_invalid` | Managed policy settings couldn't be read, the pin names no organization, or [managed model restrictions](/docs/en/errors#managed-settings-block-the-default-model) leave no permitted model for the Default option |
1679| `remote_settings_required_unavailable` | Managed settings that the organization requires couldn't be loaded |
1680| `gateway_signin_required` | The [Cloud gateway](/docs/en/claude-apps-gateway) ended this sign-in |
1681| `gateway_access_denied` | The managed settings request to the Cloud gateway came back with a 403, which the gateway's [troubleshooting table](/docs/en/claude-apps-gateway-deploy#troubleshooting) covers |
1682| `proxy_invalid` | A proxy setting isn't a complete URL |
1683| `temp_dir_unusable` | The per-user temporary directory is unsafe or couldn't be created |
1684| `cwd_unavailable` | The working directory was deleted, moved, or can't be read |
1685| `shell_tool_missing` | On Windows, no shell tool is available: Git Bash is missing, and PowerShell is missing or turned off with `CLAUDE_CODE_USE_POWERSHELL_TOOL` |
1686| `session_held_by_background` | The conversation to resume or continue is running as a [background session](/docs/en/agent-view) |
1687| `worktree_resume_refused` | The session's worktree failed its safety checks, or the resume was launched from inside it. `errors` says whether running the same resume again continues without the worktree |
1688| `worktree_unverified` | The session's worktree couldn't be verified right now, and retrying may succeed |
1689| `cli_version_too_old` | This Claude Code version is below the minimum Anthropic requires |
1690| `bypass_root` | Bypass permissions mode was requested while running as root |
1673| Value | What stopped the session |
1674| :- | :- |
1675| `org_pin_api_key_conflict` | Managed settings [require a first-party or Cloud gateway sign-in](/docs/en/authentication#restrict-login-to-your-organization), and an Anthropic API key, auth token, or `apiKeyHelper` is configured instead |
1676| `org_verify_failed` | The sign-in's organization couldn't be verified against the pin, for example because of a network failure or a revoked token |
1677| `org_pin_mismatch` | The sign-in belongs to an organization the pin doesn't allow |
1678| `managed_settings_invalid` | Managed policy settings couldn't be read, the pin names no organization, or [managed model restrictions](/docs/en/errors#managed-settings-block-the-default-model) leave no permitted model for the Default option |
1679| `remote_settings_required_unavailable` | Managed settings that the organization requires couldn't be loaded |
1680| `gateway_signin_required` | The [Cloud gateway](/docs/en/claude-apps-gateway) ended this sign-in |
1681| `gateway_access_denied` | The managed settings request to the Cloud gateway came back with a 403, which the gateway's [troubleshooting table](/docs/en/claude-apps-gateway-deploy#troubleshooting) covers |
1682| `proxy_invalid` | A proxy setting isn't a complete URL |
1683| `temp_dir_unusable` | The per-user temporary directory is unsafe or couldn't be created |
1684| `cwd_unavailable` | The working directory was deleted, moved, or can't be read |
1685| `shell_tool_missing` | On Windows, no shell tool is available: Git Bash is missing, and PowerShell is missing or turned off with `CLAUDE_CODE_USE_POWERSHELL_TOOL` |
1686| `session_held_by_background` | The conversation to resume or continue is running as a [background session](/docs/en/agent-view) |
1687| `worktree_resume_refused` | The session's worktree failed its safety checks, or the resume was launched from inside it. `errors` says whether running the same resume again continues without the worktree |
1688| `worktree_unverified` | The session's worktree couldn't be verified right now, and retrying may succeed |
1689| `cli_version_too_old` | This Claude Code version is below the minimum Anthropic requires |
1690| `bypass_root` | Bypass permissions mode was requested while running as root |
16911691 
16921692### `SDKSystemMessage`
16931693 
from line 1739
17391739 
17401740The `capabilities` array names the protocol behaviors this CLI implements, so you can feature-detect instead of comparing `claude_code_version` strings. It is an open set: ignore values you don't recognize, and check for the specific capability whose behavior you rely on. The field requires Claude Code v2.1.205 or later and is absent on earlier CLIs.
17411741 
1742| Capability | Meaning |
1743| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1744| `interrupt_receipt_v1` | [`interrupt()`](#query-object) resolves with an [`SDKControlInterruptResponse`](#sdkcontrolinterruptresponse) receipt listing the messages that were pending when the interrupt arrived |
1742| Capability | Meaning |
1743| - | - |
1744| `interrupt_receipt_v1` | [`interrupt()`](#query-object) resolves with an [`SDKControlInterruptResponse`](#sdkcontrolinterruptresponse) receipt listing the messages that were pending when the interrupt arrived |
17451745| `interrupt_cancel_queued_v1` | The `interrupt` control request honors `cancel_queued: true`, cancelling the messages the receipt would otherwise list under `still_queued` and listing them under `cancelled` instead. See [`SDKControlInterruptResponse`](#sdkcontrolinterruptresponse). Requires Claude Code v2.1.219 or later |
17461746 
17471747The `plugin_errors` array lists plugin load failures. An entry describes either a plugin that didn't load and is absent from `plugins`, or a plugin that loaded without one of its parts, such as its hooks file. The key is omitted when nothing failed. `SDKSystemMessage` declares `plugin_errors` in Agent SDK v0.3.283 or later.
from line 1750
17501750 
17511751The table below lists the fields of each `plugin_errors` entry.
17521752 
1753| Field | Type | Description |
1754| --------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1755| `plugin` | `string` | The failing plugin's ID, or a positional tag such as `inline[0]` when the plugin directory or archive itself failed to load |
1756| `type` | `string` | Error category from an open set, such as `path-not-found` or `manifest-validation-error`. Treat a value you don't recognize as a generic failure |
1757| `message` | `string` | Display text describing the failure |
1758| `path` | `string` | Present only when the plugin directory or archive itself failed to load. Its absolute path, with a relative path from your `plugins` option resolved against the [`cwd`](#options) option |
1753| Field | Type | Description |
1754| - | - | - |
1755| `plugin` | `string` | The failing plugin's ID, or a positional tag such as `inline[0]` when the plugin directory or archive itself failed to load |
1756| `type` | `string` | Error category from an open set, such as `path-not-found` or `manifest-validation-error`. Treat a value you don't recognize as a generic failure |
1757| `message` | `string` | Display text describing the failure |
1758| `path` | `string` | Present only when the plugin directory or archive itself failed to load. Its absolute path, with a relative path from your `plugins` option resolved against the [`cwd`](#options) option |
17591759 
17601760### `SDKPartialAssistantMessage`
17611761 
from line 1871
18711871};
18721872```
18731873 
1874| Field | Type | Description |
1875| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
1876| `tool_name` | `string` | Name of the tool that was denied |
1877| `tool_use_id` | `string` | ID of the `tool_use` block this denial answers |
1878| `agent_id` | `string` | Subagent ID when the denied call originated inside a subagent. Mirrors the field on `can_use_tool` for host-side routing |
1879| `decision_reason_type` | `string` | Discriminator for the component that decided, such as `"rule"`, `"mode"`, `"classifier"`, or `"asyncAgent"` |
1880| `decision_reason` | `string` | Human-readable reason from the deciding component, when available |
1881| `message` | `string` | Rejection message returned to the model in the `tool_result` |
1874| Field | Type | Description |
1875| - | - | - |
1876| `tool_name` | `string` | Name of the tool that was denied |
1877| `tool_use_id` | `string` | ID of the `tool_use` block this denial answers |
1878| `agent_id` | `string` | Subagent ID when the denied call originated inside a subagent. Mirrors the field on `can_use_tool` for host-side routing |
1879| `decision_reason_type` | `string` | Discriminator for the component that decided, such as `"rule"`, `"mode"`, `"classifier"`, or `"asyncAgent"` |
1880| `decision_reason` | `string` | Human-readable reason from the deciding component, when available |
1881| `message` | `string` | Rejection message returned to the model in the `tool_result` |
18821882 
18831883### `SDKPermissionDenial`
18841884 
from line 1933
19331933 
19341934The table lists what Claude Code puts in each field. The fields from `model` through `over_limit` describe the session as a whole, and the collection fields attribute tokens to individual items.
19351935 
1936| Field | Type | Description |
1937| ---------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1938| `model` | `string` | The main loop's model Claude Code computed the usage for, not a subagent's |
1939| `total_tokens` | `number` | Claude Code's estimate of the tokens in use. Not clamped to the window, so it can exceed `raw_max_tokens` when the session is over the limit |
1940| `raw_max_tokens` | `number` | The model's context window, or the lower [auto-compact window](/docs/en/model-config#context-window-and-auto-compaction) when one applies, such as one you set or the 200K boundary Claude Code applies to some models with a 1M-token window. Claude Code measures `total_tokens` against this window |
1941| `percentage` | `number` | `total_tokens` as a rounded percentage of `raw_max_tokens`, so it can exceed 100 when the session is over the limit |
1942| `over_limit` | `object` | Present only when `total_tokens` exceeds `raw_max_tokens`. `tokens_over` is the amount over, and `kind` says how Claude Code resolved the window |
1943| `categories` | [`SDKContextUsageCategory`](#sdkcontextusagecategory)`[]` | One entry per row of the usage-by-category breakdown |
1944| `mcp_tools` | `object[]` | Tokens attributed to each MCP tool, with its wire name, such as `mcp__linear__create_issue`, and its `server_name` |
1945| `memory_files` | `object[]` | Tokens attributed to each loaded memory file, with its `path` and a source label such as `Project` or `User` in `type` |
1946| `agents` | `object[]` | Tokens attributed to each custom subagent definition, with a source identifier such as `projectSettings`, `userSettings`, or `plugin`. Built-in subagents aren't listed |
1947| `skills` | `object[]` | Tokens attributed to each skill in the skill listing, with a source identifier and, for plugin skills, the plugin's name in `plugin_name`. Absent when no skills contribute tokens |
1936| Field | Type | Description |
1937| - | - | - |
1938| `model` | `string` | The main loop's model Claude Code computed the usage for, not a subagent's |
1939| `total_tokens` | `number` | Claude Code's estimate of the tokens in use. Not clamped to the window, so it can exceed `raw_max_tokens` when the session is over the limit |
1940| `raw_max_tokens` | `number` | The model's context window, or the lower [auto-compact window](/docs/en/model-config#context-window-and-auto-compaction) when one applies, such as one you set or the 200K boundary Claude Code applies to some models with a 1M-token window. Claude Code measures `total_tokens` against this window |
1941| `percentage` | `number` | `total_tokens` as a rounded percentage of `raw_max_tokens`, so it can exceed 100 when the session is over the limit |
1942| `over_limit` | `object` | Present only when `total_tokens` exceeds `raw_max_tokens`. `tokens_over` is the amount over, and `kind` says how Claude Code resolved the window |
1943| `categories` | [`SDKContextUsageCategory`](#sdkcontextusagecategory)`[]` | One entry per row of the usage-by-category breakdown |
1944| `mcp_tools` | `object[]` | Tokens attributed to each MCP tool, with its wire name, such as `mcp__linear__create_issue`, and its `server_name` |
1945| `memory_files` | `object[]` | Tokens attributed to each loaded memory file, with its `path` and a source label such as `Project` or `User` in `type` |
1946| `agents` | `object[]` | Tokens attributed to each custom subagent definition, with a source identifier such as `projectSettings`, `userSettings`, or `plugin`. Built-in subagents aren't listed |
1947| `skills` | `object[]` | Tokens attributed to each skill in the skill listing, with a source identifier and, for plugin skills, the plugin's name in `plugin_name`. Absent when no skills contribute tokens |
19481948 
19491949`over_limit.kind` records how Claude Code resolved the window, not whether the API accepts the next request:
19501950 
from line 1967
19671967 
19681968The table lists what Claude Code puts in each field of a row.
19691969 
1970| Field | Type | Description |
1971| -------- | -------- | -------------------------------------------------------------------------------------------------------- |
1972| `name` | `string` | The row's display name as `/context` prints it, such as `Messages`. Classify rows by `kind`, not by name |
1973| `tokens` | `number` | The row's token count. Rows can carry zero tokens |
1974| `kind` | `string` | What the row represents: `used`, `free`, `buffer`, or `deferred` |
1970| Field | Type | Description |
1971| - | - | - |
1972| `name` | `string` | The row's display name as `/context` prints it, such as `Messages`. Classify rows by `kind`, not by name |
1973| `tokens` | `number` | The row's token count. Rows can carry zero tokens |
1974| `kind` | `string` | What the row represents: `used`, `free`, `buffer`, or `deferred` |
19751975 
19761976Each `kind` value says what the row's tokens are:
19771977 
from line 2008
20082008 | { kind: "unclassified" };
20092009```
20102010 
2011| `kind` | Meaning |
2012| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2013| `human` | Direct input from the end user. If your application forwards what the user typed as a user message, set its `origin` to `{ kind: "human" }` explicitly: Claude Code treats a user message with no `origin` as unattributed, and checks that require a human-typed prompt, such as the [`ultracode` workflow keyword](/docs/en/workflows#ask-for-a-workflow-in-your-prompt), don't accept it. Before v2.1.210, Claude Code treated an absent `origin` on a user message as human input. |
2014| `channel` | Message arriving on a [channel](/docs/en/channels). `server` is the source MCP server name. |
2015| `peer` | Message from another agent: an in-process [teammate](/docs/en/agent-teams) or a [cross-session peer](/docs/en/cross-session-messaging), another of your Claude Code sessions. See [Peer origin fields](#peer-origin-fields) for the per-field semantics and the trust model. |
2016| `task-notification` | Synthetic turn injected for a delivery that arrives without a fresh user prompt, such as a finished background task; see [`SDKTaskNotificationMessage`](#sdktasknotificationmessage) for that arm. A prompt your application [declares as a scheduled run](#declare-a-scheduled-run) carries this kind too. The optional `subkind` marks what raised the notification. See [Task-notification subkinds](#task-notification-subkinds). |
2017| `coordinator` | Message from a team coordinator in an [agent team](/docs/en/agent-teams). |
2018| `auto-continuation` | Synthetic turn injected when the session continues without fresh user input, such as a command result that triggers a follow-up prompt. |
2019| `unclassified` | Injected turn whose origin couldn't be determined. Requires Claude Code v2.1.223 or later. When Claude Code receives an [`SDKUserMessage`](#sdkusermessage) with `isSynthetic: true` and can't classify it as any other `kind`, it sets this kind as the message arrives and frames the turn to the model as a non-user source rather than treating it as human input. Your application shouldn't set this value. |
2011| `kind` | Meaning |
2012| - | - |
2013| `human` | Direct input from the end user. If your application forwards what the user typed as a user message, set its `origin` to `{ kind: "human" }` explicitly: Claude Code treats a user message with no `origin` as unattributed, and checks that require a human-typed prompt, such as the [`ultracode` workflow keyword](/docs/en/workflows#ask-for-a-workflow-in-your-prompt), don't accept it. Before v2.1.210, Claude Code treated an absent `origin` on a user message as human input. |
2014| `channel` | Message arriving on a [channel](/docs/en/channels). `server` is the source MCP server name. |
2015| `peer` | Message from another agent: an in-process [teammate](/docs/en/agent-teams) or a [cross-session peer](/docs/en/cross-session-messaging), another of your Claude Code sessions. See [Peer origin fields](#peer-origin-fields) for the per-field semantics and the trust model. |
2016| `task-notification` | Synthetic turn injected for a delivery that arrives without a fresh user prompt, such as a finished background task; see [`SDKTaskNotificationMessage`](#sdktasknotificationmessage) for that arm. A prompt your application [declares as a scheduled run](#declare-a-scheduled-run) carries this kind too. The optional `subkind` marks what raised the notification. See [Task-notification subkinds](#task-notification-subkinds). |
2017| `coordinator` | Message from a team coordinator in an [agent team](/docs/en/agent-teams). |
2018| `auto-continuation` | Synthetic turn injected when the session continues without fresh user input, such as a command result that triggers a follow-up prompt. |
2019| `unclassified` | Injected turn whose origin couldn't be determined. Requires Claude Code v2.1.223 or later. When Claude Code receives an [`SDKUserMessage`](#sdkusermessage) with `isSynthetic: true` and can't classify it as any other `kind`, it sets this kind as the message arrives and frames the turn to the model as a non-user source rather than treating it as human input. Your application shouldn't set this value. |
20202020 
20212021### Task-notification subkinds
20222022 
from line 3083
30833083 
30843084Runs a [dynamic workflow](/docs/en/workflows): a script that orchestrates many subagents in the background and returns one consolidated result. The `Workflow` tool is available in Agent SDK v0.3.149 and later. At least one of `script`, `name`, or `scriptPath` is required.
30853085 
3086| Field | Type | Description |
3087| ----------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
3088| `script` | `string` | Inline workflow script. Must begin with `export const meta = { name, description }` as a literal, followed by the script body using `agent()`, `parallel()`, `pipeline()`, and `phase()`. An optional `phases` array in `meta` groups agents under named stages in the progress view |
3089| `name` | `string` | Name of a built-in workflow or one saved in `.claude/workflows/`. Resolved to a script |
3090| `scriptPath` | `string` | Path to a workflow script file on disk. Takes precedence over `script` and `name`. Claude Code persists every invocation's script and returns the path in the result, so you can edit that file and re-invoke with the same `scriptPath` to iterate |
3091| `args` | `unknown` | Input value exposed to the script as the global `args`, for parameterized named workflows such as a research question or a list of file paths. Pass arrays and objects as actual JSON values, not as a JSON-encoded string |
3092| `resumeFromRunId` | `string` | Run ID of a prior `Workflow` invocation to resume. Completed `agent()` calls with unchanged inputs usually return cached results; the rest run live. [Resume after a pause](/docs/en/workflows#resume-after-a-pause) covers which completed calls re-run. Same session only |
3093| `title` | `string` | Ignored; the script's `meta` block sets the title |
3094| `description` | `string` | Ignored; the script's `meta` block sets the description |
3086| Field | Type | Description |
3087| - | - | - |
3088| `script` | `string` | Inline workflow script. Must begin with `export const meta = { name, description }` as a literal, followed by the script body using `agent()`, `parallel()`, `pipeline()`, and `phase()`. An optional `phases` array in `meta` groups agents under named stages in the progress view |
3089| `name` | `string` | Name of a built-in workflow or one saved in `.claude/workflows/`. Resolved to a script |
3090| `scriptPath` | `string` | Path to a workflow script file on disk. Takes precedence over `script` and `name`. Claude Code persists every invocation's script and returns the path in the result, so you can edit that file and re-invoke with the same `scriptPath` to iterate |
3091| `args` | `unknown` | Input value exposed to the script as the global `args`, for parameterized named workflows such as a research question or a list of file paths. Pass arrays and objects as actual JSON values, not as a JSON-encoded string |
3092| `resumeFromRunId` | `string` | Run ID of a prior `Workflow` invocation to resume. Completed `agent()` calls with unchanged inputs usually return cached results; the rest run live. [Resume after a pause](/docs/en/workflows#resume-after-a-pause) covers which completed calls re-run. Same session only |
3093| `title` | `string` | Ignored; the script's `meta` block sets the title |
3094| `description` | `string` | Ignored; the script's `meta` block sets the description |
30953095 
30963096### TodoWrite
30973097 
from line 3705
37053705 
37063706The `stdout`, `stderr`, and `backgroundTaskId` fields carry:
37073707 
3708| Field | What it carries |
3709| ------------------ | ----------------------------------------------------------------------------------------------- |
3710| `stdout` | The command's stdout and stderr, merged into one interleaved stream |
3711| `stderr` | Notices the tool itself adds, such as a shell working-directory reset, not the command's stderr |
3712| `backgroundTaskId` | Present for background commands |
3708| Field | What it carries |
3709| - | - |
3710| `stdout` | The command's stdout and stderr, merged into one interleaved stream |
3711| `stderr` | Notices the tool itself adds, such as a shell working-directory reset, not the command's stderr |
3712| `backgroundTaskId` | Present for background commands |
37133713 
37143714`timedOutAfterMs` is the timeout in milliseconds, set when the command reached its timeout and moved to the background rather than starting there explicitly. `backgroundCwdHint` is set when the backgrounded command contained a directory-change builtin such as `cd`, `pushd`, `popd`, or `chdir`, and notes that the session working directory didn't change. Both fields require Claude Code v2.1.210 or later.
37153715 
from line 4021
40214021 
40224022Returns immediately after the tool accepts the invocation. The final result arrives later as a task completion. Check `error` before treating the run as started: a script that fails its syntax check returns `status: "async_launched"` with `error` set, and never runs.
40234023 
4024| Field | Type | Description |
4025| --------------- | --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
4026| `status` | `"async_launched" \| "remote_launched"` | The tool accepted the invocation. `"async_launched"` for in-process runs, `"remote_launched"` for runs dispatched to a cloud session instead of running in-process |
4027| `taskId` | `string` | Background task identifier for the run |
4028| `taskType` | `"local_workflow" \| "remote_agent"` | Task type of the registered background task, matching the `status` arm |
4029| `workflowName` | `string` | The `meta.name` from the workflow script |
4030| `runId` | `string` | Workflow run identifier to pass as `resumeFromRunId` on a later invocation. Absent for `remote_launched` runs, where the cloud session URL is the resume handle |
4031| `summary` | `string` | One-line description of what the workflow does |
4032| `transcriptDir` | `string` | Directory where subagent transcripts are written during execution |
4033| `scriptPath` | `string` | Path to the persisted workflow script for this run. Edit it and pass back as `scriptPath` to rerun without resending the script |
4034| `sessionUrl` | `string` | Cloud session URL, set when `status` is `"remote_launched"` |
4035| `warning` | `string` | Non-blocking heads-up, such as local git state diverging from the pushed branch a cloud session will clone |
4036| `error` | `string` | Set when the script fails its syntax check. When present, the run did not start despite the launched status |
4024| Field | Type | Description |
4025| - | - | - |
4026| `status` | `"async_launched" \| "remote_launched"` | The tool accepted the invocation. `"async_launched"` for in-process runs, `"remote_launched"` for runs dispatched to a cloud session instead of running in-process |
4027| `taskId` | `string` | Background task identifier for the run |
4028| `taskType` | `"local_workflow" \| "remote_agent"` | Task type of the registered background task, matching the `status` arm |
4029| `workflowName` | `string` | The `meta.name` from the workflow script |
4030| `runId` | `string` | Workflow run identifier to pass as `resumeFromRunId` on a later invocation. Absent for `remote_launched` runs, where the cloud session URL is the resume handle |
4031| `summary` | `string` | One-line description of what the workflow does |
4032| `transcriptDir` | `string` | Directory where subagent transcripts are written during execution |
4033| `scriptPath` | `string` | Path to the persisted workflow script for this run. Edit it and pass back as `scriptPath` to rerun without resending the script |
4034| `sessionUrl` | `string` | Cloud session URL, set when `status` is `"remote_launched"` |
4035| `warning` | `string` | Non-blocking heads-up, such as local git state diverging from the pushed branch a cloud session will clone |
4036| `error` | `string` | Set when the script fails its syntax check. When present, the run did not start despite the launched status |
40374037 
40384038### TodoWrite
40394039 
from line 4607
46074607 
46084608Claude Code reports one of four values:
46094609 
4610| Value | Key in use |
4611| -------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
4612| `ANTHROPIC_API_KEY` | The key in the `ANTHROPIC_API_KEY` environment variable |
4613| `apiKeyHelper` | The key returned by your [`apiKeyHelper`](/docs/en/settings-reference#apikeyhelper) command |
4610| Value | Key in use |
4611| - | - |
4612| `ANTHROPIC_API_KEY` | The key in the `ANTHROPIC_API_KEY` environment variable |
4613| `apiKeyHelper` | The key returned by your [`apiKeyHelper`](/docs/en/settings-reference#apikeyhelper) command |
46144614| `/login managed key` | The key Claude Code stored when you logged in with a [Claude Console account](/docs/en/authentication#claude-console-authentication) |
4615| `none` | No API key. The session authenticates another way, such as a claude.ai login, a bearer token, or a cloud provider |
4615| `none` | No API key. The session authenticates another way, such as a claude.ai login, a bearer token, or a cloud provider |
46164616 
46174617Agent SDK v0.3.234 and later list these four values in the type. The type also keeps `user`, `project`, `org`, `temporary`, and `oauth` so older code still compiles, and Claude Code doesn't report them.
46184618 
from line 4662
46624662};
46634663```
46644664 
4665| Field | Type | Description |
4666| :------------------------- | :----------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
4667| `value` | `string` | Model identifier to pass in API calls |
4668| `resolvedModel` | `string \| undefined` | Canonical wire model ID that this entry's `value` resolves to. An alias entry such as `sonnet` resolves to an explicit model ID such as `claude-sonnet-5`, so a host can match a stored explicit model ID against the alias entry that covers it. Requires Claude Code v2.1.197 or later. |
4669| `displayName` | `string` | Human-readable display name |
4670| `description` | `string` | Description of the model's capabilities |
4671| `supportsEffort` | `boolean \| undefined` | Whether this model supports effort levels |
4672| `supportedEffortLevels` | `("low" \| "medium" \| "high" \| "xhigh" \| "max")[] \| undefined` | Effort levels this model accepts |
4673| `supportsAdaptiveThinking` | `boolean \| undefined` | Whether this model supports adaptive thinking, where Claude decides when and how much to think |
4674| `supportsFastMode` | `boolean \| undefined` | Whether this model supports fast mode |
4675| `supportsAutoMode` | `boolean \| undefined` | Whether this model supports auto mode |
4665| Field | Type | Description |
4666| :- | :- | :- |
4667| `value` | `string` | Model identifier to pass in API calls |
4668| `resolvedModel` | `string \| undefined` | Canonical wire model ID that this entry's `value` resolves to. An alias entry such as `sonnet` resolves to an explicit model ID such as `claude-sonnet-5`, so a host can match a stored explicit model ID against the alias entry that covers it. Requires Claude Code v2.1.197 or later. |
4669| `displayName` | `string` | Human-readable display name |
4670| `description` | `string` | Description of the model's capabilities |
4671| `supportsEffort` | `boolean \| undefined` | Whether this model supports effort levels |
4672| `supportedEffortLevels` | `("low" \| "medium" \| "high" \| "xhigh" \| "max")[] \| undefined` | Effort levels this model accepts |
4673| `supportsAdaptiveThinking` | `boolean \| undefined` | Whether this model supports adaptive thinking, where Claude decides when and how much to think |
4674| `supportsFastMode` | `boolean \| undefined` | Whether this model supports fast mode |
4675| `supportsAutoMode` | `boolean \| undefined` | Whether this model supports auto mode |
46764676 
46774677### `AgentInfo`
46784678 
from line 4686
46864686};
46874687```
46884688 
4689| Field | Type | Description |
4690| :------------ | :-------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
4691| `name` | `string` | Agent type identifier (for example, `"Explore"`, `"general-purpose"`) |
4692| `description` | `string` | Description of when to use this agent |
4693| `model` | `string \| undefined` | Model this agent uses: an alias or model ID, or `'inherit'` for the parent's model. When it's `undefined`, Claude Code picks the model in the [subagent model order](/docs/en/sub-agents#choose-a-model) |
4689| Field | Type | Description |
4690| :- | :- | :- |
4691| `name` | `string` | Agent type identifier (for example, `"Explore"`, `"general-purpose"`) |
4692| `description` | `string` | Description of when to use this agent |
4693| `model` | `string \| undefined` | Model this agent uses: an alias or model ID, or `'inherit'` for the parent's model. When it's `undefined`, Claude Code picks the model in the [subagent model order](/docs/en/sub-agents#choose-a-model) |
46944694 
46954695### `McpServerProvenance`
46964696 
from line 4703
47034703};
47044704```
47054705 
4706| Field | Type | Description |
4707| :------- | :------- | :---------------------------------------------------------------------------------------------------------- |
4708| `name` | `string` | The name the server is registered under, the same value [`mcpServerStatus()`](#query-object) reports for it |
4709| `source` | `string` | Where the server's definition came from: `sdk`, `plugin`, or a configuration scope |
4706| Field | Type | Description |
4707| :- | :- | :- |
4708| `name` | `string` | The name the server is registered under, the same value [`mcpServerStatus()`](#query-object) reports for it |
4709| `source` | `string` | Where the server's definition came from: `sdk`, `plugin`, or a configuration scope |
47104710 
47114711`source` takes one of the following values. The set is open, so treat a value you don't recognize as a configured source, never as `sdk`:
47124712 
from line 4890
48904890 
48914891Claude Code drops a block whose `uri` or `name` isn't a string, and leaves out an optional field whose value isn't of the listed type.
48924892 
4893| Field | Type | Description |
4894| :------------ | :------------------------------------- | :---------------------------------------------------------- |
4895| `uri` | `string` | URI of the resource, as the server returned it |
4896| `name` | `string` | Name the server gave the resource |
4897| `title` | `string \| undefined` | Display title, when the server set one |
4898| `description` | `string \| undefined` | Description, when the server set one |
4899| `mimeType` | `string \| undefined` | MIME type, when the server set one |
4900| `size` | `number \| undefined` | Size in bytes, when the server set one |
4893| Field | Type | Description |
4894| :- | :- | :- |
4895| `uri` | `string` | URI of the resource, as the server returned it |
4896| `name` | `string` | Name the server gave the resource |
4897| `title` | `string \| undefined` | Display title, when the server set one |
4898| `description` | `string \| undefined` | Description, when the server set one |
4899| `mimeType` | `string \| undefined` | MIME type, when the server set one |
4900| `size` | `number \| undefined` | Size in bytes, when the server set one |
49014901| `annotations` | `Record<string, unknown> \| undefined` | The block's MCP annotations object, when the server set one |
49024902 
49034903### `ThinkingConfig`
from line 5439
54395439};
54405440```
54415441 
5442| Property | Type | Default | Description |
5443| :-------------------------- | :---------------------------------------------------- | :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
5444| `enabled` | `boolean` | `false` | Enable sandbox mode for command execution |
5445| `failIfUnavailable` | `boolean` | `true` | Stop at startup if `enabled` is `true` but the sandbox can't start. Set `false` to fall back to unsandboxed execution with a warning on stderr |
5446| `autoAllowBashIfSandboxed` | `boolean` | `true` | Auto-approve Bash commands when sandbox is enabled |
5447| `excludedCommands` | `string[]` | `[]` | Commands that bypass sandbox restrictions, such as `['docker *']`. These run unsandboxed automatically without model involvement; [`sandbox.excludedCommands`](/docs/en/settings-reference#sandbox-excludedcommands) covers when an entry applies |
5448| `allowUnsandboxedCommands` | `boolean` | `true` | Allow the model to request running commands outside the sandbox. When `true`, the model can set `dangerouslyDisableSandbox` in tool input, which falls back to the [permissions system](#permissions-fallback-for-unsandboxed-commands) |
5449| `network` | [`SandboxNetworkConfig`](#sandboxnetworkconfig) | `undefined` | Network-specific sandbox configuration |
5450| `filesystem` | [`SandboxFilesystemConfig`](#sandboxfilesystemconfig) | `undefined` | Filesystem-specific sandbox configuration for read/write restrictions |
5451| `ignoreViolations` | `Record<string, string[]>` | `undefined` | Map of command substrings, or `*` for every command, to substrings of the violation text to ignore, such as `{ "*": ['/etc/hosts'] }`; see [`sandbox.ignoreViolations`](/docs/en/settings-reference#sandbox-ignoreviolations) |
5452| `enableWeakerNestedSandbox` | `boolean` | `false` | Enable a weaker nested sandbox for compatibility |
5453| `ripgrep` | `{ command: string; args?: string[] }` | `undefined` | Custom ripgrep binary configuration for sandbox environments |
5442| Property | Type | Default | Description |
5443| :- | :- | :- | :- |
5444| `enabled` | `boolean` | `false` | Enable sandbox mode for command execution |
5445| `failIfUnavailable` | `boolean` | `true` | Stop at startup if `enabled` is `true` but the sandbox can't start. Set `false` to fall back to unsandboxed execution with a warning on stderr |
5446| `autoAllowBashIfSandboxed` | `boolean` | `true` | Auto-approve Bash commands when sandbox is enabled |
5447| `excludedCommands` | `string[]` | `[]` | Commands that bypass sandbox restrictions, such as `['docker *']`. These run unsandboxed automatically without model involvement; [`sandbox.excludedCommands`](/docs/en/settings-reference#sandbox-excludedcommands) covers when an entry applies |
5448| `allowUnsandboxedCommands` | `boolean` | `true` | Allow the model to request running commands outside the sandbox. When `true`, the model can set `dangerouslyDisableSandbox` in tool input, which falls back to the [permissions system](#permissions-fallback-for-unsandboxed-commands) |
5449| `network` | [`SandboxNetworkConfig`](#sandboxnetworkconfig) | `undefined` | Network-specific sandbox configuration |
5450| `filesystem` | [`SandboxFilesystemConfig`](#sandboxfilesystemconfig) | `undefined` | Filesystem-specific sandbox configuration for read/write restrictions |
5451| `ignoreViolations` | `Record<string, string[]>` | `undefined` | Map of command substrings, or `*` for every command, to substrings of the violation text to ignore, such as `{ "*": ['/etc/hosts'] }`; see [`sandbox.ignoreViolations`](/docs/en/settings-reference#sandbox-ignoreviolations) |
5452| `enableWeakerNestedSandbox` | `boolean` | `false` | Enable a weaker nested sandbox for compatibility |
5453| `ripgrep` | `{ command: string; args?: string[] }` | `undefined` | Custom ripgrep binary configuration for sandbox environments |
54545454 
54555455<Note>
54565456 The sandbox depends on platform support and, on Linux, tools like `bubblewrap` and `socat`. When `enabled` is `true` and the sandbox can't start, `query()` reports a `result` message with `subtype: "error_during_execution"` and the reason in `errors`. For a single message `query()` call, the SDK throws after yielding that error result, so wrap the loop in a try block to continue past it. See [Handle the result](/docs/en/agent-sdk/agent-loop#handle-the-result) for the error contract.
from line 5507
55075507};
55085508```
55095509 
5510| Property | Type | Default | Description |
5511| :------------------------ | :--------- | :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
5512| `allowedDomains` | `string[]` | `[]` | Domain names that sandboxed processes can access |
5513| `deniedDomains` | `string[]` | `[]` | Domain names that sandboxed processes cannot access. Takes precedence over `allowedDomains` |
5514| `strictAllowlist` | `boolean` | `false` | Deny sandboxed commands access to hosts outside the [network allowlist](/docs/en/sandboxing#network-isolation) instead of prompting. Enforced for sandboxed commands only; in-process tools such as WebFetch aren't gated by it. Only honored from user, managed, or CLI `--settings` settings; project settings are ignored. Requires Claude Code v2.1.219 or later |
5515| `allowManagedDomainsOnly` | `boolean` | `false` | Managed-settings only. When set in [managed settings](/docs/en/managed-settings), only `allowedDomains` entries and `WebFetch(domain:...)` allow rules from managed settings are honored, and allow entries from user, project, or local settings are ignored. From the SDK, pass it through the [`managedSettings`](#options) option |
5516| `allowLocalBinding` | `boolean` | `false` | Allow processes to bind to local ports (for example, for dev servers) |
5517| `allowUnixSockets` | `string[]` | `[]` | Unix socket paths that processes can access (for example, Docker socket) |
5518| `allowAllUnixSockets` | `boolean` | `false` | Allow access to all Unix sockets |
5519| `httpProxyPort` | `number` | `undefined` | HTTP proxy port for network requests |
5520| `socksProxyPort` | `number` | `undefined` | SOCKS proxy port for network requests |
5510| Property | Type | Default | Description |
5511| :- | :- | :- | :- |
5512| `allowedDomains` | `string[]` | `[]` | Domain names that sandboxed processes can access |
5513| `deniedDomains` | `string[]` | `[]` | Domain names that sandboxed processes cannot access. Takes precedence over `allowedDomains` |
5514| `strictAllowlist` | `boolean` | `false` | Deny sandboxed commands access to hosts outside the [network allowlist](/docs/en/sandboxing#network-isolation) instead of prompting. Enforced for sandboxed commands only; in-process tools such as WebFetch aren't gated by it. Only honored from user, managed, or CLI `--settings` settings; project settings are ignored. Requires Claude Code v2.1.219 or later |
5515| `allowManagedDomainsOnly` | `boolean` | `false` | Managed-settings only. When set in [managed settings](/docs/en/managed-settings), only `allowedDomains` entries and `WebFetch(domain:...)` allow rules from managed settings are honored, and allow entries from user, project, or local settings are ignored. From the SDK, pass it through the [`managedSettings`](#options) option |
5516| `allowLocalBinding` | `boolean` | `false` | Allow processes to bind to local ports (for example, for dev servers) |
5517| `allowUnixSockets` | `string[]` | `[]` | Unix socket paths that processes can access (for example, Docker socket) |
5518| `allowAllUnixSockets` | `boolean` | `false` | Allow access to all Unix sockets |
5519| `httpProxyPort` | `number` | `undefined` | HTTP proxy port for network requests |
5520| `socksProxyPort` | `number` | `undefined` | SOCKS proxy port for network requests |
55215521 
55225522<Note>
55235523 The built-in sandbox proxy enforces `allowedDomains` based on the requested hostname and does not terminate or inspect TLS traffic, so techniques such as [domain fronting](https://en.wikipedia.org/wiki/Domain_fronting) can potentially bypass it. See [Sandboxing security limitations](/docs/en/sandboxing#security-limitations) for details and [Secure deployment](/docs/en/agent-sdk/secure-deployment#traffic-forwarding) for configuring a TLS-terminating proxy.
from line 5535
55355535};
55365536```
55375537 
5538| Property | Type | Default | Description |
5539| :----------- | :--------- | :------ | :------------------------------------------ |
5540| `allowWrite` | `string[]` | `[]` | File path patterns to allow write access to |
5541| `denyWrite` | `string[]` | `[]` | File path patterns to deny write access to |
5542| `denyRead` | `string[]` | `[]` | File path patterns to deny read access to |
5538| Property | Type | Default | Description |
5539| :- | :- | :- | :- |
5540| `allowWrite` | `string[]` | `[]` | File path patterns to allow write access to |
5541| `denyWrite` | `string[]` | `[]` | File path patterns to deny write access to |
5542| `denyRead` | `string[]` | `[]` | File path patterns to deny read access to |
55435543 
55445544### Permissions Fallback for Unsandboxed Commands
55455545 
55465546 

agent-sdk/user-input Changed · +33 / -33 lines

from line 58
5858 
5959Your callback receives three arguments:
6060 
61| Argument | Description |
62| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
63| `toolName` | The name of the tool Claude wants to use (for example, `"Bash"`, `"Write"`, `"Edit"`) |
64| `input` | The parameters Claude is passing to the tool. Contents vary by tool. |
61| Argument | Description |
62| - | - |
63| `toolName` | The name of the tool Claude wants to use (for example, `"Bash"`, `"Write"`, `"Edit"`) |
64| `input` | The parameters Claude is passing to the tool. Contents vary by tool. |
6565| `options` (TS) / `context` (Python) | Additional context including optional `suggestions` (proposed `PermissionUpdate` entries to avoid re-prompting) and a cancellation signal. In TypeScript, `signal` is an `AbortSignal`; in Python, the signal field is reserved for future use. See [`ToolPermissionContext`](/docs/en/agent-sdk/python#toolpermissioncontext) for Python. |
6666 
6767The `input` object contains tool-specific parameters. Common examples:
6868 
69| Tool | Input fields |
70| ------- | --------------------------------------- |
71| `Bash` | `command`, `description`, `timeout` |
72| `Write` | `file_path`, `content` |
73| `Edit` | `file_path`, `old_string`, `new_string` |
74| `Read` | `file_path`, `offset`, `limit` |
69| Tool | Input fields |
70| - | - |
71| `Bash` | `command`, `description`, `timeout` |
72| `Write` | `file_path`, `content` |
73| `Edit` | `file_path`, `old_string`, `new_string` |
74| `Read` | `file_path`, `offset`, `limit` |
7575 
7676See the SDK reference for complete input schemas: [Python](/docs/en/agent-sdk/python#tool-input%2Foutput-types) | [TypeScript](/docs/en/agent-sdk/typescript#tool-input-types).
7777 
from line 202
202202 
203203Your callback returns one of two response types:
204204 
205| Response | Python | TypeScript |
206| --------- | ------------------------------------------ | ------------------------------------- |
205| Response | Python | TypeScript |
206| - | - | - |
207207| **Allow** | `PermissionResultAllow(updated_input=...)` | `{ behavior: "allow", updatedInput }` |
208| **Deny** | `PermissionResultDeny(message=...)` | `{ behavior: "deny", message }` |
208| **Deny** | `PermissionResultDeny(message=...)` | `{ behavior: "deny", message }` |
209209 
210210When allowing, the tool runs with the input Claude requested unless you return a modified input, `updatedInput` in TypeScript or `updated_input` in Python. Before v2.1.207, Claude Code rejected an allow result that omitted `updatedInput` and denied the tool call with a validation error.
211211 
from line 502
502502 <Step title="Return answers to Claude">
503503 Build the `answers` object as a record where each key is the `question` text and each value is the selected option's `label`:
504504 
505 | From the question object | Use as |
506 | ------------------------------------------------------------------- | ------ |
507 | `question` field (for example, `"How should I format the output?"`) | Key |
508 | Selected option's `label` field (for example, `"Summary"`) | Value |
505 | From the question object | Use as |
506 | - | - |
507 | `question` field (for example, `"How should I format the output?"`) | Key |
508 | Selected option's `label` field (for example, `"Summary"`) | Value |
509509 
510510 For multi-select questions, pass an array of labels or join them with `", "`. If you [support free-text input](#support-free-text-input), use the user's custom text as the value.
511511 
from line 542
542542 
543543The input contains Claude's generated questions in a `questions` array. Each question has these fields:
544544 
545| Field | Description |
546| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
547| `question` | The full question text to display |
548| `header` | Short label for the question (max 12 characters) |
549| `options` | Array of 2-4 choices, each with `label` and `description`. TypeScript: optionally `preview`. See [Option previews](#option-previews-typescript). |
550| `multiSelect` | If `true`, users can select multiple options |
545| Field | Description |
546| - | - |
547| `question` | The full question text to display |
548| `header` | Short label for the question (max 12 characters) |
549| `options` | Array of 2-4 choices, each with `label` and `description`. TypeScript: optionally `preview`. See [Option previews](#option-previews-typescript). |
550| `multiSelect` | If `true`, users can select multiple options |
551551 
552552The structure your callback receives:
553553 
from line 571
571571 
572572`toolConfig.askUserQuestion.previewFormat` adds a `preview` field to each option so your app can show a visual mockup alongside the label. Without this setting, Claude does not generate previews and the field is absent.
573573 
574| `previewFormat` | `preview` contains |
575| :-------------- | :------------------------------------------------------------------------------------------------------------ |
576| unset (default) | Field is absent. Claude does not generate previews. |
577| `"markdown"` | ASCII art and fenced code blocks |
578| `"html"` | A styled `<div>` fragment (the SDK rejects `<script>`, `<style>`, and `<!DOCTYPE>` before your callback runs) |
574| `previewFormat` | `preview` contains |
575| :- | :- |
576| unset (default) | Field is absent. Claude does not generate previews. |
577| `"markdown"` | ASCII art and fenced code blocks |
578| `"html"` | A styled `<div>` fragment (the SDK rejects `<script>`, `<style>`, and `<!DOCTYPE>` before your callback runs) |
579579 
580580The format applies to all questions in the session. Claude includes `preview` on options where a visual comparison helps (layout choices, color schemes) and omits it where one wouldn't (yes/no confirmations, text-only choices). Check for `undefined` before rendering.
581581 
from line 612
612612 
613613Return an `answers` object mapping each question's `question` field to the selected option's `label`:
614614 
615| Field | Description |
616| ----------- | ------------------------------------------------------------------------------------ |
617| `questions` | Pass through the original questions array (required for tool processing) |
618| `answers` | Object where keys are question text and values are selected labels |
619| `response` | Optional freeform reply the user typed instead of answering the structured questions |
615| Field | Description |
616| - | - |
617| `questions` | Pass through the original questions array (required for tool processing) |
618| `answers` | Object where keys are question text and values are selected labels |
619| `response` | Optional freeform reply the user typed instead of answering the structured questions |
620620 
621621For multi-select questions, pass an array of labels or join them with `", "`. For per-question free text such as an "Other" option, put the user's text in `answers[question]` as shown in [Support free-text input](#support-free-text-input). Set `response` only when your UI lets the user dismiss the question card and type a general reply that isn't an answer to any specific question. When `response` is set, Claude receives "The user responded: …" instead of the per-question answer list.
622622 

agent-teams Changed · +12 / -12 lines

from line 31
3131 <img src="https://mintcdn.com/claude-code/nsvRFSDNfpSU5nT7/images/subagents-vs-agent-teams-dark.png?fit=max&auto=format&n=nsvRFSDNfpSU5nT7&q=85&s=d573a037540f2ada6a9ae7d8285b46fd" className="hidden dark:block" alt="Diagram comparing subagent and agent team architectures. Subagents are spawned by the main agent, do work, and report results back. Agent teams coordinate through a shared task list, with teammates communicating directly with each other." width="4245" height="1615" data-path="images/subagents-vs-agent-teams-dark.png" />
3232</Frame>
3333 
34| | Subagents | Agent teams |
35| :---------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------- |
36| **Context** | Own context window; results return to the caller | Own context window; fully independent |
37| **Communication** | Return a result to the caller. Subagents that Claude named when it spawned them can also [message each other](/docs/en/sub-agents#what-loads-at-startup) | Teammates message each other directly |
38| **Coordination** | Main agent manages all work | Self-coordination through messages, plus a shared task list for [agents that have the Task tools](/docs/en/tools-reference#task-tool-availability) |
39| **Best for** | Focused tasks where only the result matters | Complex work requiring discussion and collaboration |
40| **Token cost** | Lower: results summarized back to main context | Higher: each teammate is a separate Claude instance |
34| | Subagents | Agent teams |
35| :- | :- | :- |
36| **Context** | Own context window; results return to the caller | Own context window; fully independent |
37| **Communication** | Return a result to the caller. Subagents that Claude named when it spawned them can also [message each other](/docs/en/sub-agents#what-loads-at-startup) | Teammates message each other directly |
38| **Coordination** | Main agent manages all work | Self-coordination through messages, plus a shared task list for [agents that have the Task tools](/docs/en/tools-reference#task-tool-availability) |
39| **Best for** | Focused tasks where only the result matters | Complex work requiring discussion and collaboration |
40| **Token cost** | Lower: results summarized back to main context | Higher: each teammate is a separate Claude instance |
4141 
4242Use subagents when you need quick, focused workers that report back. Use agent teams when teammates need to share findings, challenge each other, and coordinate on their own.
4343 
from line 224
224224 
225225An agent team consists of:
226226 
227| Component | Role |
228| :------------ | :---------------------------------------------------------------------- |
227| Component | Role |
228| :- | :- |
229229| **Team lead** | The main Claude Code session that spawns teammates and coordinates work |
230| **Teammates** | Separate Claude Code instances that each work on assigned tasks |
231| **Task list** | Shared list of work items that teammates claim and complete |
232| **Mailbox** | Messaging system for communication between agents |
230| **Teammates** | Separate Claude Code instances that each work on assigned tasks |
231| **Task list** | Shared list of work items that teammates claim and complete |
232| **Mailbox** | Messaging system for communication between agents |
233233 
234234Each agent's mailbox is a JSON file at `~/.claude/teams/{team-name}/inboxes/{agent-name}.json`. Claude Code validates every entry when it reads a mailbox file. Entries that don't match the message format are reported as errors and removed from the file; the valid messages are still delivered. Before v2.1.207, a single malformed mailbox entry caused a repeated error every second and blocked delivery for that mailbox until you deleted the file manually.
235235 

agent-view Changed · +165 / -165 lines

This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.

from line 102
102102 
103103Each row starts with an icon whose color and animation show the session's state:
104104 
105| State | Icon shows as | What it means |
106| :---------- | :------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
107| Working | Animated | Claude is actively running tools or generating a response |
108| Needs input | Yellow | Claude is waiting on something only you can provide: an answer to a question, a permission decision, or another prompt only you can answer, such as a [sandbox](/docs/en/sandboxing) prompt to allow a network host or an MCP server's [request for input](/docs/en/mcp#respond-to-mcp-elicitation-requests). A command that needs an attached terminal, such as `/install-github-app` or the `/mcp` settings list, [holds an unattended session here too](#attach-to-a-session) |
109| Idle | Dimmed | The session has nothing to do and is ready for your next prompt |
110| Completed | Green | The task finished successfully |
111| Failed | Red | The task ended with an error |
112| Stopped | Grey | You stopped the session with `Ctrl+X` or `claude stop`, [its process was ended from outside Claude Code](#the-supervisor-process), or [it ended while the background service was off](#sessions-show-as-failed-after-shutdown) |
105| State | Icon shows as | What it means |
106| :- | :- | :- |
107| Working | Animated | Claude is actively running tools or generating a response |
108| Needs input | Yellow | Claude is waiting on something only you can provide: an answer to a question, a permission decision, or another prompt only you can answer, such as a [sandbox](/docs/en/sandboxing) prompt to allow a network host or an MCP server's [request for input](/docs/en/mcp#respond-to-mcp-elicitation-requests). A command that needs an attached terminal, such as `/install-github-app` or the `/mcp` settings list, [holds an unattended session here too](#attach-to-a-session) |
109| Idle | Dimmed | The session has nothing to do and is ready for your next prompt |
110| Completed | Green | The task finished successfully |
111| Failed | Red | The task ended with an error |
112| Stopped | Grey | You stopped the session with `Ctrl+X` or `claude stop`, [its process was ended from outside Claude Code](#the-supervisor-process), or [it ended while the background service was off](#sessions-show-as-failed-after-shutdown) |
113113 
114114Separately, the icon's shape shows whether the underlying process is running:
115115 
116| Shape | What it means |
117| :------------------ | :-------------------------------------------------------------------------------------------------------------------------- |
118| `✻` or animated `✽` | The session process is alive and replies immediately |
119| `∙` | The process has exited. You can still peek at the row, and when you reply or attach, Claude restarts from where it left off |
120| `✢` | A [`/loop`](/docs/en/scheduled-tasks) session sleeping between iterations. The row shows its run count and a countdown |
116| Shape | What it means |
117| :- | :- |
118| `✻` or animated `✽` | The session process is alive and replies immediately |
119| `∙` | The process has exited. You can still peek at the row, and when you reply or attach, Claude restarts from where it left off |
120| `✢` | A [`/loop`](/docs/en/scheduled-tasks) session sleeping between iterations. The row shows its run count and a countdown |
121121 
122122The `#N` or `!N` label that can appear at the right edge of a row is a link to the session's [pull request or merge request](#pull-request-status), not part of the state icon.
123123 
from line 161
161161 
162162The pull request number is colored by its status:
163163 
164| Color | Pull request status |
165| :----- | :-------------------------------------------- |
164| Color | Pull request status |
165| :- | :- |
166166| Yellow | Waiting on checks or review, or checks failed |
167| Green | Checks passed and no review is blocking |
168| Purple | Merged |
169| Grey | Draft or closed |
167| Green | Checks passed and no review is blocking |
168| Purple | Merged |
169| Grey | Draft or closed |
170170 
171171For a task that ends in a pull request, check this label for the result: review and merge the pull request when its number turns green.
172172 
from line 276
276276 
277277Type in the dispatch input to filter instead of dispatching:
278278 
279| Filter | Shows |
280| :----------------------------------------- | :------------------------------------------------------------------------------------------------------- |
281| `a:<name>` | Sessions running the named agent |
282| `s:<state>` | Sessions in the given state, such as `s:working`. Also accepts `s:blocked` for everything waiting on you |
283| `#<number>` or a pull or merge request URL | The session working on that pull request or merge request |
284| Any other URL | The session whose first prompt contained that URL |
279| Filter | Shows |
280| :- | :- |
281| `a:<name>` | Sessions running the named agent |
282| `s:<state>` | Sessions in the given state, such as `s:working`. Also accepts `s:blocked` for everything waiting on you |
283| `#<number>` or a pull or merge request URL | The session working on that pull request or merge request |
284| Any other URL | The session whose first prompt contained that URL |
285285 
286286### Keyboard shortcuts
287287 
288288Press `?` in agent view to see every shortcut in context. The table below summarizes them.
289289 
290| Shortcut | Action |
291| :-------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
292| `↑` / `↓` | Move between rows |
293| `Enter` | Attach to the selected session, or dispatch if there's text in the input |
294| `Space` | Open or close the peek panel for the selected session |
295| `Shift+Enter` | Insert a newline in the dispatch input, [as in the main prompt](/docs/en/terminal-config#enter-multiline-prompts) |
296| `Ctrl+Enter` | Dispatch and attach immediately, in terminals where the `?` overlay lists `ctrl+enter to start and open` |
297| `→` | Attach to the selected session |
298| `Alt+1`..`Alt+9` | Attach to session 1–9 in the focused session's directory |
299| `Tab` | On an empty input, browse all subagents. Otherwise apply the highlighted suggestion |
300| `Ctrl+S` | Switch grouping between state and directory |
301| `Ctrl+T` | Pin or unpin the selected session |
302| `Ctrl+R` | Rename the selected session |
303| `Ctrl+G` | Open the dispatch prompt in your `$VISUAL` or `$EDITOR` |
304| `Ctrl+J` | Insert a newline in the dispatch input |
305| `Ctrl+X` | Stop the session; press again within two seconds to delete it |
306| `Shift+↑` / `Shift+↓` | Reorder the selected session |
307| `Esc` | Close the peek panel, clear the input, or exit. When you opened agent view by backgrounding your session with `←`, the final `Esc` returns to that conversation instead of exiting. With [vim editor mode](/docs/en/interactive-mode#vim-editor-mode) on, pressing `Esc` in the input switches from INSERT to NORMAL mode and keeps your text, as in the main prompt |
308| `Ctrl+C` | Clear the input; press twice to exit |
309| `?` | Show all shortcuts |
290| Shortcut | Action |
291| :- | :- |
292| `↑` / `↓` | Move between rows |
293| `Enter` | Attach to the selected session, or dispatch if there's text in the input |
294| `Space` | Open or close the peek panel for the selected session |
295| `Shift+Enter` | Insert a newline in the dispatch input, [as in the main prompt](/docs/en/terminal-config#enter-multiline-prompts) |
296| `Ctrl+Enter` | Dispatch and attach immediately, in terminals where the `?` overlay lists `ctrl+enter to start and open` |
297| `→` | Attach to the selected session |
298| `Alt+1`..`Alt+9` | Attach to session 1–9 in the focused session's directory |
299| `Tab` | On an empty input, browse all subagents. Otherwise apply the highlighted suggestion |
300| `Ctrl+S` | Switch grouping between state and directory |
301| `Ctrl+T` | Pin or unpin the selected session |
302| `Ctrl+R` | Rename the selected session |
303| `Ctrl+G` | Open the dispatch prompt in your `$VISUAL` or `$EDITOR` |
304| `Ctrl+J` | Insert a newline in the dispatch input |
305| `Ctrl+X` | Stop the session; press again within two seconds to delete it |
306| `Shift+↑` / `Shift+↓` | Reorder the selected session |
307| `Esc` | Close the peek panel, clear the input, or exit. When you opened agent view by backgrounding your session with `←`, the final `Esc` returns to that conversation instead of exiting. With [vim editor mode](/docs/en/interactive-mode#vim-editor-mode) on, pressing `Esc` in the input switches from INSERT to NORMAL mode and keeps your text, as in the main prompt |
308| `Ctrl+C` | Clear the input; press twice to exit |
309| `?` | Show all shortcuts |
310310 
311311`Ctrl+S`, `Ctrl+T`, and `Ctrl+G` follow your [`keybindings.json`](/docs/en/keybindings). Rebind or unbind `Ctrl+S` and `Ctrl+T` with the `agents:switchView` and `agents:togglePin` actions in the [`Agents` context](/docs/en/keybindings#agents-actions), and `Ctrl+G` through the `Chat` context's `chat:externalEditor` binding. The other shortcuts in the table can't be rebound.
312312 
from line 326
326326 
327327Prefix or mention parts of the prompt to control how the session starts:
328328 
329| Input | Effect |
330| :----------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |
331| `<agent-name> <prompt>` | If the first word matches a custom [subagent](/docs/en/sub-agents) name, that subagent runs as the session's main agent with the configuration from its frontmatter |
332| `@<agent-name>` | Mention a custom subagent anywhere in the prompt to run it as the main agent |
333| `@<repo>` | Mention a repository to run the session there. See [Dispatch to a specific directory](#dispatch-to-a-specific-directory) for which repositories are listed |
334| `/<command>` | Suggest [skills](/docs/en/skills) and [commands](/docs/en/commands) to dispatch as the prompt |
335| `! <command>` | Run a shell command as a background job instead of starting a Claude session. The job appears as a row you can attach to, watch, and detach from |
336| `#<number>` or a pull or merge request URL | If a session is already working on that pull request or merge request, Claude Code selects its row instead of dispatching a new session |
329| Input | Effect |
330| :- | :- |
331| `<agent-name> <prompt>` | If the first word matches a custom [subagent](/docs/en/sub-agents) name, that subagent runs as the session's main agent with the configuration from its frontmatter |
332| `@<agent-name>` | Mention a custom subagent anywhere in the prompt to run it as the main agent |
333| `@<repo>` | Mention a repository to run the session there. See [Dispatch to a specific directory](#dispatch-to-a-specific-directory) for which repositories are listed |
334| `/<command>` | Suggest [skills](/docs/en/skills) and [commands](/docs/en/commands) to dispatch as the prompt |
335| `! <command>` | Run a shell command as a background job instead of starting a Claude session. The job appears as a row you can attach to, watch, and detach from |
336| `#<number>` or a pull or merge request URL | If a session is already working on that pull request or merge request, Claude Code selects its row instead of dispatching a new session |
337337 
338338A small set of commands run in agent view itself instead of dispatching:
339339 
from line 667
667667 
668668Agent view accepts the same configuration flags as `claude` for loading settings, plugins, MCP servers, and additional directories. Agent view applies `--settings`, `--setting-sources`, and `--plugin-dir` to itself and passes every configuration flag through to the sessions you dispatch from it, so a plugin or MCP server you load this way is available in those sessions.
669669 
670| Flag | Effect |
671| :----------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
672| [`--settings <file-or-json>`](/docs/en/settings) | Override settings for agent view and dispatched sessions |
673| [`--setting-sources <sources>`](/docs/en/cli-reference#cli-flags) | Load only the named settings sources, in agent view and dispatched sessions |
674| [`--add-dir <path>`](/docs/en/permissions#additional-directories-grant-file-access-not-configuration) | Grant file access to an additional directory |
675| [`--plugin-dir <path>`](/docs/en/plugins/create#load-a-directory-or-archive-for-one-session) | Load a plugin from a local directory |
676| [`--mcp-config <file-or-json>`](/docs/en/mcp) | Load MCP servers from a config file or JSON string |
677| `--strict-mcp-config` | Use only the MCP servers from `--mcp-config`, ignoring other MCP configuration. See [Exclusive control with managed-mcp.json](/docs/en/managed-mcp#exclusive-control-with-managed-mcp-json) for what the flag does under a managed MCP file |
670| Flag | Effect |
671| :- | :- |
672| [`--settings <file-or-json>`](/docs/en/settings) | Override settings for agent view and dispatched sessions |
673| [`--setting-sources <sources>`](/docs/en/cli-reference#cli-flags) | Load only the named settings sources, in agent view and dispatched sessions |
674| [`--add-dir <path>`](/docs/en/permissions#additional-directories-grant-file-access-not-configuration) | Grant file access to an additional directory |
675| [`--plugin-dir <path>`](/docs/en/plugins/create#load-a-directory-or-archive-for-one-session) | Load a plugin from a local directory |
676| [`--mcp-config <file-or-json>`](/docs/en/mcp) | Load MCP servers from a config file or JSON string |
677| `--strict-mcp-config` | Use only the MCP servers from `--mcp-config`, ignoring other MCP configuration. See [Exclusive control with managed-mcp.json](/docs/en/managed-mcp#exclusive-control-with-managed-mcp-json) for what the flag does under a managed MCP file |
678678 
679679Repeat `--add-dir`, `--plugin-dir`, or `--mcp-config` once per value. `claude agents` doesn't support the space-separated form, such as `--add-dir a b c`.
680680 
from line 692
692692 
693693Every background session has a short ID you can use from the shell. The ID is printed when you start a session with `claude --bg`, and each session's ID is its directory name under `~/.claude/jobs/`. These commands are useful for scripting or when you don't want to open agent view.
694694 
695| Command | Purpose |
696| :--------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
697| `claude agents` | Open agent view |
698| `claude agents --cwd <path>` | Open agent view scoped to sessions started under `<path>` |
699| `claude agents --json` | Print sessions as a JSON array and exit. See [List sessions as JSON](#list-sessions-as-json) |
700| `claude attach <id>` | Attach to a session in this terminal |
701| `claude logs <id>` | Print the session's recent output |
702| `claude stop <id>` | Stop a session. Also accepts `claude kill` |
703| `claude respawn <id>` | Restart a session, running or stopped, e.g. to pick up an updated Claude Code binary. The restarted session resumes its saved conversation; when none is on disk, it runs its original prompt again as a new conversation |
704| `claude respawn --all` | Restart every running session, e.g. to move all sessions onto an updated Claude Code binary at once |
705| `claude rm <id>` | Remove a session from the list, along with a worktree Claude created for it when that's safe to delete; see [What deleting a session removes](#what-deleting-a-session-removes). The conversation transcript stays on your local machine and remains available through `claude --resume` |
706| `claude rm <id> --discard-unpushed <commit>@<worktree-id>` | Delete a session whose delete was refused over unpushed commits, discarding the worktree along with its branch and commits. Pass the exact value that refusal printed; see [What deleting a session removes](#what-deleting-a-session-removes). Requires v2.1.260 or later |
707| `claude rm <id> --force-remove-worktree <worktree-id>` | Delete a session whose delete was refused because git or the `WorktreeRemove` hook couldn't remove its worktree, deleting the worktree directory anyway and leaving its branch in the repository. Pass the exact value that refusal printed; see [What deleting a session removes](#what-deleting-a-session-removes). Requires v2.1.268 or later |
708| `claude daemon status` | Print the [supervisor's](#the-supervisor-process) state, version, socket directory, and worker count |
709| `claude daemon stop --any` | Stop the supervisor process and the background sessions it hosts. Pass `--keep-workers` to leave background sessions running so the next supervisor reconnects to them. The next `claude agents` or `claude --bg` starts a fresh supervisor |
695| Command | Purpose |
696| :- | :- |
697| `claude agents` | Open agent view |
698| `claude agents --cwd <path>` | Open agent view scoped to sessions started under `<path>` |
699| `claude agents --json` | Print sessions as a JSON array and exit. See [List sessions as JSON](#list-sessions-as-json) |
700| `claude attach <id>` | Attach to a session in this terminal |
701| `claude logs <id>` | Print the session's recent output |
702| `claude stop <id>` | Stop a session. Also accepts `claude kill` |
703| `claude respawn <id>` | Restart a session, running or stopped, e.g. to pick up an updated Claude Code binary. The restarted session resumes its saved conversation; when none is on disk, it runs its original prompt again as a new conversation |
704| `claude respawn --all` | Restart every running session, e.g. to move all sessions onto an updated Claude Code binary at once |
705| `claude rm <id>` | Remove a session from the list, along with a worktree Claude created for it when that's safe to delete; see [What deleting a session removes](#what-deleting-a-session-removes). The conversation transcript stays on your local machine and remains available through `claude --resume` |
706| `claude rm <id> --discard-unpushed <commit>@<worktree-id>` | Delete a session whose delete was refused over unpushed commits, discarding the worktree along with its branch and commits. Pass the exact value that refusal printed; see [What deleting a session removes](#what-deleting-a-session-removes). Requires v2.1.260 or later |
707| `claude rm <id> --force-remove-worktree <worktree-id>` | Delete a session whose delete was refused because git or the `WorktreeRemove` hook couldn't remove its worktree, deleting the worktree directory anyway and leaving its branch in the repository. Pass the exact value that refusal printed; see [What deleting a session removes](#what-deleting-a-session-removes). Requires v2.1.268 or later |
708| `claude daemon status` | Print the [supervisor's](#the-supervisor-process) state, version, socket directory, and worker count |
709| `claude daemon stop --any` | Stop the supervisor process and the background sessions it hosts. Pass `--keep-workers` to leave background sessions running so the next supervisor reconnects to them. The next `claude agents` or `claude --bg` starts a fresh supervisor |
710710 
711711### List sessions as JSON
712712 
from line 714
714714 
715715Each entry describes one session:
716716 
717| Field | Present | Description |
718| :------------------------- | :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
719| `cwd`, `kind`, `startedAt` | Always | The working directory, `interactive` or `background`, and the start time in Unix milliseconds |
720| `id` | Background sessions | Short ID, usable with `claude attach`, `claude logs`, and `claude stop` |
721| `state` | Background sessions | One of `working`, `blocked`, `done`, `failed`, or `stopped`. See [Read session state from a script](#read-session-state-from-a-script) for what each value means |
722| `pid`, `status` | While the process is alive | Process ID and one of `busy`, `waiting`, or `idle` |
723| `waitingFor` | When `status` is `waiting` | What the session is blocked on: `permission prompt` for an approval, `input needed` for a question from Claude or an MCP server's input request, `sandbox request`, `worker request`, or `dialog open` |
724| `sessionId`, `name` | When set | `sessionId` is the full session UUID, usable with [`claude --resume`](/docs/en/sessions). An interactive session's `name` is its [default display name](/docs/en/sessions#name-your-sessions) until you name the session or accept a plan in it |
717| Field | Present | Description |
718| :- | :- | :- |
719| `cwd`, `kind`, `startedAt` | Always | The working directory, `interactive` or `background`, and the start time in Unix milliseconds |
720| `id` | Background sessions | Short ID, usable with `claude attach`, `claude logs`, and `claude stop` |
721| `state` | Background sessions | One of `working`, `blocked`, `done`, `failed`, or `stopped`. See [Read session state from a script](#read-session-state-from-a-script) for what each value means |
722| `pid`, `status` | While the process is alive | Process ID and one of `busy`, `waiting`, or `idle` |
723| `waitingFor` | When `status` is `waiting` | What the session is blocked on: `permission prompt` for an approval, `input needed` for a question from Claude or an MCP server's input request, `sandbox request`, `worker request`, or `dialog open` |
724| `sessionId`, `name` | When set | `sessionId` is the full session UUID, usable with [`claude --resume`](/docs/en/sessions). An interactive session's `name` is its [default display name](/docs/en/sessions#name-your-sessions) until you name the session or accept a plan in it |
725725 
726726### Read session state from a script
727727 
728728`claude agents --json` is the supported way to read session state from outside Claude Code, for example from a status bar, a scheduler, or another Claude session that supervises background work. Poll `claude agents --json --all`, which keeps listing sessions whose process has exited, and read each entry's `state`, `status`, and `waitingFor`.
729729 
730| `state` | What it means |
731| :------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
732| `working` | A turn is running, or the session is between steps of work it drives on its own, such as a [`/loop`](/docs/en/scheduled-tasks) iteration or a wait on CI. `status` tells you whether its process is `busy` right now |
733| `blocked` | The session is waiting on you: a question it asked, a permission or sandbox decision, an error only you can clear such as an expired login, or its first prompt if you started it without one. When the wait is an open prompt in a live process, `waitingFor` names it |
734| `done` | The last turn finished what you asked for and the session is ready for your next prompt, whether or not its process is still alive |
735| `failed`, `stopped` | The task ended with an error, or the session was stopped |
730| `state` | What it means |
731| :- | :- |
732| `working` | A turn is running, or the session is between steps of work it drives on its own, such as a [`/loop`](/docs/en/scheduled-tasks) iteration or a wait on CI. `status` tells you whether its process is `busy` right now |
733| `blocked` | The session is waiting on you: a question it asked, a permission or sandbox decision, an error only you can clear such as an expired login, or its first prompt if you started it without one. When the wait is an open prompt in a live process, `waitingFor` names it |
734| `done` | The last turn finished what you asked for and the session is ready for your next prompt, whether or not its process is still alive |
735| `failed`, `stopped` | The task ended with an error, or the session was stopped |
736736 
737737A session that finished its turn and is waiting for your next instruction reads `done`, not `blocked`. `blocked` always means the session needs something from you before it can continue.
738738 
from line 765
765765 
766766Session state is stored under your Claude Code config directory. If you set [`CLAUDE_CONFIG_DIR`](/docs/en/env-vars), the supervisor uses that directory instead of `~/.claude` and runs as a separate instance with its own sessions.
767767 
768| Path | Contents |
769| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------- |
770| `~/.claude/daemon.log` | Supervisor log |
771| `~/.claude/daemon/roster.json` | List of running background sessions, used to reconnect after a restart |
768| Path | Contents |
769| :- | :- |
770| `~/.claude/daemon.log` | Supervisor log |
771| `~/.claude/daemon/roster.json` | List of running background sessions, used to reconnect after a restart |
772772| `~/.claude/jobs/<id>/state.json` | Per-session state shown in agent view. Read it through [`claude agents --json`](#read-session-state-from-a-script) instead of parsing the file |
773| `~/.claude/jobs/<id>/tmp/` | Per-session scratch directory. Claude's `Write` and `Edit` calls here don't prompt for permission. Removed when the session is deleted |
773| `~/.claude/jobs/<id>/tmp/` | Per-session scratch directory. Claude's `Write` and `Edit` calls here don't prompt for permission. Removed when the session is deleted |
774774 
775775Each background session has the `CLAUDE_JOB_DIR` environment variable set to its `~/.claude/jobs/<id>` directory, so shell commands the session runs can write temporary files to `$CLAUDE_JOB_DIR/tmp` without colliding with parallel sessions.
776776 
from line 940
940940 
941941Agent view has evolved quickly during research preview. If you are on an older Claude Code version, some behavior on this page may differ; in particular, `claude agents` rejects flags it doesn't yet support with an `unknown option` error. The table below lists when each flag and behavior was added.
942942 
943| Version | Change |
944| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
945| v2.1.281 | A [`--setting-sources`](/docs/en/cli-reference#cli-flags) restriction [carries over](#what-carries-over-when-you-background) to a session you background with `←` or `/bg` and to the sessions you dispatch from agent view. Before this release, the spawned session loaded every settings source. |
946| v2.1.281 | `claude --bg`, and the commands that restart a session, check workspace trust for the session's directory first. From a terminal in that directory, [the trust dialog appears](#from-your-shell) if you haven't accepted it; where no dialog can appear, such as in a script, the command exits with a [`Workspace not trusted`](/docs/en/errors#workspace-not-trusted-when-dispatching-a-background-session) error. |
947| v2.1.274 | After an auto-update, an agent view you've been away from for about an hour can relaunch itself onto the new build. When it does, it keeps the [dispatch defaults](#dispatch-defaults) you opened it with: `--model`, `--effort`, `--permission-mode`, `--allow-dangerously-skip-permissions`, and `--agent`. Before this release, the relaunched view kept only `--cwd` and configuration flags such as `--settings` and `--mcp-config`, so sessions you dispatched afterward started without those defaults. |
948| v2.1.274 | When a [delete is refused](#what-deleting-a-session-removes) because git or your `WorktreeRemove` hook couldn't remove the worktree, a checked-out submodule that Claude Code verifies has no uncommitted changes to tracked files doesn't block the offer to delete again and remove the directory anyway. Uncommitted work inside a checked-out submodule counts as uncommitted changes, and the message names the submodule. Before this release, any submodule checkout in the worktree blocked the offer, with a message saying the worktree contains a nested repository. |
949| v2.1.268 | When a [delete is refused](#what-deleting-a-session-removes) because git or your `WorktreeRemove` hook couldn't remove the worktree, the message names the cause, including how a hook ended and the start of its stderr. For a linked worktree under the repository's `.claude/worktrees/` with no uncommitted changes to tracked files, no nested repository inside it, and no other session's record naming it, deleting the session again removes the directory anyway, from agent view or with `claude rm <id> --force-remove-worktree <worktree-id>`. Before this release, the row showed only `worktree could not be removed (WorktreeRemove hook failed)` or git's error, the hook's stderr went only to the debug log, and deleting again was refused the same way. |
950| v2.1.268 | After the first `←` shows `Press ← again to open agents`, or `Press ← again to go back to agents` in an attached session, [the first press that comes at least a second later switches](#switch-sessions-without-leaving-the-terminal), even when quicker presses in between were ignored. Before this release, each ignored press restarted the wait, so pressing `←` again at a steady pace didn't switch until you paused for over a second. |
951| v2.1.260 | When you [background a session](#from-inside-a-session), your other sessions' [agent listing](/docs/en/cross-session-messaging#see-which-sessions-claude-can-reach) shows the conversation once, as its background session, and their messages to it no longer reach the terminal you moved it from. Before this release, that terminal could stay listed as a second interactive session under the conversation's name, and a session that had messaged the conversation before the move kept delivering to that terminal. |
952| v2.1.260 | When a [delete is refused over unpushed commits](#what-deleting-a-session-removes), the message names the worktree's branch and how many commits are unpushed, and deleting the session again discards the worktree and its commits. Before this release, the refusal said only `worktree has commits that are not pushed anywhere`, deleting again was refused the same way, and deleting the session required pushing the commits or removing the worktree by hand. |
953| v2.1.257 | `←` [detaches from an attached session while the `/btw` overlay is open](#attach-to-a-session), even mid-answer, and the overlay reopens when you next attach. Before this release, `←` didn't detach while the overlay was open. |
954| v2.1.257 | When you run [`claude --resume <session-id> --bg`](#from-your-shell), Claude Code continues that session under its own ID, or starts a copy under a new ID and prints a `note:` line explaining why. `--continue`, a bare `--resume`, and `--resume` with a name or path start a copy with the same note. Before this release, `--resume` with `--bg` always started a copy under a new ID and said nothing. |
955| v2.1.257 | When you dispatch a session from an agent view you opened with `←`, Claude Code starts it in [the permission mode the target directory configures](#permission-mode) through `permissions.defaultMode`. When the directory doesn't set one, the permission mode of the session you came from applies. Before this release, the dispatched session always started in the permission mode of the session you came from, overriding it. |
956| v2.1.257 | `Ctrl+S`, `Ctrl+T`, and `Ctrl+G` in agent view [follow your `keybindings.json`](#keyboard-shortcuts): `Ctrl+S` and `Ctrl+T` through the `Agents` context's `agents:switchView` and `agents:togglePin` actions, and `Ctrl+G` through the `Chat` context's `chat:externalEditor` binding. Before this release, agent view ignored `keybindings.json` and these keys were fixed. |
957| v2.1.257 | Starting the [background service](#the-supervisor-process) recovers from two failure causes. On a macOS npm installation, a start during a self-update [waits for the install](/docs/en/errors#eacces-when-starting-a-background-session) instead of running the placeholder that npm lays down while replacing the binary. On Windows, a stale `daemon.lock` written before the machine last booted, or whose recorded process ID now belongs to a different process, is replaced. Before this release, the macOS start failed with `Error: claude native binary not installed.` during the install window, and the Windows lock made every start fail with [`exited before it became reachable`](/docs/en/errors#background-service-exited-before-it-became-reachable) until you deleted `~/.claude/daemon.lock`. |
958| v2.1.257 | When you open or dispatch a background session while another Claude Code process is downloading an npm update, Claude Code [keeps waiting up to two minutes](/docs/en/errors#eacces-when-starting-a-background-session) while the install runs, then fails saying `Claude Code is being updated by npm on this machine`. Before this release, the wait stopped at ten seconds, so the open failed with `Couldn't start the background service` while the download was still running. |
959| v2.1.257 | A background session holding a [cross-session message](/docs/en/cross-session-messaging#control-inbound-messages) for your approval shows `approve message from` on its `Needs input` row, with the sender's address and the name the sender claims. Before this release, the row moved to `Needs input` but kept its previous text, so nothing in `claude agents` named the waiting message or its sender. |
960| v2.1.257 | A prompt stashed with `Ctrl+S` inside an opened background session [is kept with the session](#what-persists-across-restarts), so `Ctrl+S` restores it after the session's process is stopped and started again. Before this release, the stash lived only in the running process and was lost when the session went idle long enough for its process to stop, or when it was stopped and then reopened. |
961| v2.1.251 | In a background session that hasn't [moved into a worktree](#how-file-edits-are-isolated), Claude and the subagents it spawns can edit files inside a linked git worktree. |
962| v2.1.251 | Claude Code forwards a cloud provider gateway exported in the shell you dispatch from, such as `ANTHROPIC_VERTEX_BASE_URL` or `ANTHROPIC_BEDROCK_BASE_URL` with its auth-bypass flag, to [the session's worker](#llm-gateway) under the same conditions as `ANTHROPIC_BASE_URL`. Before this release, if you backgrounded or dispatched from a shell authenticated only through such a gateway, every request the session made failed, because the endpoint and flag were dropped from its environment. |
963| v2.1.251 | When a background session starts while another Claude Code process is refreshing a [plugin marketplace](/docs/en/plugins/overview), such as a sibling session running the [marketplace auto-update](/docs/en/plugins/install#keep-plugins-updated), Claude Code keeps that marketplace's plugins available. Before this release, such a session could start without any of that marketplace's skills, agents, hooks, and MCP servers and stay that way for its whole run. |
964| v2.1.248 | `Shift+Enter` in the [dispatch input](#keyboard-shortcuts) inserts a newline, matching the main prompt, and `Ctrl+Enter` dispatches and attaches immediately in terminals where the `?` overlay lists `ctrl+enter to start and open`. Before this release, `Shift+Enter` dispatched and attached. |
965| v2.1.248 | [Deleting a session](#what-deleting-a-session-removes) succeeds when the worktree's commits are already on the local copy of your `origin` remote's default branch and your main checkout has that branch checked out; before this release, the delete was refused with `has commits that are not pushed anywhere`. |
966| v2.1.248 | A session backgrounded with `←` or `/background` holds the [`git worktree lock`](/docs/en/worktrees#clean-up-subagent-and-background-session-worktrees) on its worktree while it runs; before this release, backgrounding released the lock, and cleanup or `git worktree remove` could remove the worktree under the running session. |
967| v2.1.248 | A background session that wasn't waiting on your input and is found dead more than 48 hours after its last activity, such as after the machine was off for days, [shows as stopped](#sessions-show-as-failed-after-shutdown) with `ended while the background service was off`, and `Enter` on it asks before resuming its saved conversation. Before this release, such a session reappeared as a fresh failure sorted to the top of the list, and a single `Enter` pulled the weeks-old conversation into the foreground. |
968| v2.1.248 | Opening a stopped row whose conversation [you resumed in another terminal](#opening-a-session-says-the-conversation-is-already-open) is refused with `Can't open — this session is running in another terminal`, and the row shows `Open in a terminal` instead of showing under `Working`. Before this release, opening the row started a second process writing to the same conversation. |
969| v2.1.248 | A background session waiting on a permission decision while a `PermissionRequest` or `PreToolUse` hook printed an invalid answer [names the hook event and the schema error on its row](#peek-and-reply). Before this release, the row showed only the pending request. |
970| v2.1.248 | On Windows, `claude agents` responds to the keyboard when launched in a terminal tab that an earlier program left in win32-input-mode. Before this release, Claude Code didn't decode the key records such a tab sends. |
971| v2.1.247 | On Linux and WSL, a session [whose terminal host process died](#the-terminal-host-died-or-the-session-stopped-responding) fails within seconds with the reason. An open that produces no output ends after about ten seconds with a restart offer, and `Enter` on the row restarts the session with its conversation; `claude attach <id>` reports the cause and exits. Before this release, opening such a session showed `opening… · esc to cancel` indefinitely and `claude attach <id>` waited without reporting an error. |
972| v2.1.246 | On an npm installation, when the [background service](#the-supervisor-process) fails to start while `npm install -g @anthropic-ai/claude-code` is replacing the binary, Claude Code waits up to ten seconds for the install to finish and retries before reporting [`EACCES: permission denied`](/docs/en/errors#eacces-when-starting-a-background-session). |
973| v2.1.246 | When the [background service](#the-supervisor-process) process dies after printing an error, Claude Code reports the failure and [quotes the service's first error line](/docs/en/errors#background-service-exited-before-it-became-reachable). |
974| v2.1.246 | If your machine sleeps while the [background service](#the-supervisor-process) is starting, Claude Code retries the start once instead of failing. |
975| v2.1.246 | Claude Code waits about two minutes instead of 45 seconds for a newly started [background service](#the-supervisor-process) that is alive but slow to accept connections. |
976| v2.1.246 | The [background service](#the-supervisor-process) starts from your home directory, so on macOS and Linux a starting directory that was deleted or moved no longer blocks the start. |
977| v2.1.246 | `/fork` [copies the full conversation](#copy-the-session-with-%2Ffork) from a session that itself started as a copy and hasn't recorded a new prompt since: a `/fork` copy you attached to, a session reattached after `←` or `/background` moved it to the background, or a session started with `claude --resume <id> --fork-session`. Before this release, if you ran `/fork` in such a session before sending it a new prompt, Claude Code printed the normal confirmation but started the copy with an empty conversation. Moving such a session to the background with `←` or `/background` lost the conversation the same way. |
978| v2.1.246 | When you open a session you just dispatched while its worker process is still starting, such as by pressing `Enter` on its row, Claude Code waits for the process and then attaches. Before this release, if you pressed `Enter` while the process was still starting, Claude Code could stop the session with [`Session <id> was stopped while the respawn was in flight`](/docs/en/errors#session-was-stopped-while-the-respawn-was-in-flight). |
979| v2.1.246 | When you [background](#from-inside-a-session) a named session, Claude Code lists it once, and when you background the same conversation again, it numbers the new row's name, such as `my-session (2)`, with the existing row keeping its name. Before this release, the terminal you pressed `←` in could appear in `claude agents --json` as a second session under the same name, and if you backgrounded the same conversation again, Claude Code added another row under the identical name. |
980| v2.1.239 | With [vim editor mode](/docs/en/interactive-mode#vim-editor-mode) on, pressing `Esc` in agent view's input switches from INSERT to NORMAL mode and keeps your text, matching the main prompt; in NORMAL mode with text still in the input, pressing `Esc` clears it, and pressing `Esc` on an empty input exits, as the [`Esc` shortcut](#keyboard-shortcuts) describes. Before this release, `Esc` cleared the input. |
981| v2.1.233 | For a session linked to a GitLab merge request, Claude Code writes the row's label in GitLab's `!1234` reference syntax. You can also paste the merge request's URL into the [dispatch input](#filter-sessions) to select that session. Before this release, the label rendered as `#1234`, and a pasted merge request URL matched a session only when its first prompt contained the URL. |
982| v2.1.227 | [Deleting a session](#what-deleting-a-session-removes) keeps the session and its worktree while another live Claude Code session is running inside that worktree directory. Agent view shows `not deleted` on the row and the reason in the footer, and `claude rm` prints `kept <id>` with the reason, which names the other session's process ID. Before this release, deleting the session removed the worktree while the other session was still working in it. |
983| v2.1.225 | `claude agents` in a directory you haven't trusted shows the same [workspace trust dialog](/docs/en/permissions#project-allow-rules-and-workspace-trust) that `claude` shows on startup, before agent view opens. Accepting saves trust for that workspace; declining exits without opening agent view. Before this release, `claude agents` opened without asking, so sessions you dispatched from it ran in a directory you'd never been asked to trust.<br /><br />With the list grouped by directory, hovering the mouse over a row highlights it without changing the [dispatch target](#dispatch-to-a-specific-directory); selecting a row with the arrow keys or a click still changes the target. Before this release, moving the mouse over a session in another project silently changed the directory the next dispatched session started in. |
984| v2.1.221 | `/status` shows a `Session kind` row: `background job · attached` or `background job · unattended` in a background session, depending on whether a terminal is attached, and `interactive` in any other session. Before this release, `/status` didn't report the session kind.<br /><br />`/fork`: Claude Code instructs [the copy](#from-inside-a-session) to isolate its work from the original session's: the copy creates a worktree of its own before making code changes, stays out of the original session's worktree, and bases a new branch on the original's branch when its task builds on that work. See the linked section for the exact conditions. Before this release, the copy received no isolation instruction and could end up editing the worktree or checkout the original session was still working in.<br /><br />With [vim editor mode](/docs/en/interactive-mode#vim-editor-mode) on, pressing `←` right after undoing the prompt back to empty with `u` asks for the same confirmation as deleting the text or moving through prompt history, and switches only on the second press; before this release the press switched immediately. |
985| v2.1.219 | With [vim editor mode](/docs/en/interactive-mode#vim-editor-mode) on, pressing `←` on an empty prompt opens agent view from NORMAL mode as well as INSERT, and the footer's `←` hint shows in NORMAL mode; before this release the gesture and hint were INSERT-only, and in NORMAL mode `←` on an empty prompt did nothing. Typing into the input while Claude Code waits to background the session cancels the switch with `Backgrounding cancelled — you have unsent text in the input. Send it or clear it, then press ← again.` so a typed draft isn't lost. |
986| v2.1.218 | Pressing `←` within two seconds of a deletion that emptied the prompt, or of moving through prompt history, shows `Press ← again to open agents`, or `Press ← again to go back to agents` in an attached session, and switches only on a second press at least a second later; before this release the press switched immediately. A `←` that arrives inside pasted or scripted input no longer triggers the switch. Backgrounding a foreground session with `←` shows `Your conversation moved to the background` above the list, and `Esc` at the root of agent view returns to that conversation instead of exiting to the shell, with double `Ctrl+C` remaining the exit; if the conversation can't be reopened, Claude Code exits and prints a `claude --resume` command for it. On Windows, a `←` pressed within about half a second of attaching shows `Ambiguous ←, press again to detach` and detaches on the second press. |
987| v2.1.217 | The pull request badge on a session's row renders as a hyperlink even when Claude Code can't detect terminal hyperlink support, for example over SSH or tmux; set [`FORCE_HYPERLINK=0`](/docs/en/env-vars) to render it as plain text. Before this release, the badge rendered as plain text when support wasn't detected. |
988| v2.1.216 | `/fork`: the [confirmation](#from-inside-a-session) is one line, showing the copy's state, the name of its agent-view row, and its session ID for `claude attach`, ending with `runs in the origin tree` or `edits this checkout` only when the copy runs in the main working tree or edits the checkout you have open. Clicking the name backgrounds this session and opens agent view in the copy's session. The confirmation no longer restates the copy's inherited permission mode; earlier versions printed a multi-line confirmation with no clickable name.<br /><br />Needs input: `/install-github-app` and the `/mcp` settings list, run while nobody is attached, show the session under `Needs input` with a row naming the command, and attaching and re-running the command continues; from v2.1.208 through v2.1.215 they were refused outright in that state.<br /><br />`--agent` restore: resuming or restarting a [backgrounded `--agent` session](#from-your-shell) restores the agent's system prompt and tool restrictions, searching the session's own directory for the agent first, when its workspace is trusted; a session whose agent no longer exists continues with the default tools and system prompt and opens with a visible warning, instead of silently reverting to the default agent.<br /><br />`Ctrl+X`: pressing it twice deletes a session even when the stop attempt fails, instead of a failed stop cancelling the pending delete, and a deleted session whose worker process had died no longer reappears on the next refresh.<br /><br />Worktree deletion: a session whose worktree directory belongs to no git repository can be deleted; before this release every attempt to delete such a session was refused. A directory that's already gone clears immediately. The agent view double-press removes a directory that still has files, running your `WorktreeRemove` hook for a hook-created directory, unless another session's records also name it. `claude rm` keeps such a directory whenever files remain. |
989| v2.1.214 | A session backgrounded with `←` or `/background` and left idle with nothing running has its process stopped like any other idle session, instead of keeping its process and the background service running indefinitely. A completed session can be removed with `claude rm` or from agent view after the background service has gone idle, and a session that entered a worktree after being dispatched from a directory that isn't a git repository, such as a multi-repo workspace folder, can be deleted from agent view when the worktree itself belongs to a git repository, because the cleanup is resolved from the worktree instead of the directory the session was dispatched from; both removals were refused on every attempt before. Reopening a stopped session restores its saved conversation even when a folder in the transcript store can't be read. |
990| v2.1.213 | `/install-github-app`, the [`/mcp`](/docs/en/mcp) settings list, and MCP authentication actions work in a background session while a terminal is attached, and are refused only when nobody is attached, with a message telling you to attach and run the command again; from v2.1.208 through v2.1.212 they were refused even with a terminal attached. |
943| Version | Change |
944| - | - |
945| v2.1.281 | A [`--setting-sources`](/docs/en/cli-reference#cli-flags) restriction [carries over](#what-carries-over-when-you-background) to a session you background with `←` or `/bg` and to the sessions you dispatch from agent view. Before this release, the spawned session loaded every settings source. |
946| v2.1.281 | `claude --bg`, and the commands that restart a session, check workspace trust for the session's directory first. From a terminal in that directory, [the trust dialog appears](#from-your-shell) if you haven't accepted it; where no dialog can appear, such as in a script, the command exits with a [`Workspace not trusted`](/docs/en/errors#workspace-not-trusted-when-dispatching-a-background-session) error. |
947| v2.1.274 | After an auto-update, an agent view you've been away from for about an hour can relaunch itself onto the new build. When it does, it keeps the [dispatch defaults](#dispatch-defaults) you opened it with: `--model`, `--effort`, `--permission-mode`, `--allow-dangerously-skip-permissions`, and `--agent`. Before this release, the relaunched view kept only `--cwd` and configuration flags such as `--settings` and `--mcp-config`, so sessions you dispatched afterward started without those defaults. |
948| v2.1.274 | When a [delete is refused](#what-deleting-a-session-removes) because git or your `WorktreeRemove` hook couldn't remove the worktree, a checked-out submodule that Claude Code verifies has no uncommitted changes to tracked files doesn't block the offer to delete again and remove the directory anyway. Uncommitted work inside a checked-out submodule counts as uncommitted changes, and the message names the submodule. Before this release, any submodule checkout in the worktree blocked the offer, with a message saying the worktree contains a nested repository. |
949| v2.1.268 | When a [delete is refused](#what-deleting-a-session-removes) because git or your `WorktreeRemove` hook couldn't remove the worktree, the message names the cause, including how a hook ended and the start of its stderr. For a linked worktree under the repository's `.claude/worktrees/` with no uncommitted changes to tracked files, no nested repository inside it, and no other session's record naming it, deleting the session again removes the directory anyway, from agent view or with `claude rm <id> --force-remove-worktree <worktree-id>`. Before this release, the row showed only `worktree could not be removed (WorktreeRemove hook failed)` or git's error, the hook's stderr went only to the debug log, and deleting again was refused the same way. |
950| v2.1.268 | After the first `←` shows `Press ← again to open agents`, or `Press ← again to go back to agents` in an attached session, [the first press that comes at least a second later switches](#switch-sessions-without-leaving-the-terminal), even when quicker presses in between were ignored. Before this release, each ignored press restarted the wait, so pressing `←` again at a steady pace didn't switch until you paused for over a second. |
951| v2.1.260 | When you [background a session](#from-inside-a-session), your other sessions' [agent listing](/docs/en/cross-session-messaging#see-which-sessions-claude-can-reach) shows the conversation once, as its background session, and their messages to it no longer reach the terminal you moved it from. Before this release, that terminal could stay listed as a second interactive session under the conversation's name, and a session that had messaged the conversation before the move kept delivering to that terminal. |
952| v2.1.260 | When a [delete is refused over unpushed commits](#what-deleting-a-session-removes), the message names the worktree's branch and how many commits are unpushed, and deleting the session again discards the worktree and its commits. Before this release, the refusal said only `worktree has commits that are not pushed anywhere`, deleting again was refused the same way, and deleting the session required pushing the commits or removing the worktree by hand. |
953| v2.1.257 | `←` [detaches from an attached session while the `/btw` overlay is open](#attach-to-a-session), even mid-answer, and the overlay reopens when you next attach. Before this release, `←` didn't detach while the overlay was open. |
954| v2.1.257 | When you run [`claude --resume <session-id> --bg`](#from-your-shell), Claude Code continues that session under its own ID, or starts a copy under a new ID and prints a `note:` line explaining why. `--continue`, a bare `--resume`, and `--resume` with a name or path start a copy with the same note. Before this release, `--resume` with `--bg` always started a copy under a new ID and said nothing. |
955| v2.1.257 | When you dispatch a session from an agent view you opened with `←`, Claude Code starts it in [the permission mode the target directory configures](#permission-mode) through `permissions.defaultMode`. When the directory doesn't set one, the permission mode of the session you came from applies. Before this release, the dispatched session always started in the permission mode of the session you came from, overriding it. |
956| v2.1.257 | `Ctrl+S`, `Ctrl+T`, and `Ctrl+G` in agent view [follow your `keybindings.json`](#keyboard-shortcuts): `Ctrl+S` and `Ctrl+T` through the `Agents` context's `agents:switchView` and `agents:togglePin` actions, and `Ctrl+G` through the `Chat` context's `chat:externalEditor` binding. Before this release, agent view ignored `keybindings.json` and these keys were fixed. |
957| v2.1.257 | Starting the [background service](#the-supervisor-process) recovers from two failure causes. On a macOS npm installation, a start during a self-update [waits for the install](/docs/en/errors#eacces-when-starting-a-background-session) instead of running the placeholder that npm lays down while replacing the binary. On Windows, a stale `daemon.lock` written before the machine last booted, or whose recorded process ID now belongs to a different process, is replaced. Before this release, the macOS start failed with `Error: claude native binary not installed.` during the install window, and the Windows lock made every start fail with [`exited before it became reachable`](/docs/en/errors#background-service-exited-before-it-became-reachable) until you deleted `~/.claude/daemon.lock`. |
958| v2.1.257 | When you open or dispatch a background session while another Claude Code process is downloading an npm update, Claude Code [keeps waiting up to two minutes](/docs/en/errors#eacces-when-starting-a-background-session) while the install runs, then fails saying `Claude Code is being updated by npm on this machine`. Before this release, the wait stopped at ten seconds, so the open failed with `Couldn't start the background service` while the download was still running. |
959| v2.1.257 | A background session holding a [cross-session message](/docs/en/cross-session-messaging#control-inbound-messages) for your approval shows `approve message from` on its `Needs input` row, with the sender's address and the name the sender claims. Before this release, the row moved to `Needs input` but kept its previous text, so nothing in `claude agents` named the waiting message or its sender. |
960| v2.1.257 | A prompt stashed with `Ctrl+S` inside an opened background session [is kept with the session](#what-persists-across-restarts), so `Ctrl+S` restores it after the session's process is stopped and started again. Before this release, the stash lived only in the running process and was lost when the session went idle long enough for its process to stop, or when it was stopped and then reopened. |
961| v2.1.251 | In a background session that hasn't [moved into a worktree](#how-file-edits-are-isolated), Claude and the subagents it spawns can edit files inside a linked git worktree. |
962| v2.1.251 | Claude Code forwards a cloud provider gateway exported in the shell you dispatch from, such as `ANTHROPIC_VERTEX_BASE_URL` or `ANTHROPIC_BEDROCK_BASE_URL` with its auth-bypass flag, to [the session's worker](#llm-gateway) under the same conditions as `ANTHROPIC_BASE_URL`. Before this release, if you backgrounded or dispatched from a shell authenticated only through such a gateway, every request the session made failed, because the endpoint and flag were dropped from its environment. |
963| v2.1.251 | When a background session starts while another Claude Code process is refreshing a [plugin marketplace](/docs/en/plugins/overview), such as a sibling session running the [marketplace auto-update](/docs/en/plugins/install#keep-plugins-updated), Claude Code keeps that marketplace's plugins available. Before this release, such a session could start without any of that marketplace's skills, agents, hooks, and MCP servers and stay that way for its whole run. |
964| v2.1.248 | `Shift+Enter` in the [dispatch input](#keyboard-shortcuts) inserts a newline, matching the main prompt, and `Ctrl+Enter` dispatches and attaches immediately in terminals where the `?` overlay lists `ctrl+enter to start and open`. Before this release, `Shift+Enter` dispatched and attached. |
965| v2.1.248 | [Deleting a session](#what-deleting-a-session-removes) succeeds when the worktree's commits are already on the local copy of your `origin` remote's default branch and your main checkout has that branch checked out; before this release, the delete was refused with `has commits that are not pushed anywhere`. |
966| v2.1.248 | A session backgrounded with `←` or `/background` holds the [`git worktree lock`](/docs/en/worktrees#clean-up-subagent-and-background-session-worktrees) on its worktree while it runs; before this release, backgrounding released the lock, and cleanup or `git worktree remove` could remove the worktree under the running session. |
967| v2.1.248 | A background session that wasn't waiting on your input and is found dead more than 48 hours after its last activity, such as after the machine was off for days, [shows as stopped](#sessions-show-as-failed-after-shutdown) with `ended while the background service was off`, and `Enter` on it asks before resuming its saved conversation. Before this release, such a session reappeared as a fresh failure sorted to the top of the list, and a single `Enter` pulled the weeks-old conversation into the foreground. |
968| v2.1.248 | Opening a stopped row whose conversation [you resumed in another terminal](#opening-a-session-says-the-conversation-is-already-open) is refused with `Can't open — this session is running in another terminal`, and the row shows `Open in a terminal` instead of showing under `Working`. Before this release, opening the row started a second process writing to the same conversation. |
969| v2.1.248 | A background session waiting on a permission decision while a `PermissionRequest` or `PreToolUse` hook printed an invalid answer [names the hook event and the schema error on its row](#peek-and-reply). Before this release, the row showed only the pending request. |
970| v2.1.248 | On Windows, `claude agents` responds to the keyboard when launched in a terminal tab that an earlier program left in win32-input-mode. Before this release, Claude Code didn't decode the key records such a tab sends. |
971| v2.1.247 | On Linux and WSL, a session [whose terminal host process died](#the-terminal-host-died-or-the-session-stopped-responding) fails within seconds with the reason. An open that produces no output ends after about ten seconds with a restart offer, and `Enter` on the row restarts the session with its conversation; `claude attach <id>` reports the cause and exits. Before this release, opening such a session showed `opening… · esc to cancel` indefinitely and `claude attach <id>` waited without reporting an error. |
972| v2.1.246 | On an npm installation, when the [background service](#the-supervisor-process) fails to start while `npm install -g @anthropic-ai/claude-code` is replacing the binary, Claude Code waits up to ten seconds for the install to finish and retries before reporting [`EACCES: permission denied`](/docs/en/errors#eacces-when-starting-a-background-session). |
973| v2.1.246 | When the [background service](#the-supervisor-process) process dies after printing an error, Claude Code reports the failure and [quotes the service's first error line](/docs/en/errors#background-service-exited-before-it-became-reachable). |
974| v2.1.246 | If your machine sleeps while the [background service](#the-supervisor-process) is starting, Claude Code retries the start once instead of failing. |
975| v2.1.246 | Claude Code waits about two minutes instead of 45 seconds for a newly started [background service](#the-supervisor-process) that is alive but slow to accept connections. |
976| v2.1.246 | The [background service](#the-supervisor-process) starts from your home directory, so on macOS and Linux a starting directory that was deleted or moved no longer blocks the start. |
977| v2.1.246 | `/fork` [copies the full conversation](#copy-the-session-with-%2Ffork) from a session that itself started as a copy and hasn't recorded a new prompt since: a `/fork` copy you attached to, a session reattached after `←` or `/background` moved it to the background, or a session started with `claude --resume <id> --fork-session`. Before this release, if you ran `/fork` in such a session before sending it a new prompt, Claude Code printed the normal confirmation but started the copy with an empty conversation. Moving such a session to the background with `←` or `/background` lost the conversation the same way. |
978| v2.1.246 | When you open a session you just dispatched while its worker process is still starting, such as by pressing `Enter` on its row, Claude Code waits for the process and then attaches. Before this release, if you pressed `Enter` while the process was still starting, Claude Code could stop the session with [`Session <id> was stopped while the respawn was in flight`](/docs/en/errors#session-was-stopped-while-the-respawn-was-in-flight). |
979| v2.1.246 | When you [background](#from-inside-a-session) a named session, Claude Code lists it once, and when you background the same conversation again, it numbers the new row's name, such as `my-session (2)`, with the existing row keeping its name. Before this release, the terminal you pressed `←` in could appear in `claude agents --json` as a second session under the same name, and if you backgrounded the same conversation again, Claude Code added another row under the identical name. |
980| v2.1.239 | With [vim editor mode](/docs/en/interactive-mode#vim-editor-mode) on, pressing `Esc` in agent view's input switches from INSERT to NORMAL mode and keeps your text, matching the main prompt; in NORMAL mode with text still in the input, pressing `Esc` clears it, and pressing `Esc` on an empty input exits, as the [`Esc` shortcut](#keyboard-shortcuts) describes. Before this release, `Esc` cleared the input. |
981| v2.1.233 | For a session linked to a GitLab merge request, Claude Code writes the row's label in GitLab's `!1234` reference syntax. You can also paste the merge request's URL into the [dispatch input](#filter-sessions) to select that session. Before this release, the label rendered as `#1234`, and a pasted merge request URL matched a session only when its first prompt contained the URL. |
982| v2.1.227 | [Deleting a session](#what-deleting-a-session-removes) keeps the session and its worktree while another live Claude Code session is running inside that worktree directory. Agent view shows `not deleted` on the row and the reason in the footer, and `claude rm` prints `kept <id>` with the reason, which names the other session's process ID. Before this release, deleting the session removed the worktree while the other session was still working in it. |
983| v2.1.225 | `claude agents` in a directory you haven't trusted shows the same [workspace trust dialog](/docs/en/permissions#project-allow-rules-and-workspace-trust) that `claude` shows on startup, before agent view opens. Accepting saves trust for that workspace; declining exits without opening agent view. Before this release, `claude agents` opened without asking, so sessions you dispatched from it ran in a directory you'd never been asked to trust.<br /><br />With the list grouped by directory, hovering the mouse over a row highlights it without changing the [dispatch target](#dispatch-to-a-specific-directory); selecting a row with the arrow keys or a click still changes the target. Before this release, moving the mouse over a session in another project silently changed the directory the next dispatched session started in. |
984| v2.1.221 | `/status` shows a `Session kind` row: `background job · attached` or `background job · unattended` in a background session, depending on whether a terminal is attached, and `interactive` in any other session. Before this release, `/status` didn't report the session kind.<br /><br />`/fork`: Claude Code instructs [the copy](#from-inside-a-session) to isolate its work from the original session's: the copy creates a worktree of its own before making code changes, stays out of the original session's worktree, and bases a new branch on the original's branch when its task builds on that work. See the linked section for the exact conditions. Before this release, the copy received no isolation instruction and could end up editing the worktree or checkout the original session was still working in.<br /><br />With [vim editor mode](/docs/en/interactive-mode#vim-editor-mode) on, pressing `←` right after undoing the prompt back to empty with `u` asks for the same confirmation as deleting the text or moving through prompt history, and switches only on the second press; before this release the press switched immediately. |
985| v2.1.219 | With [vim editor mode](/docs/en/interactive-mode#vim-editor-mode) on, pressing `←` on an empty prompt opens agent view from NORMAL mode as well as INSERT, and the footer's `←` hint shows in NORMAL mode; before this release the gesture and hint were INSERT-only, and in NORMAL mode `←` on an empty prompt did nothing. Typing into the input while Claude Code waits to background the session cancels the switch with `Backgrounding cancelled — you have unsent text in the input. Send it or clear it, then press ← again.` so a typed draft isn't lost. |
986| v2.1.218 | Pressing `←` within two seconds of a deletion that emptied the prompt, or of moving through prompt history, shows `Press ← again to open agents`, or `Press ← again to go back to agents` in an attached session, and switches only on a second press at least a second later; before this release the press switched immediately. A `←` that arrives inside pasted or scripted input no longer triggers the switch. Backgrounding a foreground session with `←` shows `Your conversation moved to the background` above the list, and `Esc` at the root of agent view returns to that conversation instead of exiting to the shell, with double `Ctrl+C` remaining the exit; if the conversation can't be reopened, Claude Code exits and prints a `claude --resume` command for it. On Windows, a `←` pressed within about half a second of attaching shows `Ambiguous ←, press again to detach` and detaches on the second press. |
987| v2.1.217 | The pull request badge on a session's row renders as a hyperlink even when Claude Code can't detect terminal hyperlink support, for example over SSH or tmux; set [`FORCE_HYPERLINK=0`](/docs/en/env-vars) to render it as plain text. Before this release, the badge rendered as plain text when support wasn't detected. |
988| v2.1.216 | `/fork`: the [confirmation](#from-inside-a-session) is one line, showing the copy's state, the name of its agent-view row, and its session ID for `claude attach`, ending with `runs in the origin tree` or `edits this checkout` only when the copy runs in the main working tree or edits the checkout you have open. Clicking the name backgrounds this session and opens agent view in the copy's session. The confirmation no longer restates the copy's inherited permission mode; earlier versions printed a multi-line confirmation with no clickable name.<br /><br />Needs input: `/install-github-app` and the `/mcp` settings list, run while nobody is attached, show the session under `Needs input` with a row naming the command, and attaching and re-running the command continues; from v2.1.208 through v2.1.215 they were refused outright in that state.<br /><br />`--agent` restore: resuming or restarting a [backgrounded `--agent` session](#from-your-shell) restores the agent's system prompt and tool restrictions, searching the session's own directory for the agent first, when its workspace is trusted; a session whose agent no longer exists continues with the default tools and system prompt and opens with a visible warning, instead of silently reverting to the default agent.<br /><br />`Ctrl+X`: pressing it twice deletes a session even when the stop attempt fails, instead of a failed stop cancelling the pending delete, and a deleted session whose worker process had died no longer reappears on the next refresh.<br /><br />Worktree deletion: a session whose worktree directory belongs to no git repository can be deleted; before this release every attempt to delete such a session was refused. A directory that's already gone clears immediately. The agent view double-press removes a directory that still has files, running your `WorktreeRemove` hook for a hook-created directory, unless another session's records also name it. `claude rm` keeps such a directory whenever files remain. |
989| v2.1.214 | A session backgrounded with `←` or `/background` and left idle with nothing running has its process stopped like any other idle session, instead of keeping its process and the background service running indefinitely. A completed session can be removed with `claude rm` or from agent view after the background service has gone idle, and a session that entered a worktree after being dispatched from a directory that isn't a git repository, such as a multi-repo workspace folder, can be deleted from agent view when the worktree itself belongs to a git repository, because the cleanup is resolved from the worktree instead of the directory the session was dispatched from; both removals were refused on every attempt before. Reopening a stopped session restores its saved conversation even when a folder in the transcript store can't be read. |
990| v2.1.213 | `/install-github-app`, the [`/mcp`](/docs/en/mcp) settings list, and MCP authentication actions work in a background session while a terminal is attached, and are refused only when nobody is attached, with a message telling you to attach and run the command again; from v2.1.208 through v2.1.212 they were refused even with a terminal attached. |
991991| v2.1.212 | [`/fork` in an interactive session](#from-inside-a-session) copies the conversation into a new background session that appears as its own row, named after the session it came from or, for a prompted fork of an unnamed session, after the fork prompt, while the original keeps running; the earlier forked-subagent behavior of `/fork` moved to `/subtask`. With [agent view turned off](#turn-off-agent-view), `/fork` keeps the forked-subagent behavior. A focused row that is waiting for its first prompt shows `space to send it a prompt`. `Ctrl+J` inserts a newline in the dispatch input on terminals with extended key reporting, where the keypress was previously ignored, and the `?` overlay lists the shortcut. The `←` footer hint in an interactive session briefly shows `N done` when a background session finishes while none need your input. Typing a bare `/resume` in agent view opens a picker of past sessions of the repository you opened agent view from, including sessions deleted from the list, and picking one resumes it as a background session; before this release `/resume` wasn't available in agent view and deleted sessions were reachable only with `claude --resume` or `/resume` from an interactive session. Targeted, scoped, and restricted forms keep the `attach to a session to run it` hint that earlier versions showed for every form. Sessions waiting on a sandbox network-host prompt, an MCP input request, or a managed-settings prompt show as `Needs input` instead of `Working`, in agent view and in `claude agents --json`, and a question from Claude reports `waitingFor: input needed` instead of `permission prompt`. Attaching to a session whose process has stopped shows its transcript formatted the way the live session renders it, instead of as raw text. A stopped session whose transcript is in an unexpected place resumes from it via a last-resort scan of your saved transcripts, and opening a row that has no saved transcript shows `Press enter again to restart this session fresh`, restarting it fresh on the second press; v2.1.211 showed the refusal with no way to restart from agent view. |
992| v2.1.211 | Waking a stopped session by attaching or replying from the directory it runs in forwards your shell's gateway `ANTHROPIC_BASE_URL` again, under the same conditions as a fresh dispatch, so a session authenticated through a gateway `ANTHROPIC_AUTH_TOKEN` resumes on the gateway instead of reporting `Not logged in`. Attaching to a stopped session that was backgrounded from another conversation before its first response finished is refused with `This session has no saved transcript` instead of silently starting a blank conversation under the same session id; opening the same row from agent view showed the refusal in the footer. Ending the process of a `←` or `/background` session from outside Claude Code marks it stopped instead of the supervisor restarting it, a stop already recorded on disk is honored unless a reply you sent is still waiting to be delivered, a session restarted after a crash is told it was restarted, and a restarted `←` or `/background` session doesn't resume an interrupted response older than about an hour. A session-naming reply that answers or refuses the prompt instead of labeling it, such as for a prompt that's mostly a link, is discarded and the row keeps a name taken from the prompt text. Deleting a session whose worktree git no longer recognizes succeeds, leaving the worktree directory on disk and naming its path, instead of every attempt being refused. A refused delete shows the reason on the session's row, including the underlying git error when the worktree couldn't be removed, instead of the row silently reappearing. |
993| v2.1.210 | `claude attach` waits while the background service is starting or reconnecting instead of failing with a `job not found` or `still starting` error, reports a session that finished during the attach as exited, and applies a terminal resize made during a slow attach when the attach completes. The prompt footer's `←` needs-input count appears on every provider, including third-party providers that previously showed the plain `← for agents` form. Backgrounding a session with `←` carries Claude's task list to the background session instead of dropping it. The row you pressed `←` from keeps a bold, undimmed name after the selection moves. `claude agents --effort` accepts `ultracode` instead of silently dropping it. |
994| v2.1.208 | Attaching to a session whose process has stopped shows the last screenful of its transcript while the process starts, instead of only a `Session is starting` note. A reply that can't be delivered because the background service is unreachable or the send fails is saved and sent as the session's next prompt when its process starts again; before this release, a reply lost while the background service was unreachable was discarded. A process whose own binary was replaced by an update can still start the supervisor, from the installed `claude` launcher or the newest version on disk, instead of failing until Claude Code was restarted. A supervisor running an older version never restarts an idle session started by a newer version onto its own older binary. Deleting a session removes its worktree even after the session moved the worktree onto a different branch, and keeps the worktree together with the session row when the worktree has commits that aren't pushed anywhere or another session claims it, instead of destroying the commits or orphaning the worktree. `/install-github-app` and the `/mcp` settings list and its authentication actions are refused in a background session with a message naming the alternative; in v2.1.208 only, the `/model` picker was refused the same way and a typed `/model <name>` switched that session only instead of also saving your default model. |
995| v2.1.207 | The peek panel opens with the sentence the row truncates, such as the exact question for a session that's waiting on you, and shows how long a blocked session has been waiting as a single `waiting 3m` line instead of prefixing the same timestamp to the status sentence and the question. Pasting the same text again in the dispatch input expands the collapsed `[Pasted text #N]` placeholder instead of adding a second one. A background session named by accepting a plan shows that name on its row. A background session that moved into a worktree keeps its conversation when its process is restarted from agent view. |
996| v2.1.206 | Row summaries fill the row's remaining width and truncate only at the terminal's right edge instead of at 64 columns. After the supervisor restarts into a new Claude Code version, it restarts the remaining idle background sessions onto that version in the background instead of a few per minute. Deleting a session with `Ctrl+X` or `claude rm` also clears it from the supervisor's session list, so the row no longer reappears after a supervisor restart. A `CLAUDE_CODE_EXTRA_BODY` request-body override exported in the dispatching shell reaches background sessions instead of being ignored. |
997| v2.1.205 | The prompt footer's `←` hint in a regular `claude` session counts the background agents waiting on you, such as `← 2 agents`. Row summaries show the session's own one-line report, truncated at 64 columns, instead of a raw tool invocation or a `done/total` count; directory-grouped rows open with a colored state word. The peek panel opens with the full status sentence and, for a session waiting on you, its exact question above the reply input. Sessions that edit, comment on, close, or mark a pull request ready with `gh` are linked to it, not only ones that create or check out a pull request, a push links a pull request even when the local branch name doesn't match, and a pull request whose creating command's output exceeded the inline limit is linked too. A turn with no readable text keeps the session's previous state instead of flipping it back to `Working`. `claude attach` waits up to about 60 seconds for a session that's restarting, with a status line naming why, instead of failing. |
998| v2.1.203 | A gateway `ANTHROPIC_BASE_URL` exported in the dispatching shell reaches the sessions dispatched from it into that same directory when the supervisor shares that gateway environment, instead of being dropped while the API key exported alongside it was kept. The dispatching shell's `PATH` is applied to each session's worker. Pressing `←` while subagents are running waits for them instead of restarting them after ten seconds. The empty list always shows the section headers with a description under each. Typing `@` in the dispatch input also lists the launch repository's registered git worktrees that live inside its directory tree. An effort inherited from the `effortLevel` setting follows later edits to that setting instead of being fixed at dispatch. Opening a stopped session whose conversation is already open in another running session is refused with a message instead of failing the row. A command that isn't available in agent view leaves the typed text in the input. A `WorktreeCreate` hook that fails outside a git repository no longer blocks the session from editing files. |
999| v2.1.202 | A name set with `/rename` or `Ctrl+R` on a background session persists when the supervisor stops and restarts its process, instead of reverting to the name the session was dispatched with. |
1000| v2.1.200 | An older Claude Code version that rewrites the session list in `roster.json` preserves fields written by a newer version, matching the existing `state.json` guarantee, so sessions started by the newer version keep accepting input after the supervisor restarts. When you open a session that has stopped responding, the supervisor restarts its process and the session continues the interrupted response from where it left off. Agent view applies a `--plugin-dir` flag placed after `agents` to its own subagent and skill autocomplete in the dispatch input as well as dispatched sessions. |
1001| v2.1.199 | A background session whose process exits before it finishes starting on a low-memory host shows `possibly low memory — free some up and retry` in its row status instead of only the bare exit reason. Backgrounding a session with `←` or `/background` carries its `/color` over to the new row. |
1002| v2.1.198 | Agent view sends a notification through `preferredNotifChannel` when a background session needs input, finishes, or fails, and fires the `Notification` hook with the `agent_needs_input` or `agent_completed` type. `←` and `/exit` inside `claude attach <id>` return to agent view instead of exiting to the shell; `Ctrl+Z` returns to the shell. A background session that isolated its work in a worktree commits, pushes its own isolated branch, never `main` or `master`, and opens a draft pull request when it finishes instead of asking first. `/login` runs in agent view and opens the sign-in dialog. The `Background work is running` exit dialog offers `Move to background and exit`. The exit handoff also covers background subagents, which resume from their transcript on the next wake instead of being reported as failed. `claude --bg` combined with `-p` or `--print` is rejected with an error. The background session host requests macOS Local Network permission on first LAN access instead of failing with `connect: no route to host`. |
1003| v2.1.196 | A single `←` press backgrounds a foreground session; earlier versions required two presses, with a footer hint and a confirm. `--dangerously-skip-permissions` passed to `claude agents` shows the bypass disclaimer instead of being silently dropped. Interactive sessions you never named carry a default name such as `my-app-3f` in session listings and `claude agents --json`. Background shell commands and dynamic workflows survive the session's process being stopped, restarted, or updated, including on Windows; set `CLAUDE_CODE_DISABLE_BG_EXIT_HANDOFF=1` to turn the handoff off. A transcript misread as empty on restart is renamed with an `.orphaned-` suffix instead of deleted. |
1004| v2.1.195 | In-flight work carries over when you background a session on Windows too; set `CLAUDE_DISABLE_ADOPT=1` to stop it instead. The `Completed` group fills the remaining vertical space and the header compacts on short terminals. An older Claude Code version no longer drops newer sessions' `state.json` fields or hides those sessions from `claude agents`. Attaching to a stopped session switches immediately instead of showing a blank screen for up to five seconds. A supervisor that can't accept connections exits and releases its lock on its own. |
1005| v2.1.191 | `claude --bg` with an `--agent` name that doesn't match any of your subagents fails the launch: the session exits immediately with an `--agent '<name>' not found` error instead of running with the default agent. |
1006| v2.1.174 | Background sessions no longer inherit gateway endpoint variables such as `ANTHROPIC_BASE_URL` from the supervisor's launch shell; the supervisor supplies a fresh credential snapshot to pre-warmed workers, fixing spurious `Could not resolve authentication method` errors. |
1007| v2.1.172 | `/model` in the dispatch input sets a session-scoped dispatch model override. |
1008| v2.1.161 | Row summaries show a `done/total` count for parallel work items; the peek panel names the longest-running parallel work item. |
1009| v2.1.157 | `claude agents` accepts `--agent`; dispatched sessions honor the `agent` setting. |
1010| v2.1.145 | Voice dictation supported in the peek-panel reply input and the dispatch input. |
1011| v2.1.143 | `worktree.bgIsolation` setting added; `claude agents` accepts `--allow-dangerously-skip-permissions`. |
1012| v2.1.142 | `claude agents` accepts `--permission-mode`, `--model`, `--effort`, `--dangerously-skip-permissions`, `--settings`, `--add-dir`, `--plugin-dir`, `--mcp-config`, and `--strict-mcp-config`. |
1013| v2.1.141 | `claude agents` accepts `--cwd` to scope the list to one project.
992| v2.1.211 | Waking a stopped session by attaching or replying from the directory it runs in forwards your shell's gateway `ANTHROPIC_BASE_URL` again, under the same conditions as a fresh dispatch, so a session authenticated through a gateway `ANTHROPIC_AUTH_TOKEN` resumes on the gateway instead of reporting `Not logged in`. Attaching to a stopped session that was backgrounded from another conversation before its first response finished is refused with `This session has no saved transcript` instead of silently starting a blank conversation under the same session id; opening the same row from agent view showed the refusal in the footer. Ending the process of a `←` or `/background` session from outside Claude Code marks it stopped instead of the supervisor restarting it, a stop already recorded on disk is honored unless a reply you sent is still waiting to be delivered, a session restarted after a crash is told it was restarted, and a restarted `←` or `/background` session doesn't resume an interrupted response older than about an hour. A session-naming reply that answers or refuses the prompt instead of labeling it, such as for a prompt that's mostly a link, is discarded and the row keeps a name taken from the prompt text. Deleting a session whose worktree git no longer recognizes succeeds, leaving the worktree directory on disk and naming its path, instead of every attempt being refused. A refused delete shows the reason on the session's row, including the underlying git error when the worktree couldn't be removed, instead of the row silently reappearing. |
993| v2.1.210 | `claude attach` waits while the background service is starting or reconnecting instead of failing with a `job not found` or `still starting` error, reports a session that finished during the attach as exited, and applies a terminal resize made during a slow attach when the attach completes. The prompt footer's `←` needs-input count appears on every provider, including third-party providers that previously showed the plain `← for agents` form. Backgrounding a session with `←` carries Claude's task list to the background session instead of dropping it. The row you pressed `←` from keeps a bold, undimmed name after the selection moves. `claude agents --effort` accepts `ultracode` instead of silently dropping it. |
994| v2.1.208 | Attaching to a session whose process has stopped shows the last screenful of its transcript while the process starts, instead of only a `Session is starting` note. A reply that can't be delivered because the background service is unreachable or the send fails is saved and sent as the session's next prompt when its process starts again; before this release, a reply lost while the background service was unreachable was discarded. A process whose own binary was replaced by an update can still start the supervisor, from the installed `claude` launcher or the newest version on disk, instead of failing until Claude Code was restarted. A supervisor running an older version never restarts an idle session started by a newer version onto its own older binary. Deleting a session removes its worktree even after the session moved the worktree onto a different branch, and keeps the worktree together with the session row when the worktree has commits that aren't pushed anywhere or another session claims it, instead of destroying the commits or orphaning the worktree. `/install-github-app` and the `/mcp` settings list and its authentication actions are refused in a background session with a message naming the alternative; in v2.1.208 only, the `/model` picker was refused the same way and a typed `/model <name>` switched that session only instead of also saving your default model. |
995| v2.1.207 | The peek panel opens with the sentence the row truncates, such as the exact question for a session that's waiting on you, and shows how long a blocked session has been waiting as a single `waiting 3m` line instead of prefixing the same timestamp to the status sentence and the question. Pasting the same text again in the dispatch input expands the collapsed `[Pasted text #N]` placeholder instead of adding a second one. A background session named by accepting a plan shows that name on its row. A background session that moved into a worktree keeps its conversation when its process is restarted from agent view. |
996| v2.1.206 | Row summaries fill the row's remaining width and truncate only at the terminal's right edge instead of at 64 columns. After the supervisor restarts into a new Claude Code version, it restarts the remaining idle background sessions onto that version in the background instead of a few per minute. Deleting a session with `Ctrl+X` or `claude rm` also clears it from the supervisor's session list, so the row no longer reappears after a supervisor restart. A `CLAUDE_CODE_EXTRA_BODY` request-body override exported in the dispatching shell reaches background sessions instead of being ignored. |
997| v2.1.205 | The prompt footer's `←` hint in a regular `claude` session counts the background agents waiting on you, such as `← 2 agents`. Row summaries show the session's own one-line report, truncated at 64 columns, instead of a raw tool invocation or a `done/total` count; directory-grouped rows open with a colored state word. The peek panel opens with the full status sentence and, for a session waiting on you, its exact question above the reply input. Sessions that edit, comment on, close, or mark a pull request ready with `gh` are linked to it, not only ones that create or check out a pull request, a push links a pull request even when the local branch name doesn't match, and a pull request whose creating command's output exceeded the inline limit is linked too. A turn with no readable text keeps the session's previous state instead of flipping it back to `Working`. `claude attach` waits up to about 60 seconds for a session that's restarting, with a status line naming why, instead of failing. |
998| v2.1.203 | A gateway `ANTHROPIC_BASE_URL` exported in the dispatching shell reaches the sessions dispatched from it into that same directory when the supervisor shares that gateway environment, instead of being dropped while the API key exported alongside it was kept. The dispatching shell's `PATH` is applied to each session's worker. Pressing `←` while subagents are running waits for them instead of restarting them after ten seconds. The empty list always shows the section headers with a description under each. Typing `@` in the dispatch input also lists the launch repository's registered git worktrees that live inside its directory tree. An effort inherited from the `effortLevel` setting follows later edits to that setting instead of being fixed at dispatch. Opening a stopped session whose conversation is already open in another running session is refused with a message instead of failing the row. A command that isn't available in agent view leaves the typed text in the input. A `WorktreeCreate` hook that fails outside a git repository no longer blocks the session from editing files. |
999| v2.1.202 | A name set with `/rename` or `Ctrl+R` on a background session persists when the supervisor stops and restarts its process, instead of reverting to the name the session was dispatched with. |
1000| v2.1.200 | An older Claude Code version that rewrites the session list in `roster.json` preserves fields written by a newer version, matching the existing `state.json` guarantee, so sessions started by the newer version keep accepting input after the supervisor restarts. When you open a session that has stopped responding, the supervisor restarts its process and the session continues the interrupted response from where it left off. Agent view applies a `--plugin-dir` flag placed after `agents` to its own subagent and skill autocomplete in the dispatch input as well as dispatched sessions. |
1001| v2.1.199 | A background session whose process exits before it finishes starting on a low-memory host shows `possibly low memory — free some up and retry` in its row status instead of only the bare exit reason. Backgrounding a session with `←` or `/background` carries its `/color` over to the new row. |
1002| v2.1.198 | Agent view sends a notification through `preferredNotifChannel` when a background session needs input, finishes, or fails, and fires the `Notification` hook with the `agent_needs_input` or `agent_completed` type. `←` and `/exit` inside `claude attach <id>` return to agent view instead of exiting to the shell; `Ctrl+Z` returns to the shell. A background session that isolated its work in a worktree commits, pushes its own isolated branch, never `main` or `master`, and opens a draft pull request when it finishes instead of asking first. `/login` runs in agent view and opens the sign-in dialog. The `Background work is running` exit dialog offers `Move to background and exit`. The exit handoff also covers background subagents, which resume from their transcript on the next wake instead of being reported as failed. `claude --bg` combined with `-p` or `--print` is rejected with an error. The background session host requests macOS Local Network permission on first LAN access instead of failing with `connect: no route to host`. |
1003| v2.1.196 | A single `←` press backgrounds a foreground session; earlier versions required two presses, with a footer hint and a confirm. `--dangerously-skip-permissions` passed to `claude agents` shows the bypass disclaimer instead of being silently dropped. Interactive sessions you never named carry a default name such as `my-app-3f` in session listings and `claude agents --json`. Background shell commands and dynamic workflows survive the session's process being stopped, restarted, or updated, including on Windows; set `CLAUDE_CODE_DISABLE_BG_EXIT_HANDOFF=1` to turn the handoff off. A transcript misread as empty on restart is renamed with an `.orphaned-` suffix instead of deleted. |
1004| v2.1.195 | In-flight work carries over when you background a session on Windows too; set `CLAUDE_DISABLE_ADOPT=1` to stop it instead. The `Completed` group fills the remaining vertical space and the header compacts on short terminals. An older Claude Code version no longer drops newer sessions' `state.json` fields or hides those sessions from `claude agents`. Attaching to a stopped session switches immediately instead of showing a blank screen for up to five seconds. A supervisor that can't accept connections exits and releases its lock on its own. |
1005| v2.1.191 | `claude --bg` with an `--agent` name that doesn't match any of your subagents fails the launch: the session exits immediately with an `--agent '<name>' not found` error instead of running with the default agent. |
1006| v2.1.174 | Background sessions no longer inherit gateway endpoint variables such as `ANTHROPIC_BASE_URL` from the supervisor's launch shell; the supervisor supplies a fresh credential snapshot to pre-warmed workers, fixing spurious `Could not resolve authentication method` errors. |
1007| v2.1.172 | `/model` in the dispatch input sets a session-scoped dispatch model override. |
1008| v2.1.161 | Row summaries show a `done/total` count for parallel work items; the peek panel names the longest-running parallel work item. |
1009| v2.1.157 | `claude agents` accepts `--agent`; dispatched sessions honor the `agent` setting. |
1010| v2.1.145 | Voice dictation supported in the peek-panel reply input and the dispatch input. |
1011| v2.1.143 | `worktree.bgIsolation` setting added; `claude agents` accepts `--allow-dangerously-skip-permissions`. |
1012| v2.1.142 | `claude agents` accepts `--permission-mode`, `--model`, `--effort`, `--dangerously-skip-permissions`, `--settings`, `--add-dir`, `--plugin-dir`, `--mcp-config`, and `--strict-mcp-config`. |
1013| v2.1.141 | `claude agents` accepts `--cwd` to scope the list to one project. |
1014| v2.1.139 | Agent view introduced as a research preview. |
1015 

agents Changed · +7 / -7 lines

from line 4
44 
55Claude Code has five ways to work on several tasks at once: [subagents](/docs/en/sub-agents), [agent view](/docs/en/agent-view), [agent teams](/docs/en/agent-teams), [dynamic workflows](/docs/en/workflows), and [projects](/docs/en/claude-projects). They differ in how involved you stay, from steering each conversation yourself to letting Claude coordinate a group of workers, and in whether the work runs on your machine or in the cloud.
66 
7| Approach | What it gives you | Use it when |
8| :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
9| [Subagents](/docs/en/sub-agents) | Delegated workers inside one session that do a side task in their own context and return a summary | A side task would flood your main conversation with search results, logs, or file contents you won't reference again |
10| [Agent view](/docs/en/agent-view) | One screen to dispatch and monitor sessions running in the background, opened with `claude agents`. Research preview | You have several independent tasks and want to hand them off, check status at a glance, and step in only when one needs you |
11| [Agent teams](/docs/en/agent-teams) | Multiple coordinated sessions with a shared task list and inter-agent messaging, managed by a lead. Experimental and disabled by default | You want Claude to split a project into pieces, assign them, and keep the workers in sync |
12| [Projects](/docs/en/claude-projects) | One ongoing conversation at claude.ai/code or in the desktop app. Claude starts parallel sessions called threads, in the cloud or, when you ask, on your computer through Remote Control, gives each one the project's instructions, and shows you which ones need you. Public beta on Pro and Max | The work spans many tasks over days or weeks, should keep running when your machine is off, and you'd rather describe it once than dispatch and track each session |
13| [Dynamic workflows](/docs/en/workflows) | A script that runs many subagents and cross-checks their results, for work too big to coordinate one turn at a time or that needs more than a single pass | A job outgrows a handful of subagents, or you want findings verified against each other: a codebase-wide audit, a 500-file migration, cross-checked research, or a plan drafted from several angles |
7| Approach | What it gives you | Use it when |
8| :- | :- | :- |
9| [Subagents](/docs/en/sub-agents) | Delegated workers inside one session that do a side task in their own context and return a summary | A side task would flood your main conversation with search results, logs, or file contents you won't reference again |
10| [Agent view](/docs/en/agent-view) | One screen to dispatch and monitor sessions running in the background, opened with `claude agents`. Research preview | You have several independent tasks and want to hand them off, check status at a glance, and step in only when one needs you |
11| [Agent teams](/docs/en/agent-teams) | Multiple coordinated sessions with a shared task list and inter-agent messaging, managed by a lead. Experimental and disabled by default | You want Claude to split a project into pieces, assign them, and keep the workers in sync |
12| [Projects](/docs/en/claude-projects) | One ongoing conversation at claude.ai/code or in the desktop app. Claude starts parallel sessions called threads, in the cloud or, when you ask, on your computer through Remote Control, gives each one the project's instructions, and shows you which ones need you. Public beta on Pro and Max | The work spans many tasks over days or weeks, should keep running when your machine is off, and you'd rather describe it once than dispatch and track each session |
13| [Dynamic workflows](/docs/en/workflows) | A script that runs many subagents and cross-checks their results, for work too big to coordinate one turn at a time or that needs more than a single pass | A job outgrows a handful of subagents, or you want findings verified against each other: a codebase-wide audit, a 500-file migration, cross-checked research, or a plan drafted from several angles |
1414 
1515In every approach the workers are Claude sessions. To involve a different tool, expose it to Claude as an [MCP server](/docs/en/mcp).
1616 

amazon-bedrock Changed · +18 / -18 lines

from line 277
277277 
278278To keep the built-in default models and change only their preferred prefix, set [`ANTHROPIC_BEDROCK_REGION_PREFIX`](#cross-region-inference-profile-prefixes) instead of pinning. The difference shows in what the `opus` alias resolves to:
279279 
280| You set | The `opus` alias resolves to |
281| :------------------------------------------------------------ | :------------------------------------------------------------------------------ |
282| `ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-4-8'` | `us.anthropic.claude-opus-4-8`, the exact ID you pinned |
283| `ANTHROPIC_BEDROCK_REGION_PREFIX=eu` | `eu.anthropic.claude-opus-5-5`, the built-in default with your preferred prefix |
280| You set | The `opus` alias resolves to |
281| :- | :- |
282| `ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-4-8'` | `us.anthropic.claude-opus-4-8`, the exact ID you pinned |
283| `ANTHROPIC_BEDROCK_REGION_PREFIX=eu` | `eu.anthropic.claude-opus-5-5`, the built-in default with your preferred prefix |
284284 
285285For current and legacy model IDs, see [Models overview](https://platform.claude.com/docs/en/about-claude/models/overview). For the full list of pinning environment variables, see [Model configuration](/docs/en/model-config#pin-models-for-third-party-deployments).
286286 
287287Claude Code uses these default models when no pinning variables are set:
288288 
289| Model type | Default model |
290| :--------------- | :---------------------------------------------------------------------------------------- |
291| Primary model | Opus 5.5, for example `us.anthropic.claude-opus-5-5` in a `us-*` region |
289| Model type | Default model |
290| :- | :- |
291| Primary model | Opus 5.5, for example `us.anthropic.claude-opus-5-5` in a `us-*` region |
292292| Small/fast model | Sonnet 4.5, for example `us.anthropic.claude-sonnet-4-5-20250929-v1:0` in a `us-*` region |
293293 
294294Background tasks such as session title generation use the small/fast model, normally a Haiku-class model. On Amazon Bedrock, Claude Code uses the default Sonnet model for background tasks because Haiku may not be enabled in every account or region. Two selections change which model carries them:
from line 358
358358 
359359On the Amazon Bedrock [Invoke API](https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_InvokeModelWithResponseStream.html), Claude Code resolves its built-in default models to [cross-region inference profile](https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html) IDs; to route model versions through your own inference profiles instead, see [Map each model version to an inference profile](#map-each-model-version-to-an-inference-profile). This table shows the prefix Claude Code prefers for each resolved AWS region:
360360 
361| AWS region | Prefix |
362| :------------------------ | :-------- |
361| AWS region | Prefix |
362| :- | :- |
363363| `us-gov-*` (AWS GovCloud) | `us-gov.` |
364| `us-*` | `us.` |
365| `eu-*` | `eu.` |
366| `ap-*` | `apac.` |
367| All other regions | `global.` |
364| `us-*` | `us.` |
365| `eu-*` | `eu.` |
366| `ap-*` | `apac.` |
367| All other regions | `global.` |
368368 
369369Set `ANTHROPIC_BEDROCK_REGION_PREFIX` to choose the prefix Claude Code tries first; when Claude Code can check profile availability and finds no matching profile for a model, it falls back as described in the resolution order below. Valid values are `us`, `eu`, `apac`, `jp`, `au`, and `global`. For example, set it to `global` when your account has `global.` profiles enabled but Claude Code would derive a geography-specific one from your AWS region. Requires Claude Code v2.1.224 or later.
370370 
from line 538
538538 
539539These variables are specific to the Mantle endpoint. See [Environment variables](/docs/en/env-vars) for the full list.
540540 
541| Variable | Purpose |
542| :-------------------------------------- | :------------------------------------------------------------------------- |
543| `CLAUDE_CODE_USE_MANTLE` | Enable the Mantle endpoint. Set to `1` or `true`. |
544| `ANTHROPIC_BEDROCK_MANTLE_BASE_URL` | Override the default Mantle endpoint URL |
545| `CLAUDE_CODE_SKIP_MANTLE_AUTH` | Skip client-side authentication for proxy setups |
541| Variable | Purpose |
542| :- | :- |
543| `CLAUDE_CODE_USE_MANTLE` | Enable the Mantle endpoint. Set to `1` or `true`. |
544| `ANTHROPIC_BEDROCK_MANTLE_BASE_URL` | Override the default Mantle endpoint URL |
545| `CLAUDE_CODE_SKIP_MANTLE_AUTH` | Skip client-side authentication for proxy setups |
546546| `ANTHROPIC_SMALL_FAST_MODEL_AWS_REGION` | Override AWS region for the Haiku-class model (shared with Amazon Bedrock) |
547547 
548548## Troubleshooting

analytics Changed · +3 / -3 lines

from line 4
44 
55Claude Code provides analytics dashboards to help organizations understand developer usage patterns, track contribution metrics, and measure how Claude Code impacts engineering velocity. Access the dashboard for your plan:
66 
7| Plan | Dashboard URL | Includes | Read more |
8| ----------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------- |
7| Plan | Dashboard URL | Includes | Read more |
8| - | - | - | - |
99| Claude for Teams / Enterprise | [claude.ai/analytics/claude-code](https://claude.ai/analytics/claude-code) | Usage metrics, contribution metrics with GitHub integration, leaderboard, data export | [Details](#access-analytics-for-team-and-enterprise) |
10| API (Claude Console) | [platform.claude.com/claude-code](https://platform.claude.com/claude-code) | Usage metrics, spend tracking, team insights | [Details](#access-analytics-for-api-customers) |
10| API (Claude Console) | [platform.claude.com/claude-code](https://platform.claude.com/claude-code) | Usage metrics, spend tracking, team insights | [Details](#access-analytics-for-api-customers) |
1111 
1212## Access analytics for Team and Enterprise
1313 

artifacts Changed · +25 / -25 lines

from line 301
301301 
302302Each artifact is one self-contained page. Claude Code wraps the file you publish in an HTML document shell and serves it under a strict Content Security Policy (CSP), which shapes what the page can do.
303303 
304| Constraint | Effect |
305| :---------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
304| Constraint | Effect |
305| :- | :- |
306306| External requests | The page can load typefaces from Google Fonts, and scripts from [five public CDN hosts](#allowlist-the-viewer-domain): cdnjs, unpkg, the Tailwind and jQuery CDNs, and selected paths on jsDelivr such as `/npm/`. The CSP blocks every external image and all other external scripts, stylesheets, and fonts, and lets `fetch`, XHR, and WebSocket calls reach only the page's own origin and the Google Fonts hosts. Claude therefore loads any library the page needs from one of those CDNs, inlines all other CSS and JavaScript, and embeds images as data URIs. [Connector calls](#pull-live-data-with-mcp-connectors) go through claude.ai, which makes the network call itself. |
307| No backend | An artifact is a static page. It can't authenticate viewers itself. |
308| Downloads | The page can't start a download itself. To let viewers save a file the page generates, Claude declares the downloads capability. See [Offer a file download](#offer-a-file-download). |
309| Single page | Relative links do not resolve, because nothing is deployed alongside the page. For multi-section content, Claude uses in-page anchors rather than separate files. |
310| Source file types | The published file must be `.html`, `.htm`, or `.md`, and must decode as UTF-8, or as little-endian UTF-16 by its byte-order mark. Markdown files render as styled document pages with syntax-highlighted code. A file that doesn't decode, or that contains the replacement character `U+FFFD`, is [refused with the line and column to fix](/docs/en/errors#the-source-file-is-not-valid-utf-8-text). |
311| Rendered size | The rendered page must be 16 MiB or smaller. Large embedded images are the usual cause when a publish fails for size. |
307| No backend | An artifact is a static page. It can't authenticate viewers itself. |
308| Downloads | The page can't start a download itself. To let viewers save a file the page generates, Claude declares the downloads capability. See [Offer a file download](#offer-a-file-download). |
309| Single page | Relative links do not resolve, because nothing is deployed alongside the page. For multi-section content, Claude uses in-page anchors rather than separate files. |
310| Source file types | The published file must be `.html`, `.htm`, or `.md`, and must decode as UTF-8, or as little-endian UTF-16 by its byte-order mark. Markdown files render as styled document pages with syntax-highlighted code. A file that doesn't decode, or that contains the replacement character `U+FFFD`, is [refused with the line and column to fix](/docs/en/errors#the-source-file-is-not-valid-utf-8-text). |
311| Rendered size | The rendered page must be 16 MiB or smaller. Large embedded images are the usual cause when a publish fails for size. |
312312 
313313Generating an artifact uses output tokens like any other response, and a styled page is more token-intensive than the same content as terminal text. Inline CSS, JavaScript for interactive controls, and especially images embedded as data URIs are the main contributors. To reduce an artifact's token cost:
314314 
from line 320
320320 
321321Artifacts require every condition below. When one is not met, Claude writes a local HTML file or says it cannot publish instead.
322322 
323| Requirement | Available when |
324| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
325| Plan | Pro, Max, Team, or Enterprise. On Pro and Max plans, artifacts are private to you until you share them, and no admin management applies. On Team plans, artifacts are on by default. On Enterprise plans, an Owner [enables them](#manage-artifacts-for-your-organization) in claude.ai admin settings. |
326| Authentication | The session is backed by a claude.ai account: sign in with `/login` in the CLI or desktop app. Claude Tag sessions are signed in through the agent's identity, so no step is needed there. Sessions using an API key, [gateway token](/docs/en/llm-gateway), or cloud-provider credential cannot publish. |
327| Model provider | Anthropic API. Not available on [Amazon Bedrock](/docs/en/amazon-bedrock), [Google Cloud's Agent Platform](/docs/en/google-vertex-ai), or [Microsoft Foundry](/docs/en/microsoft-foundry). |
328| Organization policy | Customer-managed encryption keys (CMEK), HIPAA, and [Zero Data Retention](/docs/en/zero-data-retention) are not enabled for the organization. |
329| Surface | Claude Code CLI, or the Claude desktop app version 1.13576.0 or later. [Claude Tag](https://claude.com/docs/claude-tag/overview) sessions can also publish artifacts when both Claude Tag and artifacts are enabled for the organization. Off by default in [Agent SDK](/docs/en/agent-sdk/overview), GitHub Action, and MCP-server contexts, and when [`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`](/docs/en/env-vars) is set. |
323| Requirement | Available when |
324| :- | :- |
325| Plan | Pro, Max, Team, or Enterprise. On Pro and Max plans, artifacts are private to you until you share them, and no admin management applies. On Team plans, artifacts are on by default. On Enterprise plans, an Owner [enables them](#manage-artifacts-for-your-organization) in claude.ai admin settings. |
326| Authentication | The session is backed by a claude.ai account: sign in with `/login` in the CLI or desktop app. Claude Tag sessions are signed in through the agent's identity, so no step is needed there. Sessions using an API key, [gateway token](/docs/en/llm-gateway), or cloud-provider credential cannot publish. |
327| Model provider | Anthropic API. Not available on [Amazon Bedrock](/docs/en/amazon-bedrock), [Google Cloud's Agent Platform](/docs/en/google-vertex-ai), or [Microsoft Foundry](/docs/en/microsoft-foundry). |
328| Organization policy | Customer-managed encryption keys (CMEK), HIPAA, and [Zero Data Retention](/docs/en/zero-data-retention) are not enabled for the organization. |
329| Surface | Claude Code CLI, or the Claude desktop app version 1.13576.0 or later. [Claude Tag](https://claude.com/docs/claude-tag/overview) sessions can also publish artifacts when both Claude Tag and artifacts are enabled for the organization. Off by default in [Agent SDK](/docs/en/agent-sdk/overview), GitHub Action, and MCP-server contexts, and when [`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`](/docs/en/env-vars) is set. |
330330 
331331Whether artifacts are allowed for your organization comes from your organization's policy, which Claude Code loads from `api.anthropic.com`. When Claude Code can't load the policy, artifacts are unavailable. When you ask for one, Claude says why.
332332 
from line 336
336336 
337337To turn artifacts off for your own sessions regardless of your organization's setting, use any of:
338338 
339| Where | What to do |
340| :----------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------ |
341| [`/config`](/docs/en/commands) | Turn the **Artifacts** row off, which writes [`"enableArtifact": false`](/docs/en/settings-reference#enableartifact) to your user settings |
342| [Settings file](/docs/en/settings) | Set `"enableArtifact": false`. The deprecated `"disableArtifact": true` also turns artifacts off |
343| [Environment variable](/docs/en/env-vars) | Set `CLAUDE_CODE_DISABLE_ARTIFACT=1` |
344| [Permission rule](/docs/en/permissions) | Add `Artifact` to `permissions.deny` |
339| Where | What to do |
340| :- | :- |
341| [`/config`](/docs/en/commands) | Turn the **Artifacts** row off, which writes [`"enableArtifact": false`](/docs/en/settings-reference#enableartifact) to your user settings |
342| [Settings file](/docs/en/settings) | Set `"enableArtifact": false`. The deprecated `"disableArtifact": true` also turns artifacts off |
343| [Environment variable](/docs/en/env-vars) | Set `CLAUDE_CODE_DISABLE_ARTIFACT=1` |
344| [Permission rule](/docs/en/permissions) | Add `Artifact` to `permissions.deny` |
345345 
346346Once you turn artifacts off in a [`--settings`](/docs/en/cli-reference#cli-flags) file or with `CLAUDE_CODE_DISABLE_ARTIFACT`, or your administrator turns them off in [managed settings](/docs/en/server-managed-settings), no settings file turns them back on. Before v2.1.242, a file higher in the [precedence stack](/docs/en/settings#settings-precedence) could turn artifacts back on even when a lower-precedence file set `"enableArtifact": false`.
347347 
from line 385
385385 
386386The [Compliance API](https://docs.claude.com/en/api/compliance) provides endpoints to list an organization's artifacts, retrieve a specific version's content, and delete an artifact:
387387 
388| Method | Endpoint |
389| :------- | :------------------------------------------------------------------ |
390| `GET` | `/v1/compliance/code/artifacts` |
391| `GET` | `/v1/compliance/code/artifacts/{artifact_id}/versions/{version_id}` |
392| `DELETE` | `/v1/compliance/code/artifacts/{artifact_id}` |
388| Method | Endpoint |
389| :- | :- |
390| `GET` | `/v1/compliance/code/artifacts` |
391| `GET` | `/v1/compliance/code/artifacts/{artifact_id}/versions/{version_id}` |
392| `DELETE` | `/v1/compliance/code/artifacts/{artifact_id}` |
393393 
394394For the request and response schemas, see the [Compliance API reference](https://docs.claude.com/en/api/compliance/code/artifacts).
395395 

authentication Changed · +5 / -5 lines

from line 224
224224 
225225Claude Code checks three sources in this order and stops at the first one that is set. The table shows what sets each source and where it ranks against your `/login` credential.
226226 
227| Source | Set by | Rank against `/login` |
228| :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------- |
229| Named profile | `ANTHROPIC_PROFILE` | Above, whichever auth mode the profile has |
230| Federation variables | `ANTHROPIC_FEDERATION_RULE_ID` and `ANTHROPIC_ORGANIZATION_ID`, both set | Above |
231| Active profile | The [`active_config` file](https://platform.claude.com/docs/en/manage-claude/wif-reference#active-profile) in your configuration directory, or a profile named `default` | Above when its auth mode is `oidc_federation`; below a working `/login` credential when its auth mode is `user_oauth` |
227| Source | Set by | Rank against `/login` |
228| :- | :- | :- |
229| Named profile | `ANTHROPIC_PROFILE` | Above, whichever auth mode the profile has |
230| Federation variables | `ANTHROPIC_FEDERATION_RULE_ID` and `ANTHROPIC_ORGANIZATION_ID`, both set | Above |
231| Active profile | The [`active_config` file](https://platform.claude.com/docs/en/manage-claude/wif-reference#active-profile) in your configuration directory, or a profile named `default` | Above when its auth mode is `oidc_federation`; below a working `/login` credential when its auth mode is `user_oauth` |
232232 
233233The `user_oauth` rule keeps a leftover `ant auth login` profile from moving your requests off the account you signed in to with `/login`. For the federation variables, Claude Code also reads the other variables in the [WIF reference](https://platform.claude.com/docs/en/manage-claude/wif-reference#environment-variables), such as `ANTHROPIC_IDENTITY_TOKEN_FILE`, when it exchanges your identity token. For the profile file format, see the [WIF reference](https://platform.claude.com/docs/en/manage-claude/wif-reference#profile-configuration-file).
234234 

auto-mode-config Changed · +9 / -9 lines

from line 47
4747 
4848Pick the mechanism that matches how firm the boundary needs to be:
4949 
50| Boundary | Mechanism | Behavior in auto mode |
51| :-------------------------------- | :--------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52| Prompt before the action | `permissions.ask` | Always prompts for a command that matches a content-scoped rule like the recipe above. The classifier cannot auto-approve a matching action. |
53| Never run the action | `permissions.deny` | Blocks before the classifier is consulted. Neither the classifier nor user intent can override it. |
50| Boundary | Mechanism | Behavior in auto mode |
51| :- | :- | :- |
52| Prompt before the action | `permissions.ask` | Always prompts for a command that matches a content-scoped rule like the recipe above. The classifier cannot auto-approve a matching action. |
53| Never run the action | `permissions.deny` | Blocks before the classifier is consulted. Neither the classifier nor user intent can override it. |
5454| One-off boundary for this session | State it in conversation, like "don't push until I review" | The classifier blocks matching actions, but the boundary can be lost if [context compaction](/docs/en/costs#reduce-token-usage) removes the message that stated it. Use an ask or deny rule for a durable guarantee. |
5555 
5656## Where the classifier reads configuration
from line 59
5959 
6060For rules that apply across projects, such as trusted infrastructure or organization-wide deny rules, use the `autoMode` settings block. The classifier reads `autoMode` from the following scopes:
6161 
62| Scope | File | Use for |
63| :----------------------------- | :---------------------------------------------- | :--------------------------------------------------- |
64| One developer | `~/.claude/settings.json` | Personal trusted infrastructure |
65| Organization-wide | [Managed settings](/docs/en/server-managed-settings) | Trusted infrastructure distributed to all developers |
66| `--settings` flag or Agent SDK | Inline JSON | Per-invocation overrides for automation |
62| Scope | File | Use for |
63| :- | :- | :- |
64| One developer | `~/.claude/settings.json` | Personal trusted infrastructure |
65| Organization-wide | [Managed settings](/docs/en/server-managed-settings) | Trusted infrastructure distributed to all developers |
66| `--settings` flag or Agent SDK | Inline JSON | Per-invocation overrides for automation |
6767 
6868The classifier doesn't read `autoMode` from project settings in `.claude/settings.json` or `.claude/settings.local.json`. Both files live in the repo directory, so a checked-in repo or a build step could otherwise inject its own allow rules. Move any `autoMode` block in `.claude/settings.local.json` to `~/.claude/settings.json`.
6969 

best-practices Changed · +25 / -25 lines

from line 30
3030 
3131The check is anything that returns a signal Claude can read in the conversation: a test suite, a build exit code, a linter, a script that diffs output against a fixture, or a [browser screenshot](/docs/en/chrome) compared against a design. Run [`/verify`](/docs/en/skills#run-and-verify-your-app) yourself after Claude's check passes to confirm the change against the running app.
3232 
33| Strategy | Before | After |
34| ------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
35| **Provide verification criteria** | *"implement a function that validates email addresses"* | *"write a validateEmail function. example test cases: [[email protected]](mailto:[email protected]) is true, invalid is false, [[email protected]](mailto:[email protected]) is false. run the tests after implementing"* |
36| **Verify UI changes visually** | *"make the dashboard look better"* | *"\[paste screenshot] implement this design. take a screenshot of the result and compare it to the original. list differences and fix them"* |
37| **Address root causes, not symptoms** | *"the build is failing"* | *"the build fails with this error: \[paste error]. fix it and verify the build succeeds. address the root cause, don't suppress the error"* |
33| Strategy | Before | After |
34| - | - | - |
35| **Provide verification criteria** | *"implement a function that validates email addresses"* | *"write a validateEmail function. example test cases: [[email protected]](mailto:[email protected]) is true, invalid is false, [[email protected]](mailto:[email protected]) is false. run the tests after implementing"* |
36| **Verify UI changes visually** | *"make the dashboard look better"* | *"\[paste screenshot] implement this design. take a screenshot of the result and compare it to the original. list differences and fix them"* |
37| **Address root causes, not symptoms** | *"the build is failing"* | *"the build fails with this error: \[paste error]. fix it and verify the build succeeds. address the root cause, don't suppress the error"* |
3838 
3939Once the check exists, decide how hard it gates the stop:
4040 
from line 116
116116 
117117Claude can infer intent, but it can't read your mind. Reference specific files, mention constraints, and point to example patterns.
118118 
119| Strategy | Before | After |
120| ------------------------------------------------------------------------------------------------ | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
121| **Scope the task.** Specify which file, what scenario, and testing preferences. | *"add tests for foo.py"* | *"write a test for foo.py covering the edge case where the user is logged out. avoid mocks."* |
122| **Point to sources.** Direct Claude to the source that can answer a question. | *"why does ExecutionFactory have such a weird api?"* | *"look through ExecutionFactory's git history and summarize how its api came to be"* |
123| **Reference existing patterns.** Point Claude to patterns in your codebase. | *"add a calendar widget"* | *"look at how existing widgets are implemented on the home page to understand the patterns. HotDogWidget.php is a good example. follow the pattern to implement a new calendar widget that lets the user select a month and paginate forwards/backwards to pick a year. build from scratch without libraries other than the ones already used in the codebase."* |
124| **Describe the symptom.** Provide the symptom, the likely location, and what "fixed" looks like. | *"fix the login bug"* | *"users report that login fails after session timeout. check the auth flow in src/auth/, especially token refresh. write a failing test that reproduces the issue, then fix it"* |
119| Strategy | Before | After |
120| - | - | - |
121| **Scope the task.** Specify which file, what scenario, and testing preferences. | *"add tests for foo.py"* | *"write a test for foo.py covering the edge case where the user is logged out. avoid mocks."* |
122| **Point to sources.** Direct Claude to the source that can answer a question. | *"why does ExecutionFactory have such a weird api?"* | *"look through ExecutionFactory's git history and summarize how its api came to be"* |
123| **Reference existing patterns.** Point Claude to patterns in your codebase. | *"add a calendar widget"* | *"look at how existing widgets are implemented on the home page to understand the patterns. HotDogWidget.php is a good example. follow the pattern to implement a new calendar widget that lets the user select a month and paginate forwards/backwards to pick a year. build from scratch without libraries other than the ones already used in the codebase."* |
124| **Describe the symptom.** Provide the symptom, the likely location, and what "fixed" looks like. | *"fix the login bug"* | *"users report that login fails after session timeout. check the auth flow in src/auth/, especially token refresh. write a failing test that reproduces the issue, then fix it"* |
125125 
126126Vague prompts can be useful when you're exploring and can afford to course-correct. A prompt like `"what would you improve in this file?"` can surface things you wouldn't have thought to ask about.
127127 
from line 169
169169 
170170Keep it concise. For each line, ask: *"Would removing this cause Claude to make mistakes?"* If not, cut it. Bloated CLAUDE.md files cause Claude to ignore your actual instructions!
171171 
172| ✅ Include | ❌ Exclude |
173| ---------------------------------------------------- | -------------------------------------------------- |
174| Bash commands Claude can't guess | Anything Claude can figure out by reading code |
175| Code style rules that differ from defaults | Standard language conventions Claude already knows |
176| Testing instructions and preferred test runners | Detailed API documentation (link to docs instead) |
177| Repository etiquette (branch naming, PR conventions) | Information that changes frequently |
178| Architectural decisions specific to your project | Long explanations or tutorials |
179| Developer environment quirks (required env vars) | File-by-file descriptions of the codebase |
180| Common gotchas or non-obvious behaviors | Self-evident practices like "write clean code" |
172| ✅ Include | ❌ Exclude |
173| - | - |
174| Bash commands Claude can't guess | Anything Claude can figure out by reading code |
175| Code style rules that differ from defaults | Standard language conventions Claude already knows |
176| Testing instructions and preferred test runners | Detailed API documentation (link to docs instead) |
177| Repository etiquette (branch naming, PR conventions) | Information that changes frequently |
178| Architectural decisions specific to your project | Long explanations or tutorials |
179| Developer environment quirks (required env vars) | File-by-file descriptions of the codebase |
180| Common gotchas or non-obvious behaviors | Self-evident practices like "write clean code" |
181181 
182182If Claude keeps doing something you don't want despite having a rule against it, the file is probably too long and the rule is getting lost. If Claude asks you questions that are answered in CLAUDE.md, the phrasing might be ambiguous. Treat CLAUDE.md like code: review it when things go wrong, prune it regularly, and test changes by observing whether Claude's behavior actually shifts. For a checked-in CLAUDE.md, run [`/doctor`](/docs/en/commands#all-commands) and Claude proposes cuts for content it can derive from the codebase.
183183 
from line 471
471471 
472472For example, use a Writer/Reviewer pattern:
473473 
474| Session A (Writer) | Session B (Reviewer) |
475| ----------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
476| `Implement a rate limiter for our API endpoints` | |
477| | `Review the rate limiter implementation in @src/middleware/rateLimiter.ts. Look for edge cases, race conditions, and consistency with our existing middleware patterns.` |
478| `Here's the review feedback: [Session B output]. Address these issues.` | |
474| Session A (Writer) | Session B (Reviewer) |
475| - | - |
476| `Implement a rate limiter for our API endpoints` | |
477| | `Review the rate limiter implementation in @src/middleware/rateLimiter.ts. Look for edge cases, race conditions, and consistency with our existing middleware patterns.` |
478| `Here's the review feedback: [Session B output]. Address these issues.` | |
479479 
480480You can do something similar with tests: have one Claude write tests, then another write code to pass them.
481481 

champion-kit Changed · +50 / -50 lines

from line 10
1010 
1111The role consists of three behaviors that reinforce one another.
1212 
13| Behavior | What it looks like in practice | Why it matters |
14| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15| Share what you discover | Post the prompts, screenshots, and small wins from your own work in the places your team already reads, such as an engineering channel, a standup thread, or a pull-request description. | Examples drawn from your own codebase are more persuasive than any external documentation, because colleagues can see exactly how the tool applies to the problems they share with you. |
16| Be the person people ask | When a colleague asks how you accomplished something, respond with the actual prompt you used so they can apply it directly to their own task. | A concrete, runnable example removes the gap between curiosity and a first successful use, which is where most adoption efforts stall. |
17| Grow the circle | Establish a small number of lightweight, recurring habits, such as a dedicated channel or a weekly thread, so that momentum continues even when your attention is elsewhere. | Adoption that depends on a single person is fragile. Adoption that is carried by shared habits continues to compound on its own. |
13| Behavior | What it looks like in practice | Why it matters |
14| - | - | - |
15| Share what you discover | Post the prompts, screenshots, and small wins from your own work in the places your team already reads, such as an engineering channel, a standup thread, or a pull-request description. | Examples drawn from your own codebase are more persuasive than any external documentation, because colleagues can see exactly how the tool applies to the problems they share with you. |
16| Be the person people ask | When a colleague asks how you accomplished something, respond with the actual prompt you used so they can apply it directly to their own task. | A concrete, runnable example removes the gap between curiosity and a first successful use, which is where most adoption efforts stall. |
17| Grow the circle | Establish a small number of lightweight, recurring habits, such as a dedicated channel or a weekly thread, so that momentum continues even when your attention is elsewhere. | Adoption that depends on a single person is fragile. Adoption that is carried by shared habits continues to compound on its own. |
1818 
1919### What this should cost you
2020 
2121Set expectations with yourself and with your lead. The activities below are intended to fit inside a normal working week, and the role should remain a multiplier on your existing work rather than an additional support responsibility.
2222 
23| Activity | Time per week | Guidance |
24| --------------------------------------- | ---------------- | -------------------------------------------------------------------------------------------------------------------- |
25| Posting wins and prompts | About 15 minutes | Capture these in the moment with a screenshot and one or two sentences; avoid turning them into formal write-ups. |
26| Answering questions in a shared channel | About 20 minutes | Answer publicly once, then link back to that answer when the question recurs. |
27| Hosting a weekly show-and-tell thread | About 5 minutes | You post the opening prompt; the team supplies the content. |
28| Optional pairing or walkthroughs | 0 to 30 minutes | Reserve this for colleagues who are blocked, and offer the [Quickstart](/docs/en/quickstart) link before scheduling time. |
23| Activity | Time per week | Guidance |
24| - | - | - |
25| Posting wins and prompts | About 15 minutes | Capture these in the moment with a screenshot and one or two sentences; avoid turning them into formal write-ups. |
26| Answering questions in a shared channel | About 20 minutes | Answer publicly once, then link back to that answer when the question recurs. |
27| Hosting a weekly show-and-tell thread | About 5 minutes | You post the opening prompt; the team supplies the content. |
28| Optional pairing or walkthroughs | 0 to 30 minutes | Reserve this for colleagues who are blocked, and offer the [Quickstart](/docs/en/quickstart) link before scheduling time. |
2929 
3030## Share what you discover
3131 
from line 46
4646 
4747Post wherever your team already reads. The goal is to place examples in the path of normal work rather than to create a destination.
4848 
49| Location | Best suited for | Recommended format |
50| ----------------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
51| A `#claude-code` or general engineering channel | Discoveries, prompts, and "today I learned" moments | A screenshot accompanied by one or two sentences of context |
52| Pull-request descriptions | Demonstrating the approach on real code that reviewers are already reading | A single line such as "Claude and I did this refactor; happy to walk through the approach." |
53| Standups or weekly written updates | Normalizing usage with leads and skip-level managers | One sentence describing one concrete outcome |
54| Team wiki or internal documentation | Durable patterns, custom skills, and `CLAUDE.md` examples | A short page, linked from the channel topic so it remains discoverable |
49| Location | Best suited for | Recommended format |
50| - | - | - |
51| A `#claude-code` or general engineering channel | Discoveries, prompts, and "today I learned" moments | A screenshot accompanied by one or two sentences of context |
52| Pull-request descriptions | Demonstrating the approach on real code that reviewers are already reading | A single line such as "Claude and I did this refactor; happy to walk through the approach." |
53| Standups or weekly written updates | Normalizing usage with leads and skip-level managers | One sentence describing one concrete outcome |
54| Team wiki or internal documentation | Durable patterns, custom skills, and `CLAUDE.md` examples | A short page, linked from the channel topic so it remains discoverable |
5555 
5656### The format that works
5757 
from line 99
9999 
100100### Questions you are likely to hear
101101 
102| Question | Suggested response | Follow-up resource |
103| -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
104| "What should I try it on first?" | Recommend a real but contained task, ideally a bug or chore the person has been postponing because it is tedious rather than difficult. | [Common workflows](/docs/en/common-workflows) |
105| "How do I trust it with my code?" | Introduce plan mode: pressing `Shift+Tab` cycles into it, Claude proposes exactly what it intends to change, and nothing is modified until the user approves. | [Permissions](/docs/en/permissions) |
106| "Is the setup worth the effort?" | Installation takes roughly two minutes, runs in the terminal, and requires no IDE extension. Running `/init` once is sufficient to begin working. | [Quickstart](/docs/en/quickstart) |
107| "It produced an incorrect result." | Encourage them to provide the failure back to Claude. Pasting the error message or failing test is far more effective than rephrasing the original request. | [Common workflows](/docs/en/common-workflows) |
108| "It does not understand our codebase conventions." | Suggest running `/init` to generate a `CLAUDE.md` file, then adding the team's conventions, test commands, and any directories that should be avoided. | [Memory](/docs/en/memory) |
109| "Is this just autocomplete?" | Offer a brief demonstration in which Claude explains an unfamiliar file, traces a bug across services, or drafts a migration plan. These tasks require reasoning across the repository rather than completing a single line. | A two-minute live demonstration |
110| "What about security and data handling?" | Refer this question to your administrator. Your organization's deployment and data-handling policy is already configured, and champions should not improvise this answer. | [Security](/docs/en/security) · [Data usage](/docs/en/data-usage) |
102| Question | Suggested response | Follow-up resource |
103| - | - | - |
104| "What should I try it on first?" | Recommend a real but contained task, ideally a bug or chore the person has been postponing because it is tedious rather than difficult. | [Common workflows](/docs/en/common-workflows) |
105| "How do I trust it with my code?" | Introduce plan mode: pressing `Shift+Tab` cycles into it, Claude proposes exactly what it intends to change, and nothing is modified until the user approves. | [Permissions](/docs/en/permissions) |
106| "Is the setup worth the effort?" | Installation takes roughly two minutes, runs in the terminal, and requires no IDE extension. Running `/init` once is sufficient to begin working. | [Quickstart](/docs/en/quickstart) |
107| "It produced an incorrect result." | Encourage them to provide the failure back to Claude. Pasting the error message or failing test is far more effective than rephrasing the original request. | [Common workflows](/docs/en/common-workflows) |
108| "It does not understand our codebase conventions." | Suggest running `/init` to generate a `CLAUDE.md` file, then adding the team's conventions, test commands, and any directories that should be avoided. | [Memory](/docs/en/memory) |
109| "Is this just autocomplete?" | Offer a brief demonstration in which Claude explains an unfamiliar file, traces a bug across services, or drafts a migration plan. These tasks require reasoning across the repository rather than completing a single line. | A two-minute live demonstration |
110| "What about security and data handling?" | Refer this question to your administrator. Your organization's deployment and data-handling policy is already configured, and champions should not improvise this answer. | [Security](/docs/en/security) · [Data usage](/docs/en/data-usage) |
111111 
112112## Grow the circle
113113 
from line 115
115115 
116116### Patterns that tend to work
117117 
118| Pattern | How to run it | Effort required |
119| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
120| A dedicated channel | Create a `#claude-code` channel (or a recurring thread in an existing one), pin the [Quickstart](/docs/en/quickstart) link and one strong example, and answer questions publicly so each answer benefits everyone watching. | About five minutes to set up, then ambient |
121| A weekly show-and-tell thread | Each Friday, post "What did Claude help you with this week?" No preparation, slides, or meeting are required; screenshots and short descriptions are sufficient. | About two minutes per week |
122| Share a custom skill | Post your most useful `.claude/skills/<name>/SKILL.md` file, for example a `/ship` skill that runs tests and lint before committing, with a one-line description. Because skills are plain Markdown, colleagues can adopt them immediately. | About five minutes per skill |
123| Generate a setup guide from your own usage | Run `/team-onboarding` in a project you have spent real time in. Claude scans your recent sessions, commands, and MCP servers, then produces a guide a new teammate can paste as their first message to replay your setup. Pin it in the channel. | About two minutes |
124| Pair on a first task | Offer a single fifteen-minute pairing session to anyone getting started. One successful outcome on their own code is more persuasive than any presentation. | About fifteen minutes per person |
125| Identify the next champion | The colleague who asks you the most questions is usually ready to take on this role. Forward them this page and divide the channel responsibilities between you. | Negligible |
118| Pattern | How to run it | Effort required |
119| - | - | - |
120| A dedicated channel | Create a `#claude-code` channel (or a recurring thread in an existing one), pin the [Quickstart](/docs/en/quickstart) link and one strong example, and answer questions publicly so each answer benefits everyone watching. | About five minutes to set up, then ambient |
121| A weekly show-and-tell thread | Each Friday, post "What did Claude help you with this week?" No preparation, slides, or meeting are required; screenshots and short descriptions are sufficient. | About two minutes per week |
122| Share a custom skill | Post your most useful `.claude/skills/<name>/SKILL.md` file, for example a `/ship` skill that runs tests and lint before committing, with a one-line description. Because skills are plain Markdown, colleagues can adopt them immediately. | About five minutes per skill |
123| Generate a setup guide from your own usage | Run `/team-onboarding` in a project you have spent real time in. Claude scans your recent sessions, commands, and MCP servers, then produces a guide a new teammate can paste as their first message to replay your setup. Pin it in the channel. | About two minutes |
124| Pair on a first task | Offer a single fifteen-minute pairing session to anyone getting started. One successful outcome on their own code is more persuasive than any presentation. | About fifteen minutes per person |
125| Identify the next champion | The colleague who asks you the most questions is usually ready to take on this role. Forward them this page and divide the channel responsibilities between you. | Negligible |
126126 
127127### Thirty-day playbook
128128 
from line 162
162162 
163163Healthy skepticism is expected; engineers should be cautious about tools that touch their code. The most effective response is rarely to argue the general case. Instead, acknowledge the concern, offer a brief reframe, and propose one concrete demonstration on the person's own code. Most concerns are resolved by a single successful experience.
164164 
165| Concern | Suggested response | Evidence to offer |
166| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- |
167| "I am faster without it." | That is likely true for code the person writes routinely. Suggest trying it on the work they tend to avoid: legacy files, unfamiliar services, or test scaffolding, where it helps the most. | Time one tedious task both ways and compare. |
168| "I do not trust AI to touch production code." | Agree that no change should land unread. Plan mode combined with normal diff review means nothing is applied that the engineer has not inspected, the same standard as any pull request. | Demonstrate plan mode on a real file. |
169| "It will make junior engineers weaker." | Used well, it is an effective explainer. Encourage junior engineers to ask Claude to explain a file and its call sites before asking it to change anything. | Run "Explain @file and where it is called from" together. |
170| "I tried it once and it hallucinated." | This is usually a context problem rather than a model problem. @-mentioning the relevant files, running `/init`, and providing the actual error output typically resolves it. | Re-run their original prompt with proper `@`-context. |
171| "We do not have time to learn another tool." | Claude Code is a terminal command rather than a platform. If it does not return value within the first session, it is reasonable to set it aside. | A two-minute install followed by one real bug. |
165| Concern | Suggested response | Evidence to offer |
166| - | - | - |
167| "I am faster without it." | That is likely true for code the person writes routinely. Suggest trying it on the work they tend to avoid: legacy files, unfamiliar services, or test scaffolding, where it helps the most. | Time one tedious task both ways and compare. |
168| "I do not trust AI to touch production code." | Agree that no change should land unread. Plan mode combined with normal diff review means nothing is applied that the engineer has not inspected, the same standard as any pull request. | Demonstrate plan mode on a real file. |
169| "It will make junior engineers weaker." | Used well, it is an effective explainer. Encourage junior engineers to ask Claude to explain a file and its call sites before asking it to change anything. | Run "Explain @file and where it is called from" together. |
170| "I tried it once and it hallucinated." | This is usually a context problem rather than a model problem. @-mentioning the relevant files, running `/init`, and providing the actual error output typically resolves it. | Re-run their original prompt with proper `@`-context. |
171| "We do not have time to learn another tool." | Claude Code is a terminal command rather than a platform. If it does not return value within the first session, it is reasonable to set it aside. | A two-minute install followed by one real bug. |
172172 
173173## Quick-reference sheet
174174 
175175The techniques below are the ones that most reliably move someone from a first trial to daily use. Pin this table in a channel or share it on its own.
176176 
177| Technique | How to apply it |
178| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
179| Provide the right context | Use `@file` or `@directory/` references, or paste the error or log output directly. Supplying relevant context is more effective than elaborate prompting. |
180| Review the plan before the edit | Press `Shift+Tab` to enter plan mode. Claude will describe the intended changes for your approval before executing them. |
181| Teach it your repository | Run `/init` to generate a `CLAUDE.md` file, then add your conventions, test commands, and any directories that should not be modified. See [Memory](/docs/en/memory). |
182| Reuse a workflow | Save a `SKILL.md` file in `.claude/skills/<name>/` to create a `/name` skill that the entire team can use. See [Skills](/docs/en/skills). |
183| Stay informed during long tasks | Configure a Stop hook to receive a desktop notification when a long-running task completes. See [Hooks](/docs/en/hooks-guide). |
184| Recover from an incorrect result | Rather than rephrasing the request, paste the failing test or stack trace back to Claude and ask it to address that specific failure. |
185| Keep edits surgical | Ask for a diff, or specify "only change X." Claude respects scope when scope is stated. |
177| Technique | How to apply it |
178| - | - |
179| Provide the right context | Use `@file` or `@directory/` references, or paste the error or log output directly. Supplying relevant context is more effective than elaborate prompting. |
180| Review the plan before the edit | Press `Shift+Tab` to enter plan mode. Claude will describe the intended changes for your approval before executing them. |
181| Teach it your repository | Run `/init` to generate a `CLAUDE.md` file, then add your conventions, test commands, and any directories that should not be modified. See [Memory](/docs/en/memory). |
182| Reuse a workflow | Save a `SKILL.md` file in `.claude/skills/<name>/` to create a `/name` skill that the entire team can use. See [Skills](/docs/en/skills). |
183| Stay informed during long tasks | Configure a Stop hook to receive a desktop notification when a long-running task completes. See [Hooks](/docs/en/hooks-guide). |
184| Recover from an incorrect result | Rather than rephrasing the request, paste the failing test or stack trace back to Claude and ask it to address that specific failure. |
185| Keep edits surgical | Ask for a diff, or specify "only change X." Claude respects scope when scope is stated. |
186186 
187187<Tip>
188188 Claude Code is updated frequently. Verify version-specific details against the [documentation home page](/docs/en/overview) before distributing this material internally.

channels Changed · +10 / -10 lines

from line 303
303303 
304304In all cases, no channel runs until a user opts it in for the session with `--channels`.
305305 
306| Setting | Purpose | When not configured |
307| :---------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
308| `channelsEnabled` | Master switch. Must be `true` for any channel to deliver messages. Blocks all channels including the development flag when off. See [Enable channels for your organization](#enable-channels-for-your-organization). | claude.ai Team and Enterprise: channels blocked. Console: channels allowed unless your organization deploys managed settings, in which case channels are blocked until this key is set |
309| `allowedChannelPlugins` | Which plugins can register once channels are enabled. Replaces the Anthropic-maintained list when set. | Anthropic default list applies |
306| Setting | Purpose | When not configured |
307| :- | :- | :- |
308| `channelsEnabled` | Master switch. Must be `true` for any channel to deliver messages. Blocks all channels including the development flag when off. See [Enable channels for your organization](#enable-channels-for-your-organization). | claude.ai Team and Enterprise: channels blocked. Console: channels allowed unless your organization deploys managed settings, in which case channels are blocked until this key is set |
309| `allowedChannelPlugins` | Which plugins can register once channels are enabled. Replaces the Anthropic-maintained list when set. | Anthropic default list applies |
310310 
311311Pro and Max users without an organization skip these checks entirely: channels are available and users opt in per session with `--channels`.
312312 
from line 351
351351 
352352Several Claude Code features connect to systems outside the terminal, each suited to a different kind of work:
353353 
354| Feature | What it does | Good for |
355| -------------------------------------------- | ----------------------------------------------------------------------- | --------------------------------------------------------- |
356| [Cloud sessions](/docs/en/claude-code-on-the-web) | Run tasks in a fresh cloud sandbox, cloned from GitHub | Delegating self-contained async work you check on later |
357| [Claude in Slack](/docs/en/slack) | Spawns a cloud session from an `@Claude` mention in a channel or thread | Starting tasks directly from team conversation context |
358| Standard [MCP server](/docs/en/mcp) | Claude queries it during a task; nothing is pushed to the session | Giving Claude on-demand access to read or query a system |
359| [Remote Control](/docs/en/remote-control) | You drive your local session from claude.ai or the Claude mobile app | Steering an in-progress session while away from your desk |
354| Feature | What it does | Good for |
355| - | - | - |
356| [Cloud sessions](/docs/en/claude-code-on-the-web) | Run tasks in a fresh cloud sandbox, cloned from GitHub | Delegating self-contained async work you check on later |
357| [Claude in Slack](/docs/en/slack) | Spawns a cloud session from an `@Claude` mention in a channel or thread | Starting tasks directly from team conversation context |
358| Standard [MCP server](/docs/en/mcp) | Claude queries it during a task; nothing is pushed to the session | Giving Claude on-demand access to read or query a system |
359| [Remote Control](/docs/en/remote-control) | You drive your local session from claude.ai or the Claude mobile app | Steering an in-progress session while away from your desk |
360360 
361361Channels fill the gap in that list by pushing events from non-Claude sources into your already-running local session.
362362 

channels-reference Changed · +15 / -15 lines

from line 189
189189 
190190A channel sets these options in the [`Server`](https://modelcontextprotocol.io/docs/learn/server-concepts) constructor. The `instructions` and `capabilities.tools` fields are [standard MCP](https://modelcontextprotocol.io/docs/learn/server-concepts); `capabilities.experimental['claude/channel']` and `capabilities.experimental['claude/channel/permission']` are the channel-specific additions:
191191 
192| Field | Type | Description |
193| :------------------------------------------------------- | :------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
194| `capabilities.experimental['claude/channel']` | `object` | Required. Always `{}`. Presence registers the notification listener. |
192| Field | Type | Description |
193| :- | :- | :- |
194| `capabilities.experimental['claude/channel']` | `object` | Required. Always `{}`. Presence registers the notification listener. |
195195| `capabilities.experimental['claude/channel/permission']` | `object` or `false` | Optional. Set it to `{}` to declare that this channel can receive permission relay requests. When declared, Claude Code forwards tool approval prompts to your channel so you can approve or deny them remotely. To opt out, omit the key or set it to `false`. Before v2.1.234, Claude Code treated `false` as declared. See [Relay permission prompts](#relay-permission-prompts). |
196| `capabilities.tools` | `object` | Two-way only. Always `{}`. Standard MCP tool capability. See [Expose a reply tool](#expose-a-reply-tool). |
197| `instructions` | `string` | Recommended. Claude Code delivers it to Claude as context when the server connects. Tell Claude what events to expect, what the `<channel>` tag attributes mean, whether to reply, and if so which tool to use and which attribute to pass back (like `chat_id`). |
196| `capabilities.tools` | `object` | Two-way only. Always `{}`. Standard MCP tool capability. See [Expose a reply tool](#expose-a-reply-tool). |
197| `instructions` | `string` | Recommended. Claude Code delivers it to Claude as context when the server connects. Tell Claude what events to expect, what the `<channel>` tag attributes mean, whether to reply, and if so which tool to use and which attribute to pass back (like `chat_id`). |
198198 
199199To create a one-way channel, omit `capabilities.tools`. This example shows a two-way setup with the channel capability, tools, and instructions set:
200200 
from line 218
218218 
219219Your server emits `notifications/claude/channel` with two params:
220220 
221| Field | Type | Description |
222| :-------- | :----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
223| `content` | `string` | The event body. Delivered as the body of the `<channel>` tag. |
224| `meta` | `Record<string, string>` | Optional. Each entry becomes an attribute on the `<channel>` tag for routing context like chat ID, sender name, or alert severity. Keys must be identifiers: letters, digits, and underscores only. Keys containing hyphens or other characters are silently dropped. |
221| Field | Type | Description |
222| :- | :- | :- |
223| `content` | `string` | The event body. Delivered as the body of the `<channel>` tag. |
224| `meta` | `Record<string, string>` | Optional. Each entry becomes an attribute on the `<channel>` tag for routing context like chat ID, sender name, or alert severity. Keys must be identifiers: letters, digits, and underscores only. Keys containing hyphens or other characters are silently dropped. |
225225 
226226Your server pushes events by calling `mcp.notification()` on the `Server` instance. This example pushes a CI failure alert with two meta keys:
227227 
from line 458
458458 
459459The outbound notification from Claude Code is `notifications/claude/channel/permission_request`. Like the [channel notification](#notification-format), the transport is standard MCP but the method and schema are Claude Code extensions. The `params` object has four string fields your server formats into the outgoing prompt:
460460 
461| Field | Description |
462| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
463| `request_id` | Five lowercase letters drawn from `a`-`z` without `l`, so it never reads as a `1` or `I` when typed on a phone. Include it in your outgoing prompt so it can be echoed in the reply. Claude Code only accepts a verdict that carries an ID it issued. The local terminal dialog doesn't display this ID, so your outbound handler is the only way to learn it. |
464| `tool_name` | Name of the tool Claude wants to use, for example `Bash` or `Write`. |
465| `description` | Human-readable summary of what this specific tool call does, never the command itself. For a Bash call this is Claude's description of the command; when the model gives no description, the field is the constant `Run shell command` and carries zero command detail. Render `input_preview` when you have room. |
466| `input_preview` | The tool's arguments as JSON-shaped display text, keyed per top-level field. For Bash this is the command; for Write, the file path and the content. Omit it from your prompt if you only have room for a one-line message. Your server decides what to show. |
461| Field | Description |
462| - | - |
463| `request_id` | Five lowercase letters drawn from `a`-`z` without `l`, so it never reads as a `1` or `I` when typed on a phone. Include it in your outgoing prompt so it can be echoed in the reply. Claude Code only accepts a verdict that carries an ID it issued. The local terminal dialog doesn't display this ID, so your outbound handler is the only way to learn it. |
464| `tool_name` | Name of the tool Claude wants to use, for example `Bash` or `Write`. |
465| `description` | Human-readable summary of what this specific tool call does, never the command itself. For a Bash call this is Claude's description of the command; when the model gives no description, the field is the constant `Run shell command` and carries zero command detail. Render `input_preview` when you have room. |
466| `input_preview` | The tool's arguments as JSON-shaped display text, keyed per top-level field. For Bash this is the command; for Write, the file path and the content. Omit it from your prompt if you only have room for a one-line message. Your server decides what to show. |
467467 
468468Clients on Claude Code v2.1.211 or later sanitize `description` and `input_preview` before relaying them. Expect three changes in the text you receive:
469469 

chrome Changed · +6 / -6 lines

from line 277
277277 
278278These are the most frequently encountered errors and how to resolve them:
279279 
280| Error | Cause | Fix |
281| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
282| "Browser extension is not connected" | Native messaging host cannot reach the extension, or your organization's IP allowlist rejects the connection to `bridge.claudeusercontent.com` | Restart Chrome and Claude Code, then run `/chrome` to reconnect. If your organization uses IP allowlisting and the error persists, see [Organization IP allowlists and proxy egress](/docs/en/network-config#organization-ip-allowlists-and-proxy-egress) |
283| Extension shows "Not detected" in `/chrome` | Chrome extension is not installed or is disabled | Install or enable the extension in `chrome://extensions` |
284| "No tab available" | Claude tried to act before a tab was ready | Ask Claude to create a new tab and retry |
285| "Receiving end does not exist" | Extension service worker went idle | Run `/chrome` and select "Reconnect extension" |
280| Error | Cause | Fix |
281| - | - | - |
282| "Browser extension is not connected" | Native messaging host cannot reach the extension, or your organization's IP allowlist rejects the connection to `bridge.claudeusercontent.com` | Restart Chrome and Claude Code, then run `/chrome` to reconnect. If your organization uses IP allowlisting and the error persists, see [Organization IP allowlists and proxy egress](/docs/en/network-config#organization-ip-allowlists-and-proxy-egress) |
283| Extension shows "Not detected" in `/chrome` | Chrome extension is not installed or is disabled | Install or enable the extension in `chrome://extensions` |
284| "No tab available" | Claude tried to act before a tab was ready | Ask Claude to create a new tab and retry |
285| "Receiving end does not exist" | Extension service worker went idle | Run `/chrome` and select "Reconnect extension" |
286286 
287287## See also
288288 

claude-apps-gateway Changed · +31 / -31 lines

from line 59
5959 
6060Have these in place before you start:
6161 
62| You need | Details |
63| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
64| Claude Code v2.1.195 or later | The `claude gateway` subcommand and the gateway sign-in flow ship in v2.1.195. Earlier public builds don't include them. Both the machine running the gateway server and each developer's machine must be on v2.1.195 or later; run `claude update` to get the latest release. The [Claude Platform on AWS upstream](/docs/en/claude-apps-gateway-config#claude-platform-on-aws) requires Claude Code v2.1.198 or later on the gateway server. |
65| OpenID Connect (OIDC) identity provider | Okta, Microsoft Entra ID, Google Workspace, Keycloak, or Dex, or any other OIDC-compliant IdP such as PingFederate. The gateway runs standard OIDC discovery and the authorization-code flow against it. SAML and LDAP aren't supported. |
66| PostgreSQL 14 or later | Backs the device sign-in flow, where the browser callback writes and the polling CLI reads, plus rate-limit counters. Any managed Postgres works, including the smallest tier. Without spend limits configured, the gateway stores a few KB of short-lived auth state; with [spend limits](/docs/en/claude-apps-gateway-spend-limits), it also holds durable spend, audit, and identity tables that should be backed up. TLS via `?sslmode=require` is recommended. |
67| Model upstream | Amazon Bedrock credentials, Claude Platform on AWS credentials, Google Cloud credentials, a Microsoft Foundry resource, or an Anthropic API key. Multiple upstreams are supported with failover. |
68| HTTPS | The gateway must be reachable over `https://` from developer laptops and from any browser used for sign-in; the gateway serves the device-verification page on the same listener. Either provide a TLS cert via `listen.tls` or run behind a TLS-terminating ingress, and set `listen.public_url` to the external origin in both cases. At `/login`, Claude Code accepts a plain `http://` origin only when the gateway host is loopback: `localhost`, `127.0.0.1`, or `::1`. |
69| Private-network address | At `/login`, Claude Code requires the gateway's hostname or IP address to resolve only to private addresses: RFC 1918, link-local, CGNAT `100.64.0.0/10`, IPv6 ULA `fc00::/7`, or loopback. For a gateway you host, any public address outside a block you declare is rejected; see the [threat model](/docs/en/claude-apps-gateway-deploy#threat-model-summary) in the deployment guide. If developer machines route HTTPS through a corporate proxy, sign-in also requires the proxy host to resolve to private addresses; if it doesn't, add the gateway host to `NO_PROXY` so the CLI connects directly. If your internal network is numbered from public IPv4 space your organization owns, [declare those blocks](#allow-a-gateway-on-public-address-space-you-own) so `/login` accepts a gateway there. |
70| Linux runtime | The gateway server runs only on the native Linux binary. macOS works for local development. Windows isn't supported as a server platform. |
62| You need | Details |
63| - | - |
64| Claude Code v2.1.195 or later | The `claude gateway` subcommand and the gateway sign-in flow ship in v2.1.195. Earlier public builds don't include them. Both the machine running the gateway server and each developer's machine must be on v2.1.195 or later; run `claude update` to get the latest release. The [Claude Platform on AWS upstream](/docs/en/claude-apps-gateway-config#claude-platform-on-aws) requires Claude Code v2.1.198 or later on the gateway server. |
65| OpenID Connect (OIDC) identity provider | Okta, Microsoft Entra ID, Google Workspace, Keycloak, or Dex, or any other OIDC-compliant IdP such as PingFederate. The gateway runs standard OIDC discovery and the authorization-code flow against it. SAML and LDAP aren't supported. |
66| PostgreSQL 14 or later | Backs the device sign-in flow, where the browser callback writes and the polling CLI reads, plus rate-limit counters. Any managed Postgres works, including the smallest tier. Without spend limits configured, the gateway stores a few KB of short-lived auth state; with [spend limits](/docs/en/claude-apps-gateway-spend-limits), it also holds durable spend, audit, and identity tables that should be backed up. TLS via `?sslmode=require` is recommended. |
67| Model upstream | Amazon Bedrock credentials, Claude Platform on AWS credentials, Google Cloud credentials, a Microsoft Foundry resource, or an Anthropic API key. Multiple upstreams are supported with failover. |
68| HTTPS | The gateway must be reachable over `https://` from developer laptops and from any browser used for sign-in; the gateway serves the device-verification page on the same listener. Either provide a TLS cert via `listen.tls` or run behind a TLS-terminating ingress, and set `listen.public_url` to the external origin in both cases. At `/login`, Claude Code accepts a plain `http://` origin only when the gateway host is loopback: `localhost`, `127.0.0.1`, or `::1`. |
69| Private-network address | At `/login`, Claude Code requires the gateway's hostname or IP address to resolve only to private addresses: RFC 1918, link-local, CGNAT `100.64.0.0/10`, IPv6 ULA `fc00::/7`, or loopback. For a gateway you host, any public address outside a block you declare is rejected; see the [threat model](/docs/en/claude-apps-gateway-deploy#threat-model-summary) in the deployment guide. If developer machines route HTTPS through a corporate proxy, sign-in also requires the proxy host to resolve to private addresses; if it doesn't, add the gateway host to `NO_PROXY` so the CLI connects directly. If your internal network is numbered from public IPv4 space your organization owns, [declare those blocks](#allow-a-gateway-on-public-address-space-you-own) so `/login` accepts a gateway there. |
70| Linux runtime | The gateway server runs only on the native Linux binary. macOS works for local development. Windows isn't supported as a server platform. |
7171 
7272### Steps
7373 
from line 473
473473 
474474The gateway delivers the [`anthropic-beta`](https://platform.claude.com/docs/en/api/beta-headers) values the CLI sends to every upstream, so operators don't maintain a beta allowlist. For Amazon Bedrock, which ignores the header, the gateway moves the values into the request body's `anthropic_beta` field; the other upstreams receive the header as sent.
475475 
476| Feature | Status | Notes |
477| -------------------------------------------------------------------------------------------------------------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
478| Inference forwarding (Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform, Microsoft Foundry, Anthropic) | Available | With per-upstream model translation and failover. The Amazon Bedrock upstream uses the `bedrock-runtime` endpoint and the AWS default credential chain; the Amazon Bedrock [Mantle endpoint](/docs/en/amazon-bedrock#use-the-mantle-endpoint) is not a supported upstream. The [Claude Platform on AWS upstream](/docs/en/claude-apps-gateway-config#claude-platform-on-aws) requires Claude Code v2.1.198 or later on the gateway server. |
479| Model access and managed settings by IdP group | Available | Model access is enforced server-side; managed settings are delivered per IdP group and applied by the CLI at the [managed settings tier](/docs/en/settings#settings-precedence) |
480| Claude Desktop | Available with opt-in | The gateway serves Claude Desktop's configuration at `/user/bootstrap` once a policy [opts in with a `desktop` key](/docs/en/claude-apps-gateway-config#claude-desktop-overlay), and Claude Desktop sends model requests from its Cowork and Code tabs, and from the Chat tab when you enable it, through the gateway. To turn on the Chat tab, see [Connect Claude Desktop](#connect-claude-desktop). Requires Claude Code v2.1.203 or later on the gateway server. |
481| Telemetry fan-out (OTLP/HTTP) | Available | Identity-stamped per export; both protobuf and JSON encodings |
482| OIDC identity providers | Available | Any OIDC-compliant IdP; the gateway runs standard OIDC discovery and the authorization-code flow. See [Identity provider setup](/docs/en/claude-apps-gateway-deploy#identity-provider-setup) for per-IdP configuration |
483| Per-user and per-group spend limits | Available | See [Spend limits](/docs/en/claude-apps-gateway-spend-limits) |
484| Server-side web search | Not available | The CLI can't see which upstream provider the gateway routes to, so it can't verify web search support and disables WebSearch on gateway sessions |
485| [Remote Control](/docs/en/remote-control) | Not available | The CLI shows [an error naming the gateway](/docs/en/errors#remote-control-requires-the-anthropic-api) |
486| [`/design-sync`](/docs/en/commands#all-commands) and `/design-login` | Not available | Both need claude.ai, which the CLI doesn't contact on gateway sessions, so neither command appears there |
487| Features that need feature-flag fetching, such as `/import` and `claude import` | Not available | The CLI skips the flag fetch on gateway sessions. [Features that need feature-flag fetching](/docs/en/env-vars#features-that-need-feature-flag-fetching) lists what that turns off |
488| Standard prompt caching | Available | The gateway forwards `cache_control` breakpoints to every upstream. [Where the cache lives](/docs/en/prompt-caching#where-the-cache-lives) covers which blocks the CLI marks, including the system context it appends mid-conversation |
489| 1-hour cache TTL | Not available | The CLI omits the extended-cache-ttl beta on gateway sessions, because not every upstream the gateway can route to supports the 1-hour TTL, so prompt caching through the gateway uses the 5-minute TTL; see the beta-header note above |
490| Auto mode | Available | Follows the [third-party provider rules](/docs/en/permission-modes#enable-auto-mode-on-bedrock-agent-platform-or-foundry): only the models eligible on third-party providers can use it. Before v2.1.207, auto mode on gateway sessions required setting `CLAUDE_CODE_ENABLE_AUTO_MODE=1`, deliverable through the managed policy `env` block |
491| First-party-only optimizations such as global cache scope and token-efficient tools | Not available | The CLI doesn't enable them on gateway sessions; see the beta-header note above |
492| OTLP/gRPC | Not supported | OTLP over HTTP only |
493| SAML, LDAP, and other non-OIDC auth | Not supported | OIDC only. Front with an OIDC bridge if needed |
494| Multi-tenant (multiple OIDC issuers) | Not supported | One issuer per gateway. Run separate instances |
495| Windows server | Not supported | Deploy on Linux. macOS for local development only |
496| Helm chart | Not available | The gateway runs as a standard stateless Deployment; see the [deployment guide](/docs/en/claude-apps-gateway-deploy#kubernetes) |
497| Admin UI | Not available | Configuration is the YAML file; redeploy to change it |
476| Feature | Status | Notes |
477| - | - | - |
478| Inference forwarding (Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform, Microsoft Foundry, Anthropic) | Available | With per-upstream model translation and failover. The Amazon Bedrock upstream uses the `bedrock-runtime` endpoint and the AWS default credential chain; the Amazon Bedrock [Mantle endpoint](/docs/en/amazon-bedrock#use-the-mantle-endpoint) is not a supported upstream. The [Claude Platform on AWS upstream](/docs/en/claude-apps-gateway-config#claude-platform-on-aws) requires Claude Code v2.1.198 or later on the gateway server. |
479| Model access and managed settings by IdP group | Available | Model access is enforced server-side; managed settings are delivered per IdP group and applied by the CLI at the [managed settings tier](/docs/en/settings#settings-precedence) |
480| Claude Desktop | Available with opt-in | The gateway serves Claude Desktop's configuration at `/user/bootstrap` once a policy [opts in with a `desktop` key](/docs/en/claude-apps-gateway-config#claude-desktop-overlay), and Claude Desktop sends model requests from its Cowork and Code tabs, and from the Chat tab when you enable it, through the gateway. To turn on the Chat tab, see [Connect Claude Desktop](#connect-claude-desktop). Requires Claude Code v2.1.203 or later on the gateway server. |
481| Telemetry fan-out (OTLP/HTTP) | Available | Identity-stamped per export; both protobuf and JSON encodings |
482| OIDC identity providers | Available | Any OIDC-compliant IdP; the gateway runs standard OIDC discovery and the authorization-code flow. See [Identity provider setup](/docs/en/claude-apps-gateway-deploy#identity-provider-setup) for per-IdP configuration |
483| Per-user and per-group spend limits | Available | See [Spend limits](/docs/en/claude-apps-gateway-spend-limits) |
484| Server-side web search | Not available | The CLI can't see which upstream provider the gateway routes to, so it can't verify web search support and disables WebSearch on gateway sessions |
485| [Remote Control](/docs/en/remote-control) | Not available | The CLI shows [an error naming the gateway](/docs/en/errors#remote-control-requires-the-anthropic-api) |
486| [`/design-sync`](/docs/en/commands#all-commands) and `/design-login` | Not available | Both need claude.ai, which the CLI doesn't contact on gateway sessions, so neither command appears there |
487| Features that need feature-flag fetching, such as `/import` and `claude import` | Not available | The CLI skips the flag fetch on gateway sessions. [Features that need feature-flag fetching](/docs/en/env-vars#features-that-need-feature-flag-fetching) lists what that turns off |
488| Standard prompt caching | Available | The gateway forwards `cache_control` breakpoints to every upstream. [Where the cache lives](/docs/en/prompt-caching#where-the-cache-lives) covers which blocks the CLI marks, including the system context it appends mid-conversation |
489| 1-hour cache TTL | Not available | The CLI omits the extended-cache-ttl beta on gateway sessions, because not every upstream the gateway can route to supports the 1-hour TTL, so prompt caching through the gateway uses the 5-minute TTL; see the beta-header note above |
490| Auto mode | Available | Follows the [third-party provider rules](/docs/en/permission-modes#enable-auto-mode-on-bedrock-agent-platform-or-foundry): only the models eligible on third-party providers can use it. Before v2.1.207, auto mode on gateway sessions required setting `CLAUDE_CODE_ENABLE_AUTO_MODE=1`, deliverable through the managed policy `env` block |
491| First-party-only optimizations such as global cache scope and token-efficient tools | Not available | The CLI doesn't enable them on gateway sessions; see the beta-header note above |
492| OTLP/gRPC | Not supported | OTLP over HTTP only |
493| SAML, LDAP, and other non-OIDC auth | Not supported | OIDC only. Front with an OIDC bridge if needed |
494| Multi-tenant (multiple OIDC issuers) | Not supported | One issuer per gateway. Run separate instances |
495| Windows server | Not supported | Deploy on Linux. macOS for local development only |
496| Helm chart | Not available | The gateway runs as a standard stateless Deployment; see the [deployment guide](/docs/en/claude-apps-gateway-deploy#kubernetes) |
497| Admin UI | Not available | Configuration is the YAML file; redeploy to change it |
498498 
499499## Next steps
500500 

claude-apps-gateway-config Changed · +140 / -140 lines

from line 37
3737 
3838Don't write secrets such as `client_secret`, `jwt_secret`, or `postgres_url` directly in `gateway.yaml`. Reference them with one of the forms below, and the gateway resolves the value at boot from an environment variable or a file:
3939 
40| Form | Resolves to | Use for |
41| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
42| `${VAR}` | The environment variable `VAR`. Boot fails if undefined. | Container environment variables, AWS Secrets Manager via env injection |
43| `${file:/path}` | Contents of the file at that absolute path, trimmed. The reference must be the field's entire value: unlike `${VAR}`, it isn't expanded inside a longer string, so for a database password set `store.password` rather than embedding it in `postgres_url`. | Kubernetes Secret volume mounts, Vault Agent, SOPS |
40| Form | Resolves to | Use for |
41| - | - | - |
42| `${VAR}` | The environment variable `VAR`. Boot fails if undefined. | Container environment variables, AWS Secrets Manager via env injection |
43| `${file:/path}` | Contents of the file at that absolute path, trimmed. The reference must be the field's entire value: unlike `${VAR}`, it isn't expanded inside a longer string, so for a database password set `store.password` rather than embedding it in `postgres_url`. | Kubernetes Secret volume mounts, Vault Agent, SOPS |
4444 
4545## Required sections
4646 
from line 48
4848 
4949The `listen` block controls where the gateway serves: the bind address and port, the externally visible origin, and optional TLS termination.
5050 
51| Field | Required | Description |
52| ---------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
53| `host` | No | Bind address. Default `0.0.0.0`. |
54| `port` | No | Bind port. Default `8080`. |
55| `public_url` | Unless `host` is loopback | The externally visible `https://` origin, used to build the IdP `redirect_uri` and discovery metadata. Required whenever `host` isn't a loopback address, whether TLS terminates at a proxy such as an ALB, Ingress, or Cloud Run or at the gateway itself through `tls`, because the gateway never derives its own origin from `X-Forwarded-*` headers; they are client-spoofable. Boot fails without it. `trusted_proxies` below governs client-IP resolution only. Also required to enable [telemetry](#telemetry), because the gateway builds the OTLP endpoint it pushes to clients from this URL. |
56| `tls.cert` / `tls.key` | No | PEM paths if the gateway terminates TLS itself |
57| `trusted_proxies` | No | CIDRs or IPs of load balancers in front of the gateway. When set, the gateway trusts `X-Forwarded-For` only from these peers and records the real client IP for per-IP rate limiting and audit. Equivalent to nginx `set_real_ip_from`. `X-Forwarded-For` entries written as `ipv4:port` or `[ipv6]:port`, as some load balancers do, are read with the port dropped. An IPv6 address with a port appended and no brackets may be read as a different address or not read at all, so turn off the port option on any proxy that writes that form. |
51| Field | Required | Description |
52| - | - | - |
53| `host` | No | Bind address. Default `0.0.0.0`. |
54| `port` | No | Bind port. Default `8080`. |
55| `public_url` | Unless `host` is loopback | The externally visible `https://` origin, used to build the IdP `redirect_uri` and discovery metadata. Required whenever `host` isn't a loopback address, whether TLS terminates at a proxy such as an ALB, Ingress, or Cloud Run or at the gateway itself through `tls`, because the gateway never derives its own origin from `X-Forwarded-*` headers; they are client-spoofable. Boot fails without it. `trusted_proxies` below governs client-IP resolution only. Also required to enable [telemetry](#telemetry), because the gateway builds the OTLP endpoint it pushes to clients from this URL. |
56| `tls.cert` / `tls.key` | No | PEM paths if the gateway terminates TLS itself |
57| `trusted_proxies` | No | CIDRs or IPs of load balancers in front of the gateway. When set, the gateway trusts `X-Forwarded-For` only from these peers and records the real client IP for per-IP rate limiting and audit. Equivalent to nginx `set_real_ip_from`. `X-Forwarded-For` entries written as `ipv4:port` or `[ipv6]:port`, as some load balancers do, are read with the port dropped. An IPv6 address with a port appended and no brackets may be read as a different address or not read at all, so turn off the port option on any proxy that writes that form. |
5858 
5959### `oidc`
6060 
from line 62
6262 
6363OpenID Connect (OIDC) is the SSO protocol the gateway uses with your identity provider; see [Identity provider setup](/docs/en/claude-apps-gateway-deploy#identity-provider-setup) for what to register on the IdP side.
6464 
65| Field | Required | Description |
66| ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
67| `issuer` | Yes | OIDC discovery base. Must serve discovery at `/.well-known/openid-configuration`. Use HTTPS in production; the gateway accepts an `http://` issuer. A loopback issuer such as `http://localhost:8081` is rejected by the [SSRF guard](/docs/en/claude-apps-gateway-deploy#threat-model-summary) unless `CLAUDE_GATEWAY_ALLOW_LOOPBACK=1` is set in the gateway's environment. |
68| `client_id` / `client_secret` | Yes | From your OAuth client registration |
69| `allowed_email_domains` | No | Reject id\_tokens whose `email` claim isn't in one of these domains, case-insensitive. Defense-in-depth against multi-tenant IdP misconfiguration. Independent of this setting, an id\_token whose `email_verified` claim is explicitly `false` is always rejected. |
70| `allowed_groups` | No | Restrict sign-in to members of these IdP groups, matched against `groups_claim`. A user in an allowed email domain but in none of these groups is rejected. Requires the IdP to emit the groups claim. Matching is an exact, case-sensitive string comparison against the values in that claim, and the gateway doesn't expand nested groups: to admit members of a sub-group, list the sub-group here or configure the IdP to emit flattened membership. |
71| `groups_claim` | No | Which id\_token claim carries group membership. Default `groups`. Microsoft Entra emits app roles under `roles`. Accepts a flat key or an RFC 6901 JSON Pointer such as `/resource_access/gateway/roles` for nested claims. |
72| `google_groups` | No | Look up the signed-in user's groups through the Google Workspace Admin SDK Directory API, because Google's id\_token carries no groups claim. Set `service_account_json_path` to a service-account key file with domain-wide delegation on the `https://www.googleapis.com/auth/admin.directory.group.readonly` scope, and `admin_email` to a Workspace administrator the service account impersonates; the Directory API requires a real admin subject. Each user's group email addresses become their groups claim, so `allowed_groups` and `managed.policies.match.groups` match on group emails. |
73| `email_claim` | No | Which id\_token claim carries the user's email. Default `email`. Some IdPs, such as ADFS and Entra B2C, emit `upn` or `preferred_username` instead. Accepts a flat key, a JSON Pointer, or a list of fallback keys where the first present key is used. |
74| `scopes` | No | Full override of the OIDC scopes the gateway requests. Default `[openid, profile, email, offline_access]`. Set when your IdP rejects scopes it doesn't recognize, or requires a custom scope to emit groups or email. Must include `openid`. Dropping `offline_access` disables refresh tokens, so developers re-run the browser login every `session.ttl_hours`. See [Identity provider setup](/docs/en/claude-apps-gateway-deploy#identity-provider-setup) for per-IdP scope recipes such as Google's refresh-token flow. |
75| `scope_on_refresh` | No | Also send `scope`, with the same list as the sign-in request, when the gateway exchanges a refresh token. Default `false`: the refresh request omits `scope`. Most IdPs return an id\_token on every refresh and don't need this. Set `true` when your IdP returns an id\_token on refresh only if asked for `openid` again, which Okta documents for its refresh grant. Without an id\_token, every refresh depends on the IdP's userinfo endpoint accepting the refreshed access token. If you gate sign-in or match policies on groups and your IdP's refresh-time id\_token omits them, also set `userinfo_fallback: true` so the gateway fills them from the userinfo endpoint. An IdP that granted fewer scopes than requested can reject the refresh with `invalid_scope`, including for existing sessions if you add entries to `scopes` while this is on. Unset the key if refreshes start failing at `token_endpoint` after you set it. Requires Claude Code v2.1.260 or later on the gateway server. |
76| `extra_auth_params` | No | Extra query parameters appended to the IdP authorization request, verbatim. This is the override mechanism for IdP-specific behavior, such as `access_type: offline` for Google refresh tokens, `domain_hint` for some Entra tenants, or `acr_values` for step-up flows. Cannot override the gateway-managed protocol params: `state`, `nonce`, `redirect_uri`, PKCE, `scope`, `response_type`, `response_mode`, and `client_id`. |
77| `userinfo_fallback` | No | When the id\_token omits email or groups, fetch them from `/userinfo`. Needed for Keycloak lightweight access tokens, the Okta org server, and ADFS minimal tokens. The id\_token stays authoritative; userinfo only fills gaps. Default `false`. |
78| `use_pkce` | No | Send a PKCE (S256) challenge on the authorization request. Default `true`. Set `false` only if your IdP rejects PKCE for this confidential client. |
79| `clock_skew_seconds` | No | Tolerate clock drift when validating id\_token time claims. Default `0`, which is strict. Raise if you see "token expired / not yet valid" errors right after sign-in due to host/IdP clock skew. |
80| `token_endpoint_auth_method` | No | Override the token-endpoint auth method. Accepts `client_secret_basic` or `client_secret_post`. Auto-negotiated by default. |
81| `id_token_signed_response_alg` | No | Expected id\_token signing algorithm. Default `RS256`. Set for IdPs that sign with ES256, PS256, or EdDSA. |
82| `additional_authorized_parties` | No | Extra `azp` values to accept beyond `client_id`, for Keycloak broker and token-exchange flows |
83| `discovery_url` | No | Fetch the discovery document from this URL instead of deriving it from `issuer`, for IdPs behind a proxy that rewrites the issuer host. The path must contain `/.well-known/`. |
84| `use_proxy` | No | Send the gateway's own IdP requests through the forward proxy in `HTTPS_PROXY` or `HTTP_PROXY`, honoring `NO_PROXY`. `false` keeps those requests direct. Requires v2.1.227 or later; see [IdP requests through a forward proxy](#idp-requests-through-a-forward-proxy) below. |
85| `form_action_origins` | No | Additional origins for the `/device` page's `Content-Security-Policy: form-action` directive. The gateway already allows `'self'` and the discovered `authorization_endpoint` origin, but Chrome enforces `form-action` against the entire redirect chain. If your IdP redirects through a second host, such as Azure AD federated to ADFS, hub-spoke Okta, or a corporate SSO interceptor, list every origin the authorization request may redirect through. |
86| `ca_cert_pem` | No | The PEM-encoded CA certificate itself, not a path to a file. It replaces the system trust store for IdP requests only. To load a mounted file, write `${file:/etc/gateway/idp-ca.pem}`. Use for Keycloak or Dex behind corporate PKI. |
65| Field | Required | Description |
66| - | - | - |
67| `issuer` | Yes | OIDC discovery base. Must serve discovery at `/.well-known/openid-configuration`. Use HTTPS in production; the gateway accepts an `http://` issuer. A loopback issuer such as `http://localhost:8081` is rejected by the [SSRF guard](/docs/en/claude-apps-gateway-deploy#threat-model-summary) unless `CLAUDE_GATEWAY_ALLOW_LOOPBACK=1` is set in the gateway's environment. |
68| `client_id` / `client_secret` | Yes | From your OAuth client registration |
69| `allowed_email_domains` | No | Reject id\_tokens whose `email` claim isn't in one of these domains, case-insensitive. Defense-in-depth against multi-tenant IdP misconfiguration. Independent of this setting, an id\_token whose `email_verified` claim is explicitly `false` is always rejected. |
70| `allowed_groups` | No | Restrict sign-in to members of these IdP groups, matched against `groups_claim`. A user in an allowed email domain but in none of these groups is rejected. Requires the IdP to emit the groups claim. Matching is an exact, case-sensitive string comparison against the values in that claim, and the gateway doesn't expand nested groups: to admit members of a sub-group, list the sub-group here or configure the IdP to emit flattened membership. |
71| `groups_claim` | No | Which id\_token claim carries group membership. Default `groups`. Microsoft Entra emits app roles under `roles`. Accepts a flat key or an RFC 6901 JSON Pointer such as `/resource_access/gateway/roles` for nested claims. |
72| `google_groups` | No | Look up the signed-in user's groups through the Google Workspace Admin SDK Directory API, because Google's id\_token carries no groups claim. Set `service_account_json_path` to a service-account key file with domain-wide delegation on the `https://www.googleapis.com/auth/admin.directory.group.readonly` scope, and `admin_email` to a Workspace administrator the service account impersonates; the Directory API requires a real admin subject. Each user's group email addresses become their groups claim, so `allowed_groups` and `managed.policies.match.groups` match on group emails. |
73| `email_claim` | No | Which id\_token claim carries the user's email. Default `email`. Some IdPs, such as ADFS and Entra B2C, emit `upn` or `preferred_username` instead. Accepts a flat key, a JSON Pointer, or a list of fallback keys where the first present key is used. |
74| `scopes` | No | Full override of the OIDC scopes the gateway requests. Default `[openid, profile, email, offline_access]`. Set when your IdP rejects scopes it doesn't recognize, or requires a custom scope to emit groups or email. Must include `openid`. Dropping `offline_access` disables refresh tokens, so developers re-run the browser login every `session.ttl_hours`. See [Identity provider setup](/docs/en/claude-apps-gateway-deploy#identity-provider-setup) for per-IdP scope recipes such as Google's refresh-token flow. |
75| `scope_on_refresh` | No | Also send `scope`, with the same list as the sign-in request, when the gateway exchanges a refresh token. Default `false`: the refresh request omits `scope`. Most IdPs return an id\_token on every refresh and don't need this. Set `true` when your IdP returns an id\_token on refresh only if asked for `openid` again, which Okta documents for its refresh grant. Without an id\_token, every refresh depends on the IdP's userinfo endpoint accepting the refreshed access token. If you gate sign-in or match policies on groups and your IdP's refresh-time id\_token omits them, also set `userinfo_fallback: true` so the gateway fills them from the userinfo endpoint. An IdP that granted fewer scopes than requested can reject the refresh with `invalid_scope`, including for existing sessions if you add entries to `scopes` while this is on. Unset the key if refreshes start failing at `token_endpoint` after you set it. Requires Claude Code v2.1.260 or later on the gateway server. |
76| `extra_auth_params` | No | Extra query parameters appended to the IdP authorization request, verbatim. This is the override mechanism for IdP-specific behavior, such as `access_type: offline` for Google refresh tokens, `domain_hint` for some Entra tenants, or `acr_values` for step-up flows. Cannot override the gateway-managed protocol params: `state`, `nonce`, `redirect_uri`, PKCE, `scope`, `response_type`, `response_mode`, and `client_id`. |
77| `userinfo_fallback` | No | When the id\_token omits email or groups, fetch them from `/userinfo`. Needed for Keycloak lightweight access tokens, the Okta org server, and ADFS minimal tokens. The id\_token stays authoritative; userinfo only fills gaps. Default `false`. |
78| `use_pkce` | No | Send a PKCE (S256) challenge on the authorization request. Default `true`. Set `false` only if your IdP rejects PKCE for this confidential client. |
79| `clock_skew_seconds` | No | Tolerate clock drift when validating id\_token time claims. Default `0`, which is strict. Raise if you see "token expired / not yet valid" errors right after sign-in due to host/IdP clock skew. |
80| `token_endpoint_auth_method` | No | Override the token-endpoint auth method. Accepts `client_secret_basic` or `client_secret_post`. Auto-negotiated by default. |
81| `id_token_signed_response_alg` | No | Expected id\_token signing algorithm. Default `RS256`. Set for IdPs that sign with ES256, PS256, or EdDSA. |
82| `additional_authorized_parties` | No | Extra `azp` values to accept beyond `client_id`, for Keycloak broker and token-exchange flows |
83| `discovery_url` | No | Fetch the discovery document from this URL instead of deriving it from `issuer`, for IdPs behind a proxy that rewrites the issuer host. The path must contain `/.well-known/`. |
84| `use_proxy` | No | Send the gateway's own IdP requests through the forward proxy in `HTTPS_PROXY` or `HTTP_PROXY`, honoring `NO_PROXY`. `false` keeps those requests direct. Requires v2.1.227 or later; see [IdP requests through a forward proxy](#idp-requests-through-a-forward-proxy) below. |
85| `form_action_origins` | No | Additional origins for the `/device` page's `Content-Security-Policy: form-action` directive. The gateway already allows `'self'` and the discovered `authorization_endpoint` origin, but Chrome enforces `form-action` against the entire redirect chain. If your IdP redirects through a second host, such as Azure AD federated to ADFS, hub-spoke Okta, or a corporate SSO interceptor, list every origin the authorization request may redirect through. |
86| `ca_cert_pem` | No | The PEM-encoded CA certificate itself, not a path to a file. It replaces the system trust store for IdP requests only. To load a mounted file, write `${file:/etc/gateway/idp-ca.pem}`. Use for Keycloak or Dex behind corporate PKI. |
8787 
8888#### IdP requests through a forward proxy
8989 
from line 108
108108 
109109Each row below is one class of outbound request on a gateway with `HTTPS_PROXY` set, by default and while proxy-only egress is active.
110110 
111| Outbound request | Default | Proxy-only egress active |
112| ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
113| `provider: anthropic` upstreams, Workload Identity Federation token exchange, `telemetry.forward_to` exports | Resolved and checked locally, then `CONNECT` to the checked IP address through the proxy. A telemetry collector listed in `NO_PROXY` is reached directly instead | Hostname handed to the proxy |
114| IdP discovery, JWKS, token, and userinfo | Direct unless [`oidc.use_proxy: true`](#idp-requests-through-a-forward-proxy), then `CONNECT` to the checked IP address | Hostname handed to the proxy, unless `oidc.use_proxy: false` keeps an internal IdP direct |
115| Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform, and Microsoft Foundry upstreams; Google group lookups | Hostname handed to the proxy | Unchanged |
111| Outbound request | Default | Proxy-only egress active |
112| - | - | - |
113| `provider: anthropic` upstreams, Workload Identity Federation token exchange, `telemetry.forward_to` exports | Resolved and checked locally, then `CONNECT` to the checked IP address through the proxy. A telemetry collector listed in `NO_PROXY` is reached directly instead | Hostname handed to the proxy |
114| IdP discovery, JWKS, token, and userinfo | Direct unless [`oidc.use_proxy: true`](#idp-requests-through-a-forward-proxy), then `CONNECT` to the checked IP address | Hostname handed to the proxy, unless `oidc.use_proxy: false` keeps an internal IdP direct |
115| Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform, and Microsoft Foundry upstreams; Google group lookups | Hostname handed to the proxy | Unchanged |
116116 
117117Proxy-only egress stays off unless the gateway's environment meets all three of these conditions:
118118 
from line 132
132132 
133133The `session` block shapes the bearer tokens the gateway mints after sign-in: the secret that signs them and how long they live.
134134 
135| Field | Required | Description |
136| ------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
137| `jwt_secret` | Yes | At least 32 bytes of entropy, for example from `openssl rand -base64 32`. Signs the gateway's HS256 bearer tokens. Accepts a single string or an array for rotation: index 0 signs and all entries verify. To rotate, prepend a new secret, wait `ttl_hours`, then drop the old one. |
138| `ttl_hours` | No | Gateway bearer token lifetime. Default `1`. The CLI silently refreshes before expiry when the IdP issues refresh tokens. A shorter lifetime deprovisions faster; a longer one makes fewer IdP round-trips. If your IdP can't issue refresh tokens because `offline_access` is unavailable, there is no silent refresh, so raise this to `8` or `12` to avoid sending developers back to the browser login every hour. |
135| Field | Required | Description |
136| - | - | - |
137| `jwt_secret` | Yes | At least 32 bytes of entropy, for example from `openssl rand -base64 32`. Signs the gateway's HS256 bearer tokens. Accepts a single string or an array for rotation: index 0 signs and all entries verify. To rotate, prepend a new secret, wait `ttl_hours`, then drop the old one. |
138| `ttl_hours` | No | Gateway bearer token lifetime. Default `1`. The CLI silently refreshes before expiry when the IdP issues refresh tokens. A shorter lifetime deprovisions faster; a longer one makes fewer IdP round-trips. If your IdP can't issue refresh tokens because `offline_access` is unavailable, there is no silent refresh, so raise this to `8` or `12` to avoid sending developers back to the browser login every hour. |
139139 
140140### `store`
141141 
142142The `store` block points the gateway at its PostgreSQL database, which holds device grants and rate-limit counters.
143143 
144| Field | Required | Description |
145| ------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
146| `postgres_url` | Yes | `postgres://` or `postgresql://` URL. Required: the device-grant rendezvous, where the browser callback writes and the polling CLI reads, needs cross-replica state. The gateway runs its own schema migrations at boot and on upgrade, so the role needs rights to create and alter tables on the target schema. See [Upgrades](/docs/en/claude-apps-gateway-deploy#upgrades) and [Postgres](/docs/en/claude-apps-gateway-deploy#postgres). |
147| `username` | No | Overrides the user in `postgres_url` |
148| `password` | No | Database credential. Set it here rather than in `postgres_url` so the credential stays out of the URL. Accepts any characters and takes precedence over URL credentials. |
149| `max_connections` | No | Postgres connection-pool size per replica. Default `5`, which is conservative and friendly to shared databases. With [spend limits](#admin) enabled, the hot path does a few operations per inference request, so raise it for a dedicated database under load, and keep replicas × this below the database's `max_connections`. |
150| `connect_timeout_seconds` | No | Seconds the gateway waits when it opens a Postgres connection. A whole number from `1` to `60`, default `5`. Raise it if connection attempts time out when a new gateway instance starts. Requires Claude Code v2.1.274 or later on the gateway server. Earlier versions refuse to start when the key is set. |
151| `readiness_grace_seconds` | No | How many seconds `/readyz` keeps reporting ready after Postgres stops answering. A whole number from `0` to `3600`, default `0`. See [Outage behavior](/docs/en/claude-apps-gateway-deploy#outage-behavior) for how to pick a value. Requires Claude Code v2.1.282 or later on the gateway server. Earlier versions refuse to start when the key is set. |
144| Field | Required | Description |
145| - | - | - |
146| `postgres_url` | Yes | `postgres://` or `postgresql://` URL. Required: the device-grant rendezvous, where the browser callback writes and the polling CLI reads, needs cross-replica state. The gateway runs its own schema migrations at boot and on upgrade, so the role needs rights to create and alter tables on the target schema. See [Upgrades](/docs/en/claude-apps-gateway-deploy#upgrades) and [Postgres](/docs/en/claude-apps-gateway-deploy#postgres). |
147| `username` | No | Overrides the user in `postgres_url` |
148| `password` | No | Database credential. Set it here rather than in `postgres_url` so the credential stays out of the URL. Accepts any characters and takes precedence over URL credentials. |
149| `max_connections` | No | Postgres connection-pool size per replica. Default `5`, which is conservative and friendly to shared databases. With [spend limits](#admin) enabled, the hot path does a few operations per inference request, so raise it for a dedicated database under load, and keep replicas × this below the database's `max_connections`. |
150| `connect_timeout_seconds` | No | Seconds the gateway waits when it opens a Postgres connection. A whole number from `1` to `60`, default `5`. Raise it if connection attempts time out when a new gateway instance starts. Requires Claude Code v2.1.274 or later on the gateway server. Earlier versions refuse to start when the key is set. |
151| `readiness_grace_seconds` | No | How many seconds `/readyz` keeps reporting ready after Postgres stops answering. A whole number from `0` to `3600`, default `0`. See [Outage behavior](/docs/en/claude-apps-gateway-deploy#outage-behavior) for how to pick a value. Requires Claude Code v2.1.282 or later on the gateway server. Earlier versions refuse to start when the key is set. |
152152 
153153For local development, point `postgres_url` at a throwaway Postgres container, for example `docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres`.
154154 
from line 236
236236 
237237The gateway adds these headers to every request it forwards to that upstream.
238238 
239| Header | Value |
240| ----------------------------- | ---------------------------------------------------------- |
241| `x-litellm-end-user-id` | The developer's email, when the IdP supplied one. |
242| `x-claude-gateway-user-id` | The developer's IdP subject, from the token's `sub` claim. |
243| `x-claude-gateway-user-email` | The developer's email, when the IdP supplied one. |
239| Header | Value |
240| - | - |
241| `x-litellm-end-user-id` | The developer's email, when the IdP supplied one. |
242| `x-claude-gateway-user-id` | The developer's IdP subject, from the token's `sub` claim. |
243| `x-claude-gateway-user-email` | The developer's email, when the IdP supplied one. |
244244 
245245When the IdP token carries no email, the gateway sends only `x-claude-gateway-user-id` and omits the two email headers. If your IdP puts the email in a different claim, set [`oidc.email_claim`](#oidc) to that claim.
246246 
from line 273
273273 
274274Explicit credentials must be complete: the gateway fails at boot when `aws_access_key_id` and `aws_secret_access_key` aren't set together, or when `aws_session_token` is set without them. Before v2.1.207, a partial `auth:` block passed validation.
275275 
276| Setup | How |
277| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
276| Setup | How |
277| - | - |
278278| IAM permissions | Grant the gateway's principal `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream` on both the inference-profile ARNs and the underlying foundation-model ARNs. For the built-in catalog in US regions: `arn:aws:bedrock:<region>:<account>:inference-profile/us.anthropic.*` and `arn:aws:bedrock:*::foundation-model/anthropic.*`. Also grant `bedrock:CountTokens` on the foundation-model ARNs. The gateway uses it, at no charge, to count the input tokens of a request the client abandoned, so [spend limits](#admin) stay accurate. Without it the gateway falls back to a one-token Bedrock request for that count. |
279| Model access | Amazon Bedrock enables model access by default in commercial regions. The remaining account-level gate is Anthropic's one-time use case form: if no one in your AWS account has submitted it, open the Amazon Bedrock console, select an Anthropic model from the Model catalog, and complete the form. See [Submit use case details](/docs/en/amazon-bedrock#1-submit-use-case-details) for the AWS Organizations form and the permissions the submitter needs. |
280| EKS (IRSA) | Create an IAM role with the policy above and a trust policy for your cluster's OIDC provider scoped to the gateway's service account. Annotate the service account with `eks.amazonaws.com/role-arn: arn:aws:iam::<acct>:role/claude-gateway`. `auth: {}` picks it up. |
281| ECS / EC2 | Attach the IAM role to the task definition or instance profile. `auth: {}` picks it up. |
282| Anywhere else | Pass credentials via the `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` env vars, or set them explicitly in `auth:` with `${VAR}` expansion |
283| Region | `region:` is the API endpoint region. Cross-region inference profiles route across the geo (US, EU, APAC) regardless of which one you pick. For non-US regions or provisioned-throughput ARNs, add a [`models:`](#models) block with the right per-upstream IDs. |
279| Model access | Amazon Bedrock enables model access by default in commercial regions. The remaining account-level gate is Anthropic's one-time use case form: if no one in your AWS account has submitted it, open the Amazon Bedrock console, select an Anthropic model from the Model catalog, and complete the form. See [Submit use case details](/docs/en/amazon-bedrock#1-submit-use-case-details) for the AWS Organizations form and the permissions the submitter needs. |
280| EKS (IRSA) | Create an IAM role with the policy above and a trust policy for your cluster's OIDC provider scoped to the gateway's service account. Annotate the service account with `eks.amazonaws.com/role-arn: arn:aws:iam::<acct>:role/claude-gateway`. `auth: {}` picks it up. |
281| ECS / EC2 | Attach the IAM role to the task definition or instance profile. `auth: {}` picks it up. |
282| Anywhere else | Pass credentials via the `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN` env vars, or set them explicitly in `auth:` with `${VAR}` expansion |
283| Region | `region:` is the API endpoint region. Cross-region inference profiles route across the geo (US, EU, APAC) regardless of which one you pick. For non-US regions or provisioned-throughput ARNs, add a [`models:`](#models) block with the right per-upstream IDs. |
284284 
285285#### Claude Platform on AWS
286286 
from line 307
307307 
308308The platform runs in a separate AWS account from Amazon Bedrock and signs SigV4 requests for its own service name, `aws-external-anthropic`, so a Bedrock-scoped IAM role doesn't authorize it. An API key in `auth.api_key` takes precedence when SigV4 credentials are also set. An empty `auth` block uses the AWS SDK's default credential chain, the same chain the [Amazon Bedrock](#amazon-bedrock) upstream uses.
309309 
310| Field | Required | Description |
311| ------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
312| `region` | Yes | AWS region, lowercase letters, digits, and hyphens. The gateway derives the endpoint from it as `https://aws-external-anthropic.<region>.api.aws`. |
313| `workspace_id` | Yes | Sent as a header on every request; the platform requires it |
314| `auth.api_key` | No | API key for the platform, sent as `x-api-key`. Not a bearer token: the two auth modes are an API key or SigV4. |
315| `auth.aws_access_key_id` / `auth.aws_secret_access_key` | No | Explicit SigV4 credentials. Setting one without the other fails at boot. `auth.aws_session_token` is accepted alongside them. |
316| `base_url` | No | Override the derived endpoint |
310| Field | Required | Description |
311| - | - | - |
312| `region` | Yes | AWS region, lowercase letters, digits, and hyphens. The gateway derives the endpoint from it as `https://aws-external-anthropic.<region>.api.aws`. |
313| `workspace_id` | Yes | Sent as a header on every request; the platform requires it |
314| `auth.api_key` | No | API key for the platform, sent as `x-api-key`. Not a bearer token: the two auth modes are an API key or SigV4. |
315| `auth.aws_access_key_id` / `auth.aws_secret_access_key` | No | Explicit SigV4 credentials. Setting one without the other fails at boot. `auth.aws_session_token` is accepted alongside them. |
316| `base_url` | No | Override the derived endpoint |
317317 
318318Because the platform resolves first-party model IDs, the built-in catalog routes to it with no [`models:`](#models) block. When you curate a `models:` list, key the entry `anthropicAws:` with the first-party ID.
319319 
from line 337
337337 
338338Set `region: global` to use the [global endpoint for Google Cloud's Agent Platform](https://cloud.google.com/vertex-ai/generative-ai/docs/learn/locations) instead of a regional one. Google then routes each request to an available region, so you don't track per-region model availability. Setting a specific region pins every request to it.
339339 
340| Setup | How |
341| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
342| IAM permissions | Grant the gateway's service account `roles/aiplatform.user` on the project, or a custom role with `aiplatform.endpoints.predict`. Enable Google Cloud's Agent Platform API (`aiplatform.googleapis.com`). |
343| Model access | In Model Garden, enable the Claude models for your project. They publish to specific regions; check the model card for supported regions. |
340| Setup | How |
341| - | - |
342| IAM permissions | Grant the gateway's service account `roles/aiplatform.user` on the project, or a custom role with `aiplatform.endpoints.predict`. Enable Google Cloud's Agent Platform API (`aiplatform.googleapis.com`). |
343| Model access | In Model Garden, enable the Claude models for your project. They publish to specific regions; check the model card for supported regions. |
344344| GKE (Workload Identity) | Bind a GCP service account to the gateway's Kubernetes service account and annotate the KSA with `iam.gke.io/gcp-service-account: claude-gateway@<proj>.iam.gserviceaccount.com`. `auth: {}` picks it up. |
345| Cloud Run / GCE | Set the service's service account to one with `roles/aiplatform.user`. `auth: {}` picks it up. |
346| Anywhere else | `auth: { service_account_json: /secrets/sa.json }`, the path to a JSON key file mounted as a secret. The field takes a file path, not the key contents, so no `${file:…}` expansion is involved. |
345| Cloud Run / GCE | Set the service's service account to one with `roles/aiplatform.user`. `auth: {}` picks it up. |
346| Anywhere else | `auth: { service_account_json: /secrets/sa.json }`, the path to a JSON key file mounted as a secret. The field takes a file path, not the key contents, so no `${file:…}` expansion is involved. |
347347 
348348#### Microsoft Foundry
349349 
from line 361
361361 
362362`use_azure_ad: true` resolves through `DefaultAzureCredential`: Managed Identity on AKS, ACI, or App Service; the Azure CLI; or environment credentials. API keys work but are project-wide and don't rotate automatically. Microsoft Foundry's endpoint is derived from `resource:`; set the optional `base_url` to override it for sovereign clouds such as Azure Government.
363363 
364| Setup | How |
365| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
366| RBAC | Grant the gateway's identity `Azure AI User` or `Cognitive Services User` on the Microsoft Foundry resource |
367| Deployments | Microsoft Foundry uses admin-chosen deployment names, not canonical model IDs. Add a [`models:`](#models) block mapping each canonical ID to your deployment name. |
364| Setup | How |
365| - | - |
366| RBAC | Grant the gateway's identity `Azure AI User` or `Cognitive Services User` on the Microsoft Foundry resource |
367| Deployments | Microsoft Foundry uses admin-chosen deployment names, not canonical model IDs. Add a [`models:`](#models) block mapping each canonical ID to your deployment name. |
368368| AKS (workload identity) | Federate a User-Assigned Managed Identity with the cluster's OIDC issuer and bind it to the gateway's service account. `use_azure_ad: true` picks it up via `WorkloadIdentityCredential`. |
369| ACI / App Service | Enable system-assigned or user-assigned managed identity on the resource. `use_azure_ad: true` picks it up. |
370| Anywhere else | `auth: { api_key: "${FOUNDRY_API_KEY}" }`. Quote `${…}` inside `{ }`. |
369| ACI / App Service | Enable system-assigned or user-assigned managed identity on the resource. `use_azure_ad: true` picks it up. |
370| Anywhere else | `auth: { api_key: "${FOUNDRY_API_KEY}" }`. Quote `${…}` inside `{ }`. |
371371 
372372#### Static headers on upstream requests
373373 
from line 399
399399 
400400Not every request that the gateway sends to an upstream carries them:
401401 
402| Request the gateway sends to this upstream | Carries `headers:` |
403| ---------------------------------------------------------------------- | ------------------------------------ |
404| `/v1/messages`, streaming or not, and `/v1/messages/count_tokens` | Yes |
405| A request that failed over from another upstream | Yes, this upstream's `headers:` only |
406| Amazon Bedrock's `CountTokens` call for a request the client abandoned | No |
407| The Workload Identity Federation token exchange | No |
402| Request the gateway sends to this upstream | Carries `headers:` |
403| - | - |
404| `/v1/messages`, streaming or not, and `/v1/messages/count_tokens` | Yes |
405| A request that failed over from another upstream | Yes, this upstream's `headers:` only |
406| Amazon Bedrock's `CountTokens` call for a request the client abandoned | No |
407| The Workload Identity Federation token exchange | No |
408408 
409409On an Amazon Bedrock or Claude Platform on AWS upstream that signs requests with AWS SigV4, these headers are part of the signature, so your proxy must pass them through unchanged.
410410 
from line 468
468468 anthropic-fallback: claude-opus-4-8
469469```
470470 
471| Lever | How |
472| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
473| Different regions | One Amazon Bedrock upstream per region, each with its own `region:`. With [`auto_include_builtin_models: true`](#models) the cross-region inference profiles route automatically; for region-pinned deployments use a `models:` block. |
474| Different accounts | One Amazon Bedrock upstream per account, each with its own credentials in `auth:`. The default chain (`auth: {}`) uses the pod's identity; for a second account, set explicit credentials or a bearer token. |
475| Provisioned throughput | Map the model to the provisioned-throughput ARN in `models:` for that upstream's name. Other upstreams keep the on-demand ID, so PT capacity is exhausted before failing over. |
476| VPC / FIPS endpoints | Set `base_url:` on the upstream to your VPC endpoint or FIPS endpoint URL |
477| Model-scoped routing | Only a custom model `id`, one that isn't a built-in Claude model, skips the upstreams absent from its `upstream_model:` map. The gateway tries built-in models on every upstream in order and uses the provider's default ID where the map has no entry, so for built-in models the map changes which ID an upstream receives rather than whether it is tried; an upstream that rejects the ID follows the same [failover rules](#upstreams) as any other upstream error. |
471| Lever | How |
472| - | - |
473| Different regions | One Amazon Bedrock upstream per region, each with its own `region:`. With [`auto_include_builtin_models: true`](#models) the cross-region inference profiles route automatically; for region-pinned deployments use a `models:` block. |
474| Different accounts | One Amazon Bedrock upstream per account, each with its own credentials in `auth:`. The default chain (`auth: {}`) uses the pod's identity; for a second account, set explicit credentials or a bearer token. |
475| Provisioned throughput | Map the model to the provisioned-throughput ARN in `models:` for that upstream's name. Other upstreams keep the on-demand ID, so PT capacity is exhausted before failing over. |
476| VPC / FIPS endpoints | Set `base_url:` on the upstream to your VPC endpoint or FIPS endpoint URL |
477| Model-scoped routing | Only a custom model `id`, one that isn't a built-in Claude model, skips the upstreams absent from its `upstream_model:` map. The gateway tries built-in models on every upstream in order and uses the provider's default ID where the map has no entry, so for built-in models the map changes which ID an upstream receives rather than whether it is tried; an upstream that rejects the ID follows the same [failover rules](#upstreams) as any other upstream error. |
478478 
479479Failing over between cloud providers, or to the direct Anthropic API, changes which agreement, geography, and other terms govern the request.
480480 
from line 502
502502 blocked_message: request an increase at https://go.example.com/claude-limits
503503```
504504 
505| Field | Required | Description |
506| ------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
507| `write_keys` | No | Array of `{id, key}`. An `x-api-key` matching one of these can list, set, and delete spend limits. Key values must be at least 32 characters; `id`s must be unique across `read_keys` and `write_keys`. |
508| `read_keys` | No | Array of `{id, key}`. Read-only: every `GET` endpoint, including listing caps, fetching one by ID, and reading [`/effective`](/docs/en/claude-apps-gateway-spend-limits#%2Feffective) and [`/audit`](/docs/en/claude-apps-gateway-spend-limits#%2Faudit). |
509| `admin_groups` | No | IdP group names. A gateway JWT whose `groups` claim includes one of these has full admin access, read and write, and audits as `oidc:<sub>`. Use this for human admins; use API keys for machines. An empty entry in this list stops the gateway at boot. See [Matcher values that stop the gateway at boot](#matcher-values-that-stop-the-gateway-at-boot). |
510| `blocked_message` | No | Appended verbatim to the `429 billing_error` a blocked developer sees. Write the whole instruction, such as a URL or a Slack channel. When unset, the gateway sends only the default message. See [How enforcement works](/docs/en/claude-apps-gateway-spend-limits#how-enforcement-works). |
511| `audit_retention_days` | No | Default `365`. Older `admin_audit` rows are swept. |
512| `spend_retention_months` | No | Default `13`. `spend` counter rows older than this are swept. The default keeps a full year plus the current partial month for year-over-year reporting. |
513| `identity_retention_days` | No | Default `90`. Last-seen TTL for `principal_emails` rows, which hold each developer's email, display name, and groups (PII). Deliberately shorter than spend retention so a deprovisioned identity ages out while its anonymous spend counters remain. |
514| `group_limit_mode` | No | `min` (default) or `max`. When a developer is in several groups with caps, `min` enforces the most restrictive and `max` the least. Used by both enforcement and `/effective`. |
505| Field | Required | Description |
506| - | - | - |
507| `write_keys` | No | Array of `{id, key}`. An `x-api-key` matching one of these can list, set, and delete spend limits. Key values must be at least 32 characters; `id`s must be unique across `read_keys` and `write_keys`. |
508| `read_keys` | No | Array of `{id, key}`. Read-only: every `GET` endpoint, including listing caps, fetching one by ID, and reading [`/effective`](/docs/en/claude-apps-gateway-spend-limits#%2Feffective) and [`/audit`](/docs/en/claude-apps-gateway-spend-limits#%2Faudit). |
509| `admin_groups` | No | IdP group names. A gateway JWT whose `groups` claim includes one of these has full admin access, read and write, and audits as `oidc:<sub>`. Use this for human admins; use API keys for machines. An empty entry in this list stops the gateway at boot. See [Matcher values that stop the gateway at boot](#matcher-values-that-stop-the-gateway-at-boot). |
510| `blocked_message` | No | Appended verbatim to the `429 billing_error` a blocked developer sees. Write the whole instruction, such as a URL or a Slack channel. When unset, the gateway sends only the default message. See [How enforcement works](/docs/en/claude-apps-gateway-spend-limits#how-enforcement-works). |
511| `audit_retention_days` | No | Default `365`. Older `admin_audit` rows are swept. |
512| `spend_retention_months` | No | Default `13`. `spend` counter rows older than this are swept. The default keeps a full year plus the current partial month for year-over-year reporting. |
513| `identity_retention_days` | No | Default `90`. Last-seen TTL for `principal_emails` rows, which hold each developer's email, display name, and groups (PII). Deliberately shorter than spend retention so a deprovisioned identity ages out while its anonymous spend counters remain. |
514| `group_limit_mode` | No | `min` (default) or `max`. When a developer is in several groups with caps, `min` enforces the most restrictive and `max` the least. Used by both enforcement and `/effective`. |
515515 
516516### `enforcement`
517517 
518518The `enforcement` block controls how spend-limit checks behave when the store is unavailable.
519519 
520| Field | Required | Description |
521| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
522| `fail_closed_on_error` | No | Default `false`. Spend enforcement fails open on a Postgres outage, so inference stays up. Set `true` to fail closed: over-cap developers are blocked, but so is everyone else if the store is unreachable. Requires an [`admin:`](#admin) block: spend enforcement only runs when `admin` is configured, and the gateway refuses to start if you set this `true` without one. |
520| Field | Required | Description |
521| - | - | - |
522| `fail_closed_on_error` | No | Default `false`. Spend enforcement fails open on a Postgres outage, so inference stays up. Set `true` to fail closed: over-cap developers are blocked, but so is everyone else if the store is unreachable. Requires an [`admin:`](#admin) block: spend enforcement only runs when `admin` is configured, and the gateway refuses to start if you set this `true` without one. |
523523 
524524### `pricing`
525525 
from line 540
540540 cache_write: 4.125
541541```
542542 
543| Field | Required | Description |
544| ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
545| `multiplier` | No | Default `1`. The meter multiplies every metered amount by this, whether list-priced or overridden, so `0.85` bills 85% of the price. Must be greater than 0 and at most 10, and a value above 1 is a [markup](#mark-prices-up). |
546| `overrides` | No | Rows of `{upstream, model, input, output, cache_read, cache_write}` in USD per million tokens. All four rates are required. Each must be greater than 0 and at most 10000. |
543| Field | Required | Description |
544| - | - | - |
545| `multiplier` | No | Default `1`. The meter multiplies every metered amount by this, whether list-priced or overridden, so `0.85` bills 85% of the price. Must be greater than 0 and at most 10, and a value above 1 is a [markup](#mark-prices-up). |
546| `overrides` | No | Rows of `{upstream, model, input, output, cache_read, cache_write}` in USD per million tokens. All four rates are required. Each must be greater than 0 and at most 10000. |
547547 
548548How the meter matches an override row:
549549 
from line 629
629629* When the value is missing or empty, the gateway rejects the request with the message `model is required`. That check requires a gateway running Claude Code v2.1.228 or later.
630630* When the value is present but isn't a string, the gateway rejects the request with the message `model must be a string`. Requires a gateway running Claude Code v2.1.221 or later.
631631 
632| Matcher | Behavior |
633| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
634| `match: {}` | Matches every authenticated user. Start with one of these and add group-scoped policies above it later. |
635| `match: { groups: [a, b] }` | Matches if the JWT's `groups` claim contains any of the listed groups. Case-sensitive: groups must match the IdP's exact casing. |
636| `match: { email_domain: example.com }` | Matches the part after the last `@` in the JWT's `email` claim, case-insensitive. Accepts one domain per policy. |
637| `match: { groups: [a], email_domain: example.com }` | Both conditions must match |
632| Matcher | Behavior |
633| - | - |
634| `match: {}` | Matches every authenticated user. Start with one of these and add group-scoped policies above it later. |
635| `match: { groups: [a, b] }` | Matches if the JWT's `groups` claim contains any of the listed groups. Case-sensitive: groups must match the IdP's exact casing. |
636| `match: { email_domain: example.com }` | Matches the part after the last `@` in the JWT's `email` claim, case-insensitive. Accepts one domain per policy. |
637| `match: { groups: [a], email_domain: example.com }` | Both conditions must match |
638638 
639639An authenticated user who matches no policy gets the gateway's defaults, which means every model in the catalog and no managed settings. Add a `match: {}` catch-all last if you want a guaranteed default policy.
640640 
from line 707
707707 - { type: command, command: /usr/local/bin/audit-edit.sh }
708708```
709709 
710| Key | Enforced by | Effect |
711| ------------------------------------------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
712| `availableModels` | Gateway + CLI | Model allowlist. Also checked at `/v1/messages`, so a patched client can't bypass it. |
713| `permissions.allow` / `.deny` | CLI | Tool and command rules. See [Permissions](/docs/en/permissions). |
714| `permissions.disableBypassPermissionsMode` | CLI | Set to `disable` to block [`bypassPermissions`](/docs/en/permission-modes#skip-all-checks-with-bypasspermissions-mode), the mode that skips permission prompts, and the `--dangerously-skip-permissions` flag |
715| `allowManagedPermissionRulesOnly` | CLI | When `true`, managed settings become the only settings source of permission rules. The [`allowManagedPermissionRulesOnly`](/docs/en/settings-reference#allowmanagedpermissionrulesonly) entry lists every source Claude Code then ignores. |
716| `env` | CLI | Environment variables merged into the CLI process. Use for telemetry, auto-update, and model-name overrides. |
717| `hooks` | CLI | Org-wide [hooks](/docs/en/hooks) |
718| `managedMcpServers` | CLI | Remote MCP servers [provided to every matching developer](/docs/en/managed-mcp#provide-servers-through-managed-settings) alongside the servers they add themselves, `http` and `sse` only. See [MCP servers in a policy](#mcp-servers-in-a-policy). Requires Claude Code v2.1.259 or later on the gateway server and on clients. Earlier clients ignore the key. |
710| Key | Enforced by | Effect |
711| - | - | - |
712| `availableModels` | Gateway + CLI | Model allowlist. Also checked at `/v1/messages`, so a patched client can't bypass it. |
713| `permissions.allow` / `.deny` | CLI | Tool and command rules. See [Permissions](/docs/en/permissions). |
714| `permissions.disableBypassPermissionsMode` | CLI | Set to `disable` to block [`bypassPermissions`](/docs/en/permission-modes#skip-all-checks-with-bypasspermissions-mode), the mode that skips permission prompts, and the `--dangerously-skip-permissions` flag |
715| `allowManagedPermissionRulesOnly` | CLI | When `true`, managed settings become the only settings source of permission rules. The [`allowManagedPermissionRulesOnly`](/docs/en/settings-reference#allowmanagedpermissionrulesonly) entry lists every source Claude Code then ignores. |
716| `env` | CLI | Environment variables merged into the CLI process. Use for telemetry, auto-update, and model-name overrides. |
717| `hooks` | CLI | Org-wide [hooks](/docs/en/hooks) |
718| `managedMcpServers` | CLI | Remote MCP servers [provided to every matching developer](/docs/en/managed-mcp#provide-servers-through-managed-settings) alongside the servers they add themselves, `http` and `sse` only. See [MCP servers in a policy](#mcp-servers-in-a-policy). Requires Claude Code v2.1.259 or later on the gateway server and on clients. Earlier clients ignore the key. |
719719 
720720Because these settings arrive over the network, the CLI shows each developer a security approval dialog before applying the settings listed below:
721721 
from line 963
963963 
964964Four optional top-level blocks, `access_control`, `limits`, `timeouts`, and `rate_limits`, tune the HTTP surface. The defaults suit most deployments.
965965 
966| Block | Key | Default | Description |
967| ---------------- | ---------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
968| `access_control` | `allow_cidrs` / `deny_cidrs` | empty | Inbound IP allow/deny by client address, after `trusted_proxies` resolution. `deny_cidrs` is checked first; a client it matches is rejected even if `allow_cidrs` also matches. If `allow_cidrs` is non-empty the gateway is default-deny. `/healthz` and `/readyz` are exempt from `allow_cidrs`. When a trusted proxy sends an `X-Forwarded-For` entry that isn't an IP address, the real client is unknown and the gateway logs a warning once naming what to check. Where either list applies to the request, it refuses it with `403` and audit reason `xff_unparseable`. Where neither does, it serves the request and uses the proxy's own address as the client IP for per-IP rate limits and audit. |
969| `limits` | `max_request_bytes` | 32 MiB | Max inbound request body; oversize requests get `413` before the body is buffered. Raise for large file or image requests. |
970| `limits` | `max_request_header_bytes` | unset | When set, oversize headers return `431` |
971| `limits` | `max_url_length` | unset | When set, an over-long URL returns `414` |
972| `timeouts` | `upstream_ttfb_ms` | 120000 | Max wait for the upstream's response headers (time to first byte). The response body then streams with no wall-clock cap. Applies to the direct Anthropic upstream path; on every other provider the gateway waits up to one hour for the response to start. |
973| `rate_limits` | `device_authorization.max` / `.window_seconds` | 30 / 600 | Per-IP rate limit on the unauthenticated device-authorization endpoint. Raise for a large org behind a shared egress IP or NAT. [Large rollouts](/docs/en/claude-apps-gateway-deploy#large-rollouts) shows how to size it. These limits apply only to the device-grant sign-in flow, not to `/v1/messages` inference. See [User-code brute-force resistance](/docs/en/claude-apps-gateway-deploy#user-code-brute-force-resistance). |
974| `rate_limits` | `device_verify.max` / `.window_seconds` | 10 / 600 | Per-IP rate limit on `user_code` submissions at `/device`. It is what stops someone from guessing another developer's code. [Large rollouts](/docs/en/claude-apps-gateway-deploy#large-rollouts) shows how far to raise it. |
966| Block | Key | Default | Description |
967| - | - | - | - |
968| `access_control` | `allow_cidrs` / `deny_cidrs` | empty | Inbound IP allow/deny by client address, after `trusted_proxies` resolution. `deny_cidrs` is checked first; a client it matches is rejected even if `allow_cidrs` also matches. If `allow_cidrs` is non-empty the gateway is default-deny. `/healthz` and `/readyz` are exempt from `allow_cidrs`. When a trusted proxy sends an `X-Forwarded-For` entry that isn't an IP address, the real client is unknown and the gateway logs a warning once naming what to check. Where either list applies to the request, it refuses it with `403` and audit reason `xff_unparseable`. Where neither does, it serves the request and uses the proxy's own address as the client IP for per-IP rate limits and audit. |
969| `limits` | `max_request_bytes` | 32 MiB | Max inbound request body; oversize requests get `413` before the body is buffered. Raise for large file or image requests. |
970| `limits` | `max_request_header_bytes` | unset | When set, oversize headers return `431` |
971| `limits` | `max_url_length` | unset | When set, an over-long URL returns `414` |
972| `timeouts` | `upstream_ttfb_ms` | 120000 | Max wait for the upstream's response headers (time to first byte). The response body then streams with no wall-clock cap. Applies to the direct Anthropic upstream path; on every other provider the gateway waits up to one hour for the response to start. |
973| `rate_limits` | `device_authorization.max` / `.window_seconds` | 30 / 600 | Per-IP rate limit on the unauthenticated device-authorization endpoint. Raise for a large org behind a shared egress IP or NAT. [Large rollouts](/docs/en/claude-apps-gateway-deploy#large-rollouts) shows how to size it. These limits apply only to the device-grant sign-in flow, not to `/v1/messages` inference. See [User-code brute-force resistance](/docs/en/claude-apps-gateway-deploy#user-code-brute-force-resistance). |
974| `rate_limits` | `device_verify.max` / `.window_seconds` | 10 / 600 | Per-IP rate limit on `user_code` submissions at `/device`. It is what stops someone from guessing another developer's code. [Large rollouts](/docs/en/claude-apps-gateway-deploy#large-rollouts) shows how far to raise it. |
975975 
976976If you leave both `access_control` lists empty, which is the default, the gateway serves any client address, so only your network restricts who can reach it. That matters because a gateway can push [managed settings](#managed) that run commands on developer machines.
977977 
from line 999
999999 reply_seconds: 9.5 # how long a streamed reply takes
10001000```
10011001 
1002| Field | Required | Description |
1003| --------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1004| `enabled` | Yes | `true` turns the mode on. `false` keeps your numbers in the file with the mode off. The gateway refuses to start if the block is present without it. |
1005| `reply_tokens` | No | Default `750`. Roughly how many tokens of text each canned reply carries, a whole number from 1 to 100000. |
1006| `reply_seconds` | No | Default `9.5`. How long a streamed reply takes, from 0 to 600. `0` sends the whole reply at once. A reply to a non-streaming request always comes back at once. |
1002| Field | Required | Description |
1003| - | - | - |
1004| `enabled` | Yes | `true` turns the mode on. `false` keeps your numbers in the file with the mode off. The gateway refuses to start if the block is present without it. |
1005| `reply_tokens` | No | Default `750`. Roughly how many tokens of text each canned reply carries, a whole number from 1 to 100000. |
1006| `reply_seconds` | No | Default `9.5`. How long a streamed reply takes, from 0 to 600. `0` sends the whole reply at once. A reply to a non-streaming request always comes back at once. |
10071007 
10081008A load test in this mode covers the gateway, your Postgres, and everything in front of the gateway. It doesn't cover the provider's limits, speed, or network path.
10091009 

claude-apps-gateway-deploy Changed · +50 / -50 lines

from line 217
217217 
218218The gateway holds five data tables plus a `_migrations` table, all created by its boot-time migrations:
219219 
220| Table | Contents | Retention |
221| ------------------ | ----------------------------------------------------------------------------- | --------------------------------------------------------------- |
222| `kv` | Device grants (10-minute TTL) and rate-limit counters | TTL per row |
223| `spend` | Per-principal period-to-date spend counters, in cents | `admin.spend_retention_months`, default 13 |
224| `spend_limits` | Configured spend caps | Until deleted via the API |
225| `admin_audit` | Admin API mutation trail | `admin.audit_retention_days`, default 365 |
220| Table | Contents | Retention |
221| - | - | - |
222| `kv` | Device grants (10-minute TTL) and rate-limit counters | TTL per row |
223| `spend` | Per-principal period-to-date spend counters, in cents | `admin.spend_retention_months`, default 13 |
224| `spend_limits` | Configured spend caps | Until deleted via the API |
225| `admin_audit` | Admin API mutation trail | `admin.audit_retention_days`, default 365 |
226226| `principal_emails` | Each principal's last-seen email, display name, and IdP groups. Contains PII. | `admin.identity_retention_days` since last activity, default 90 |
227227 
228228A 30-second loop expires `kv` rows past their TTL, and an hourly sweep enforces the retention windows on the spend tables, so nothing grows without bound. Without [spend limits](/docs/en/claude-apps-gateway-spend-limits) configured, only `kv` is written. The gateway applies its own schema migrations at boot and on every upgrade, so its database role needs rights to create and alter tables. Point it at a database or schema dedicated to the gateway to keep that grant narrow.
from line 259
259259 
260260### Data flow
261261 
262| Data | Path | Sent to Anthropic by the gateway |
263| ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
264| Inference (prompts, completions) | CLI → gateway → your upstream | Only if the Anthropic API is a configured upstream |
265| Telemetry (OTLP metrics, plus [opt-in logs and traces](/docs/en/claude-apps-gateway-config#telemetry)) | CLI → gateway → your collector | Never |
266| Identity (email, groups, sub) | IdP → gateway → JWT → CLI; the CLI stamps it on OTLP exports. If you turn on [`forward_user_identity`](/docs/en/claude-apps-gateway-config#per-user-identity-headers-for-a-proxy-you-run), the gateway also sends the developer's email and IdP subject as headers to your proxy | Never |
267| Managed settings | Your gateway YAML → CLI | Never |
268| Audit log | Gateway stderr → your aggregator | Never |
262| Data | Path | Sent to Anthropic by the gateway |
263| - | - | - |
264| Inference (prompts, completions) | CLI → gateway → your upstream | Only if the Anthropic API is a configured upstream |
265| Telemetry (OTLP metrics, plus [opt-in logs and traces](/docs/en/claude-apps-gateway-config#telemetry)) | CLI → gateway → your collector | Never |
266| Identity (email, groups, sub) | IdP → gateway → JWT → CLI; the CLI stamps it on OTLP exports. If you turn on [`forward_user_identity`](/docs/en/claude-apps-gateway-config#per-user-identity-headers-for-a-proxy-you-run), the gateway also sends the developer's email and IdP subject as headers to your proxy | Never |
267| Managed settings | Your gateway YAML → CLI | Never |
268| Audit log | Gateway stderr → your aggregator | Never |
269269 
270270### Threat model summary
271271 
from line 315
315315 
316316The gateway's stderr includes the audit event stream, the audit log records developer identities, and the debug file records hook and MCP server output from the developer's machine. Review and redact these before posting to a public issue.
317317 
318| Symptom | Cause | Fix |
319| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
320| A developer's `/login` shows the standard account picker instead of the **Cloud gateway** screen | `forceLoginMethod` or `forceLoginGatewayUrl` isn't set in managed settings on that machine | Deploy the [managed settings file](/docs/en/claude-apps-gateway#set-the-gateway-url) to the device; `/login` reads the gateway URL from there |
321| A developer's requests fail with `Not signed in to the Cloud gateway — run /login.` | The machine's managed settings set `forceLoginMethod: "gateway"` or `forceLoginGatewayUrl`, and the session has no gateway sign-in. A leftover claude.ai login doesn't satisfy the requirement. | Have the developer run `/login` and complete the gateway sign-in. See also [Administrator policy requires a Cloud gateway sign-in](/docs/en/errors#administrator-policy-requires-a-cloud-gateway-sign-in). |
322| Claude Desktop reports that its bootstrap configuration couldn't be fetched | `/user/bootstrap` returned 404: the policy matching the user doesn't carry a `desktop` key, or no policy matched. The gateway's audit log records each rejection as `desktop_bootstrap.denied` with the reason. | Add a `desktop` block to the policy that matches the user, or to the `match: {}` base layer; an empty `desktop: {}` suffices. See [Claude Desktop overlay](/docs/en/claude-apps-gateway-config#claude-desktop-overlay). |
323| Startup shows `Gateway login is configured in managed settings, but this Claude Code build does not include Cloud gateway support.` | The installed Claude Code build predates gateway support | Have the developer update Claude Code to a release that includes Cloud gateway support |
324| Startup exits with `Administrator policy requires a Cloud gateway sign-in on this machine` | The developer's environment sets `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN`, their settings configure an [`apiKeyHelper`](/docs/en/settings-reference#apikeyhelper), or an API key from an earlier Claude Console login is still saved | Have the developer clear each that applies: unset the variable, remove the `apiKeyHelper` entry, or run `claude auth logout` to remove the saved key. A session that selects a cloud provider with `CLAUDE_CODE_USE_*` then starts with no sign-in; for every other session, have them start `claude` and sign in with `/login`. See also [Administrator policy requires a Cloud gateway sign-in](/docs/en/errors#administrator-policy-requires-a-cloud-gateway-sign-in). |
325| Startup or `/login` reports `Claude Code may not be enabled for your organization` after a 403 on the managed settings load | The gateway, or something in front of it, answered the `/managed/settings` request with 403. The gateway's own settings route never answers 403. The status comes from the [`access_control`](/docs/en/claude-apps-gateway-config#http-tuning) IP checks or from a proxy or WAF in front of the gateway. The audit log records an IP-check denial as `access.denied` with the reason. The developer stays signed in. | Check the audit log for `access.denied` at the time of the failure and fix the `access_control` lists or the front end, then have the developer start `claude` again |
326| CLI `/login`: `The gateway is limiting sign-in attempts right now`, or `Request failed with status code 429` on older versions. The `/device` page may show `Too many attempts` to developers who haven't tried before | The per-IP sign-in rate limit was reached. Either `listen.trusted_proxies` doesn't cover the load balancer, so every developer shares its address, or many developers share a NAT or VPN egress address. Audit events with `result: rate_limited` show the same one or few `client_ip` values. | Set `listen.trusted_proxies` to the load balancer's source ranges first, then raise `rate_limits` if developers still share addresses. See [Large rollouts](#large-rollouts). |
327| CLI `/login`: `Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip>` | The gateway hostname resolves to at least one public IP address. Claude Code checks each resolved address and requires every one to be private. A common cause is a dual-stack name where one family resolves to a public address, including AWS internal dual-stack load balancers, which return public-range AAAA addresses. | Have the gateway name resolve only to private addresses on developer machines. For a dual-stack name, drop the public-range record or serve a separate internal-only DNS name. See the [private-network prerequisite](/docs/en/claude-apps-gateway#prerequisites). If the address is public space your organization owns and uses internally, [declare that block](/docs/en/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own) instead. |
328| CLI `/login`: `Gateway login would go through proxy <proxy>, which is not on a private network` | An `HTTPS_PROXY` or `HTTP_PROXY` applies to the gateway host and the proxy's hostname resolves to a public address. A proxy whose host resolves only to private addresses is allowed and doesn't trigger this error | Add the gateway host to `NO_PROXY` on the developer's machine so the connection is direct, or use a proxy whose hostname resolves to private addresses. The message names the exact `NO_PROXY` entry to add |
329| CLI `/login`: `Claude Code only signs in to <host> from inside its declared network <block> (managed settings), and this machine is connecting from <ip>, outside it` | The gateway is on a block declared in [`gatewayInternalNetworks`](/docs/en/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own), and the developer's machine reached it from an address outside that block: a VPN address pool, a container or WSL2 NAT segment, or a network that isn't yours | Have the developer run `/login` from the host OS on your network. If the address shown is also your organization's own public space, replace the gateway's entry with a block that covers both, up to `/8`; a second, overlapping entry is refused |
330| CLI `/login`: `Every address for gateway host <host> must be inside its declared network <block>, and it also resolves to <ip>` | The gateway's name resolves to an address outside the block declared in [`gatewayInternalNetworks`](/docs/en/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own): a second site, or an IPv6 record on a dual-stack name. Under a declared block every record must be inside that one IPv4 block, private and IPv6 addresses included | Publish only records inside the block for the gateway name on developer machines, or serve a separate internal-only name |
331| CLI `/login`: `<host> is on the declared network <block>, which Claude Code checks over a direct connection, not through an HTTP proxy` | An `HTTPS_PROXY` or `HTTP_PROXY` applies to a gateway on a declared block | On the developer's machine, add the `NO_PROXY` entry the message names |
332| CLI `/login`: a message starting `gatewayInternalNetworks in managed settings` | The value breaks one of the [validation rules](/docs/en/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own), and the message names which. Until you fix it, Claude Code refuses every new gateway `/login` on the machine, gateways on private addresses included; existing sign-ins keep working | In the managed settings source you deploy, correct the entry the message names, then rerun `/login` |
333| CLI `/login`: `Could not resolve the configured HTTP proxy` | The hostname in `HTTPS_PROXY` or `HTTP_PROXY` doesn't resolve from the developer's machine, typically because it isn't connected to the corporate network | Have the developer connect to your network or VPN and retry, or fix the proxy URL |
334| CLI `/login`: `Could not resolve gateway host <host>` | The machine can't resolve the gateway's internal DNS name, typically because it isn't on the corporate network | Have the developer connect to your network or VPN, then retry `/login` |
335| Boot exits with a config validation error naming `store.postgres_url` | No Postgres configured; the gateway requires Postgres | Set `store.postgres_url`. For local development, use a throwaway container: `docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres`. |
336| Boot exits: `requires the native binary` | Running under Node instead of the native binary | Install Claude Code with one of the [standalone install methods](/docs/en/setup) |
337| Boot exits with an OIDC discovery error after `config.load` | `oidc.issuer` unreachable, or TLS chain not trusted | Check the issuer is reachable from the pod and serves `/.well-known/openid-configuration`. Set `ca_cert_pem` for private PKI. If the pod reaches the IdP only through a forward proxy, set [`oidc.use_proxy: true`](/docs/en/claude-apps-gateway-config#idp-requests-through-a-forward-proxy); on versions before v2.1.227, give the pod a direct route to each of the IdP's endpoints instead. If the pod also can't resolve the IdP's hostname, or the proxy refuses `CONNECT` to an IP address, see [Proxy-only egress](/docs/en/claude-apps-gateway-config#proxy-only-egress), which requires v2.1.277 or later. |
338| Boot exits with a Postgres permission error | The database role lacks DDL rights on its schema | Grant the role `CREATE` on the gateway's schema so it can create and alter its tables at boot |
339| Log: `could not connect to Postgres at boot, attempt 1 of 3` | The database wasn't reachable yet when the gateway started, for example on a cold instance whose network is still coming up | If the gateway then finishes booting, no action is needed. When the database isn't reachable, the gateway tries the connection three times, two seconds apart, before it exits. If it exits with `could not connect to Postgres`, check `store.postgres_url` and the network path to the database. If the attempts time out rather than being refused, raise [`store.connect_timeout_seconds`](/docs/en/claude-apps-gateway-config#store) to give each one longer. |
340| `/oauth/callback` shows "Sign-in could not be completed" | Email domain rejected, id\_token validation failed, or `email_verified` is explicitly `false`, which the gateway always rejects with no override | Check `allowed_email_domains` and that the IdP returns a verified `email` claim. For `email_verified: false`, fix the IdP-side verification. If your IdP emits email under a different claim name, set `oidc.email_claim`. |
341| Log: `token exchange failed request_id=<id>: id_token missing email claim` | The IdP isn't including `email` in the id\_token by default. This rejection fires only when `allowed_email_domains` is set; without it, a missing email mints a session with no email | Configure the IdP to emit `email` in the id\_token. Okta: add `email` to a custom authorization server's ID-token claims. Entra: add `email` as an optional claim on the app registration. PingFederate: enable an OpenID Connect Policy that emits `email`. If the IdP serves `email` from the userinfo endpoint but won't include it in the id\_token, such as the Okta org authorization server, set `oidc.userinfo_fallback: true`. |
342| Log: `refresh failed request_id=<id>: invalid_token (…) (at userinfo_no_id_token, …)`, and developers see `Cloud gateway session expired` every `session.ttl_hours` | The IdP accepted the refresh token but returned no id\_token with it, so the gateway asked the IdP's userinfo endpoint for the user's claims. The IdP rejected the refreshed access token there. The gateway answers `temporarily_unavailable`, so Claude Code keeps the refresh token but can't renew the session. Gateway versions before v2.1.260 log the same line without the `(at …)` detail. | Set [`oidc.scope_on_refresh: true`](/docs/en/claude-apps-gateway-config#oidc), available in gateway v2.1.260 or later, so the refresh request asks for `openid` again. Some IdPs, such as Okta, return an id\_token on refresh only when asked. On PingFederate, enable **Return ID Token On Refresh Grant** under **Applications > OAuth > OpenID Connect Policy Management** instead. The key doesn't change PingFederate's behavior. For other IdPs that still omit it, check whether the userinfo endpoint accepts access tokens issued by a refresh. As a stopgap, raise [`session.ttl_hours`](/docs/en/claude-apps-gateway-config#session). See [Identity provider setup](#identity-provider-setup) for the deprovisioning tradeoff. |
343| Every Amazon Bedrock request returns 502; log shows `Could not load credentials from any providers` | On EC2, IMDSv2's default hop limit of 1 blocks the instance-metadata request from inside the container. Boot and `/readyz` pass anyway because the AWS SDK resolves instance credentials on the first request, not at client construction | Raise the hop limit with `aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2`, or set it in the launch template. The change applies to every container on the instance. Prefer ECS task roles where available, which read credentials from the ECS container-credentials endpoint and avoid the change entirely, or apply the change on a dedicated gateway instance to limit the exposure. |
344| At peak load, responses are slow to start or appear to hang, or fail with a 502 `all upstreams failed` while the upstream is healthy | A replica has more requests open than it sends upstream at once, so the extra requests wait inside the gateway. On a `provider: anthropic` upstream, a request that waits longer than `timeouts.upstream_ttfb_ms` gives up on that upstream, which produces the 502 when no later upstream serves it. The log shows a warning that contains `client requests are open`. | Add replicas, or raise the limit on each replica. See [Concurrent upstream requests](#concurrent-upstream-requests). |
345| IdP error: unknown or unsupported scope | The IdP rejects scopes it doesn't recognize | Set `oidc.scopes` to exactly the list your IdP accepts; it must include `openid`. The default is `openid profile email offline_access`. |
346| Sessions don't silently renew after setting `oidc.scopes` | `offline_access` was dropped from the override | Add `offline_access` back if your IdP supports it. Without a refresh token, developers re-run the browser login every `session.ttl_hours`. |
347| Browser shows "This request came from another site and was blocked" | Cross-site form POST, blocked as CSRF protection. Expected for embedded or proxied pages | Open the verification link directly |
348| Chrome blocks the Approve button with "Refused to send form data … violates … Content Security Policy directive: form-action", but the same page works in Safari or Firefox | Chrome enforces `form-action` against the entire redirect chain. Your IdP redirects onward to a second host that isn't allowlisted. | Add each additional origin in the redirect chain to `oidc.form_action_origins`. Open Chrome DevTools → Console on the Approve page to see which origin was blocked. |
349| Sign-in completes at the IdP but the callback fails, with a CSP error in Chrome or "this sign-in link has expired" in Safari | The IdP returned the code via `response_mode=form_post`, which auto-submits it cross-origin via POST to `/oauth/callback`. Chrome blocks that under a strict CSP; Safari allows the submit but the callback reads only the query string. | Make sure your IdP honors `response_mode=query`, which the gateway requests explicitly so the callback is a plain redirect |
350| Login works locally but fails behind an ALB | `public_url` still names the local or inner `http://` origin, so the IdP gets the wrong `redirect_uri` | Set `listen.public_url` to the external `https://` origin and register `<public_url>/oauth/callback` with the IdP |
351| Developer sees the trust prompt repeatedly | TLS cert is rotating per replica or per request | Use a stable cert at the ingress, or terminate TLS once and run replicas over plain HTTP internally |
352| CLI `/login`: "Could not verify the gateway's TLS certificate" or `SELF_SIGNED_CERT_IN_CHAIN` | Gateway's TLS chain is signed by a private CA not in the CLI host's trust store | Claude Code reads the OS trust store by default on the native binary and on Node 22.15 or later; [`CLAUDE_CODE_CERT_STORE`](/docs/en/network-config#ca-certificate-store) controls this behavior. If the CA is installed in the OS trust store, ensure developers are on a current runtime. Otherwise set `NODE_EXTRA_CA_CERTS` to the CA certificate PEM before launching. The first-connect fingerprint prompt still applies. |
353| CLI `/login` completes the browser sign-in, then the session ends with `Cloud gateway sign-in was not completed` and a TLS certificate mismatch | On the first request after sign-in, the gateway presented a certificate that doesn't match the fingerprint Claude Code pinned, so Claude Code kept no gateway credential. The usual causes are replicas behind one address that serve different certificates, or something on the network path that intercepts TLS. | Serve one certificate for the hostname, for example by terminating TLS once at the ingress, then have the developer run `/login` again. If that certificate differs from the pinned one, Claude Code shows the [trust prompt](/docs/en/claude-apps-gateway#connect-developers) again with a warning that the certificate changed. |
354| CLI `/login` stops with `The gateway's TLS certificate changed during sign-in: it no longer matches the one you trusted` | A sign-in request reached a server whose certificate doesn't match the one the developer accepted when `/login` started: replicas behind one address serving different certificates, TLS interception on the path, or a certificate rotation while the sign-in was in progress. | Serve one certificate for the hostname, then have the developer start the sign-in again and review the new certificate at the [trust prompt](/docs/en/claude-apps-gateway#connect-developers). |
318| Symptom | Cause | Fix |
319| - | - | - |
320| A developer's `/login` shows the standard account picker instead of the **Cloud gateway** screen | `forceLoginMethod` or `forceLoginGatewayUrl` isn't set in managed settings on that machine | Deploy the [managed settings file](/docs/en/claude-apps-gateway#set-the-gateway-url) to the device; `/login` reads the gateway URL from there |
321| A developer's requests fail with `Not signed in to the Cloud gateway — run /login.` | The machine's managed settings set `forceLoginMethod: "gateway"` or `forceLoginGatewayUrl`, and the session has no gateway sign-in. A leftover claude.ai login doesn't satisfy the requirement. | Have the developer run `/login` and complete the gateway sign-in. See also [Administrator policy requires a Cloud gateway sign-in](/docs/en/errors#administrator-policy-requires-a-cloud-gateway-sign-in). |
322| Claude Desktop reports that its bootstrap configuration couldn't be fetched | `/user/bootstrap` returned 404: the policy matching the user doesn't carry a `desktop` key, or no policy matched. The gateway's audit log records each rejection as `desktop_bootstrap.denied` with the reason. | Add a `desktop` block to the policy that matches the user, or to the `match: {}` base layer; an empty `desktop: {}` suffices. See [Claude Desktop overlay](/docs/en/claude-apps-gateway-config#claude-desktop-overlay). |
323| Startup shows `Gateway login is configured in managed settings, but this Claude Code build does not include Cloud gateway support.` | The installed Claude Code build predates gateway support | Have the developer update Claude Code to a release that includes Cloud gateway support |
324| Startup exits with `Administrator policy requires a Cloud gateway sign-in on this machine` | The developer's environment sets `ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN`, their settings configure an [`apiKeyHelper`](/docs/en/settings-reference#apikeyhelper), or an API key from an earlier Claude Console login is still saved | Have the developer clear each that applies: unset the variable, remove the `apiKeyHelper` entry, or run `claude auth logout` to remove the saved key. A session that selects a cloud provider with `CLAUDE_CODE_USE_*` then starts with no sign-in; for every other session, have them start `claude` and sign in with `/login`. See also [Administrator policy requires a Cloud gateway sign-in](/docs/en/errors#administrator-policy-requires-a-cloud-gateway-sign-in). |
325| Startup or `/login` reports `Claude Code may not be enabled for your organization` after a 403 on the managed settings load | The gateway, or something in front of it, answered the `/managed/settings` request with 403. The gateway's own settings route never answers 403. The status comes from the [`access_control`](/docs/en/claude-apps-gateway-config#http-tuning) IP checks or from a proxy or WAF in front of the gateway. The audit log records an IP-check denial as `access.denied` with the reason. The developer stays signed in. | Check the audit log for `access.denied` at the time of the failure and fix the `access_control` lists or the front end, then have the developer start `claude` again |
326| CLI `/login`: `The gateway is limiting sign-in attempts right now`, or `Request failed with status code 429` on older versions. The `/device` page may show `Too many attempts` to developers who haven't tried before | The per-IP sign-in rate limit was reached. Either `listen.trusted_proxies` doesn't cover the load balancer, so every developer shares its address, or many developers share a NAT or VPN egress address. Audit events with `result: rate_limited` show the same one or few `client_ip` values. | Set `listen.trusted_proxies` to the load balancer's source ranges first, then raise `rate_limits` if developers still share addresses. See [Large rollouts](#large-rollouts). |
327| CLI `/login`: `Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip>` | The gateway hostname resolves to at least one public IP address. Claude Code checks each resolved address and requires every one to be private. A common cause is a dual-stack name where one family resolves to a public address, including AWS internal dual-stack load balancers, which return public-range AAAA addresses. | Have the gateway name resolve only to private addresses on developer machines. For a dual-stack name, drop the public-range record or serve a separate internal-only DNS name. See the [private-network prerequisite](/docs/en/claude-apps-gateway#prerequisites). If the address is public space your organization owns and uses internally, [declare that block](/docs/en/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own) instead. |
328| CLI `/login`: `Gateway login would go through proxy <proxy>, which is not on a private network` | An `HTTPS_PROXY` or `HTTP_PROXY` applies to the gateway host and the proxy's hostname resolves to a public address. A proxy whose host resolves only to private addresses is allowed and doesn't trigger this error | Add the gateway host to `NO_PROXY` on the developer's machine so the connection is direct, or use a proxy whose hostname resolves to private addresses. The message names the exact `NO_PROXY` entry to add |
329| CLI `/login`: `Claude Code only signs in to <host> from inside its declared network <block> (managed settings), and this machine is connecting from <ip>, outside it` | The gateway is on a block declared in [`gatewayInternalNetworks`](/docs/en/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own), and the developer's machine reached it from an address outside that block: a VPN address pool, a container or WSL2 NAT segment, or a network that isn't yours | Have the developer run `/login` from the host OS on your network. If the address shown is also your organization's own public space, replace the gateway's entry with a block that covers both, up to `/8`; a second, overlapping entry is refused |
330| CLI `/login`: `Every address for gateway host <host> must be inside its declared network <block>, and it also resolves to <ip>` | The gateway's name resolves to an address outside the block declared in [`gatewayInternalNetworks`](/docs/en/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own): a second site, or an IPv6 record on a dual-stack name. Under a declared block every record must be inside that one IPv4 block, private and IPv6 addresses included | Publish only records inside the block for the gateway name on developer machines, or serve a separate internal-only name |
331| CLI `/login`: `<host> is on the declared network <block>, which Claude Code checks over a direct connection, not through an HTTP proxy` | An `HTTPS_PROXY` or `HTTP_PROXY` applies to a gateway on a declared block | On the developer's machine, add the `NO_PROXY` entry the message names |
332| CLI `/login`: a message starting `gatewayInternalNetworks in managed settings` | The value breaks one of the [validation rules](/docs/en/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own), and the message names which. Until you fix it, Claude Code refuses every new gateway `/login` on the machine, gateways on private addresses included; existing sign-ins keep working | In the managed settings source you deploy, correct the entry the message names, then rerun `/login` |
333| CLI `/login`: `Could not resolve the configured HTTP proxy` | The hostname in `HTTPS_PROXY` or `HTTP_PROXY` doesn't resolve from the developer's machine, typically because it isn't connected to the corporate network | Have the developer connect to your network or VPN and retry, or fix the proxy URL |
334| CLI `/login`: `Could not resolve gateway host <host>` | The machine can't resolve the gateway's internal DNS name, typically because it isn't on the corporate network | Have the developer connect to your network or VPN, then retry `/login` |
335| Boot exits with a config validation error naming `store.postgres_url` | No Postgres configured; the gateway requires Postgres | Set `store.postgres_url`. For local development, use a throwaway container: `docker run --rm -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust postgres`. |
336| Boot exits: `requires the native binary` | Running under Node instead of the native binary | Install Claude Code with one of the [standalone install methods](/docs/en/setup) |
337| Boot exits with an OIDC discovery error after `config.load` | `oidc.issuer` unreachable, or TLS chain not trusted | Check the issuer is reachable from the pod and serves `/.well-known/openid-configuration`. Set `ca_cert_pem` for private PKI. If the pod reaches the IdP only through a forward proxy, set [`oidc.use_proxy: true`](/docs/en/claude-apps-gateway-config#idp-requests-through-a-forward-proxy); on versions before v2.1.227, give the pod a direct route to each of the IdP's endpoints instead. If the pod also can't resolve the IdP's hostname, or the proxy refuses `CONNECT` to an IP address, see [Proxy-only egress](/docs/en/claude-apps-gateway-config#proxy-only-egress), which requires v2.1.277 or later. |
338| Boot exits with a Postgres permission error | The database role lacks DDL rights on its schema | Grant the role `CREATE` on the gateway's schema so it can create and alter its tables at boot |
339| Log: `could not connect to Postgres at boot, attempt 1 of 3` | The database wasn't reachable yet when the gateway started, for example on a cold instance whose network is still coming up | If the gateway then finishes booting, no action is needed. When the database isn't reachable, the gateway tries the connection three times, two seconds apart, before it exits. If it exits with `could not connect to Postgres`, check `store.postgres_url` and the network path to the database. If the attempts time out rather than being refused, raise [`store.connect_timeout_seconds`](/docs/en/claude-apps-gateway-config#store) to give each one longer. |
340| `/oauth/callback` shows "Sign-in could not be completed" | Email domain rejected, id\_token validation failed, or `email_verified` is explicitly `false`, which the gateway always rejects with no override | Check `allowed_email_domains` and that the IdP returns a verified `email` claim. For `email_verified: false`, fix the IdP-side verification. If your IdP emits email under a different claim name, set `oidc.email_claim`. |
341| Log: `token exchange failed request_id=<id>: id_token missing email claim` | The IdP isn't including `email` in the id\_token by default. This rejection fires only when `allowed_email_domains` is set; without it, a missing email mints a session with no email | Configure the IdP to emit `email` in the id\_token. Okta: add `email` to a custom authorization server's ID-token claims. Entra: add `email` as an optional claim on the app registration. PingFederate: enable an OpenID Connect Policy that emits `email`. If the IdP serves `email` from the userinfo endpoint but won't include it in the id\_token, such as the Okta org authorization server, set `oidc.userinfo_fallback: true`. |
342| Log: `refresh failed request_id=<id>: invalid_token (…) (at userinfo_no_id_token, …)`, and developers see `Cloud gateway session expired` every `session.ttl_hours` | The IdP accepted the refresh token but returned no id\_token with it, so the gateway asked the IdP's userinfo endpoint for the user's claims. The IdP rejected the refreshed access token there. The gateway answers `temporarily_unavailable`, so Claude Code keeps the refresh token but can't renew the session. Gateway versions before v2.1.260 log the same line without the `(at …)` detail. | Set [`oidc.scope_on_refresh: true`](/docs/en/claude-apps-gateway-config#oidc), available in gateway v2.1.260 or later, so the refresh request asks for `openid` again. Some IdPs, such as Okta, return an id\_token on refresh only when asked. On PingFederate, enable **Return ID Token On Refresh Grant** under **Applications > OAuth > OpenID Connect Policy Management** instead. The key doesn't change PingFederate's behavior. For other IdPs that still omit it, check whether the userinfo endpoint accepts access tokens issued by a refresh. As a stopgap, raise [`session.ttl_hours`](/docs/en/claude-apps-gateway-config#session). See [Identity provider setup](#identity-provider-setup) for the deprovisioning tradeoff. |
343| Every Amazon Bedrock request returns 502; log shows `Could not load credentials from any providers` | On EC2, IMDSv2's default hop limit of 1 blocks the instance-metadata request from inside the container. Boot and `/readyz` pass anyway because the AWS SDK resolves instance credentials on the first request, not at client construction | Raise the hop limit with `aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2`, or set it in the launch template. The change applies to every container on the instance. Prefer ECS task roles where available, which read credentials from the ECS container-credentials endpoint and avoid the change entirely, or apply the change on a dedicated gateway instance to limit the exposure. |
344| At peak load, responses are slow to start or appear to hang, or fail with a 502 `all upstreams failed` while the upstream is healthy | A replica has more requests open than it sends upstream at once, so the extra requests wait inside the gateway. On a `provider: anthropic` upstream, a request that waits longer than `timeouts.upstream_ttfb_ms` gives up on that upstream, which produces the 502 when no later upstream serves it. The log shows a warning that contains `client requests are open`. | Add replicas, or raise the limit on each replica. See [Concurrent upstream requests](#concurrent-upstream-requests). |
345| IdP error: unknown or unsupported scope | The IdP rejects scopes it doesn't recognize | Set `oidc.scopes` to exactly the list your IdP accepts; it must include `openid`. The default is `openid profile email offline_access`. |
346| Sessions don't silently renew after setting `oidc.scopes` | `offline_access` was dropped from the override | Add `offline_access` back if your IdP supports it. Without a refresh token, developers re-run the browser login every `session.ttl_hours`. |
347| Browser shows "This request came from another site and was blocked" | Cross-site form POST, blocked as CSRF protection. Expected for embedded or proxied pages | Open the verification link directly |
348| Chrome blocks the Approve button with "Refused to send form data … violates … Content Security Policy directive: form-action", but the same page works in Safari or Firefox | Chrome enforces `form-action` against the entire redirect chain. Your IdP redirects onward to a second host that isn't allowlisted. | Add each additional origin in the redirect chain to `oidc.form_action_origins`. Open Chrome DevTools → Console on the Approve page to see which origin was blocked. |
349| Sign-in completes at the IdP but the callback fails, with a CSP error in Chrome or "this sign-in link has expired" in Safari | The IdP returned the code via `response_mode=form_post`, which auto-submits it cross-origin via POST to `/oauth/callback`. Chrome blocks that under a strict CSP; Safari allows the submit but the callback reads only the query string. | Make sure your IdP honors `response_mode=query`, which the gateway requests explicitly so the callback is a plain redirect |
350| Login works locally but fails behind an ALB | `public_url` still names the local or inner `http://` origin, so the IdP gets the wrong `redirect_uri` | Set `listen.public_url` to the external `https://` origin and register `<public_url>/oauth/callback` with the IdP |
351| Developer sees the trust prompt repeatedly | TLS cert is rotating per replica or per request | Use a stable cert at the ingress, or terminate TLS once and run replicas over plain HTTP internally |
352| CLI `/login`: "Could not verify the gateway's TLS certificate" or `SELF_SIGNED_CERT_IN_CHAIN` | Gateway's TLS chain is signed by a private CA not in the CLI host's trust store | Claude Code reads the OS trust store by default on the native binary and on Node 22.15 or later; [`CLAUDE_CODE_CERT_STORE`](/docs/en/network-config#ca-certificate-store) controls this behavior. If the CA is installed in the OS trust store, ensure developers are on a current runtime. Otherwise set `NODE_EXTRA_CA_CERTS` to the CA certificate PEM before launching. The first-connect fingerprint prompt still applies. |
353| CLI `/login` completes the browser sign-in, then the session ends with `Cloud gateway sign-in was not completed` and a TLS certificate mismatch | On the first request after sign-in, the gateway presented a certificate that doesn't match the fingerprint Claude Code pinned, so Claude Code kept no gateway credential. The usual causes are replicas behind one address that serve different certificates, or something on the network path that intercepts TLS. | Serve one certificate for the hostname, for example by terminating TLS once at the ingress, then have the developer run `/login` again. If that certificate differs from the pinned one, Claude Code shows the [trust prompt](/docs/en/claude-apps-gateway#connect-developers) again with a warning that the certificate changed. |
354| CLI `/login` stops with `The gateway's TLS certificate changed during sign-in: it no longer matches the one you trusted` | A sign-in request reached a server whose certificate doesn't match the one the developer accepted when `/login` started: replicas behind one address serving different certificates, TLS interception on the path, or a certificate rotation while the sign-in was in progress. | Serve one certificate for the hostname, then have the developer start the sign-in again and review the new certificate at the [trust prompt](/docs/en/claude-apps-gateway#connect-developers). |
355355 
356356The `Cloud gateway sign-in was not completed` message names the gateway hostname. When Claude Code has both the pinned fingerprint and the presented one, the message also shows the first 16 characters of each.
357357 

claude-apps-gateway-on-aws Changed · +10 / -10 lines

from line 485
485485 
486486For gateway boot and login errors, see the platform-agnostic [troubleshooting table](/docs/en/claude-apps-gateway-deploy#troubleshooting). The entries below are specific to AWS.
487487 
488| Symptom | Cause | Fix |
489| ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
490| CLI `/login`: `Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip>` | The gateway name resolves to at least one public address. A dual-stack internal ALB publishes public-range AAAA records, and the [private-network check](/docs/en/claude-apps-gateway#prerequisites) requires every resolved address to be private | Create the ALB with `--ip-address-type ipv4`, or serve a separate internal-only DNS name with no public AAAA record |
491| Every Bedrock request returns 502; log shows `Could not load credentials from any providers` | The task runs on the ECS EC2 launch type without a task role, or the pod runs on an EKS node without IRSA, so credentials come from instance metadata, which IMDSv2's default hop limit of 1 stops inside a container. Neither track on this page is affected: Fargate task roles and IRSA don't use instance metadata | Prefer task roles and IRSA. Where instance credentials are unavoidable, raise the hop limit with `aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2`; the [platform-agnostic table](/docs/en/claude-apps-gateway-deploy#troubleshooting) covers the tradeoffs |
492| Bedrock requests return `403 AccessDeniedException` | The account hasn't submitted Anthropic's one-time use case form, the automatic AWS Marketplace subscription that starts on the account's first invoke hasn't finished yet, or the task role's policy is missing the inference-profile or foundation-model ARNs | Submit the use case form from the Bedrock console's Model catalog; if it was just submitted or this is the account's first invoke, retry after a few minutes. Grant `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream` on both ARN families. |
493| Bedrock returns a `ValidationException` saying on-demand throughput isn't supported | A custom `models:` entry maps to a bare foundation-model ID that the region serves only through inference profiles | Map the model to its cross-region inference profile ID (`us.anthropic.*`) instead; the built-in catalog already does this |
494| ECS task stops with `ResourceInitializationError` before the gateway logs anything | The execution role can't read the Secrets Manager secrets, or the private subnets have no path to Secrets Manager or ECR | Grant `secretsmanager:GetSecretValue` on the three `gateway-` secrets' ARNs to the execution role, and provide egress via the NAT gateway, or, without one, interface endpoints for Secrets Manager, ECR, and CloudWatch Logs, which the `awslogs` driver needs at the same stage, plus an S3 gateway endpoint |
495| Gateway boot exits with a Postgres connection-timeout error | The database security group doesn't admit the gateway's security group on 5432, or the service runs outside the database's VPC | Allow 5432 from the gateway's security group on the database's, and run the service in the same VPC as the DB subnet group |
496| Gateway boot exits with a Postgres TLS certificate verification error | The connection string sets `sslmode=verify-full` but the image doesn't trust the RDS CA bundle: the bundle wasn't copied into the image, or `NODE_EXTRA_CA_CERTS` doesn't point at it | Add the build step's two Dockerfile lines that copy the bundle and set `NODE_EXTRA_CA_CERTS`, then rebuild, push under a new tag, and redeploy |
497| Streaming responses drop mid-stream after a quiet period | A gateway older than v2.1.229 on a Bedrock or Claude Platform on AWS upstream sends nothing while the upstream is quiet, for example during extended thinking with no streamed output. The ALB closes a connection after 60 seconds with no data by default, so it cuts the stream at that gap. Gateways v2.1.229 and later keep a quiet stream under that timeout: on those upstreams the gateway emits an SSE `ping` event once about 15 seconds pass with no stream data, and on an Anthropic API upstream it relays the API's own pings | Update the gateway to v2.1.229 or later, or set the `idle_timeout.timeout_seconds` attribute to `3600`, via `modify-load-balancer-attributes` or the `load-balancer-attributes` Ingress annotation on EKS |
488| Symptom | Cause | Fix |
489| - | - | - |
490| CLI `/login`: `Gateway hosts must be on your organization's private network; <host> resolves to the public (or unrecognized) address <ip>` | The gateway name resolves to at least one public address. A dual-stack internal ALB publishes public-range AAAA records, and the [private-network check](/docs/en/claude-apps-gateway#prerequisites) requires every resolved address to be private | Create the ALB with `--ip-address-type ipv4`, or serve a separate internal-only DNS name with no public AAAA record |
491| Every Bedrock request returns 502; log shows `Could not load credentials from any providers` | The task runs on the ECS EC2 launch type without a task role, or the pod runs on an EKS node without IRSA, so credentials come from instance metadata, which IMDSv2's default hop limit of 1 stops inside a container. Neither track on this page is affected: Fargate task roles and IRSA don't use instance metadata | Prefer task roles and IRSA. Where instance credentials are unavoidable, raise the hop limit with `aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2`; the [platform-agnostic table](/docs/en/claude-apps-gateway-deploy#troubleshooting) covers the tradeoffs |
492| Bedrock requests return `403 AccessDeniedException` | The account hasn't submitted Anthropic's one-time use case form, the automatic AWS Marketplace subscription that starts on the account's first invoke hasn't finished yet, or the task role's policy is missing the inference-profile or foundation-model ARNs | Submit the use case form from the Bedrock console's Model catalog; if it was just submitted or this is the account's first invoke, retry after a few minutes. Grant `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream` on both ARN families. |
493| Bedrock returns a `ValidationException` saying on-demand throughput isn't supported | A custom `models:` entry maps to a bare foundation-model ID that the region serves only through inference profiles | Map the model to its cross-region inference profile ID (`us.anthropic.*`) instead; the built-in catalog already does this |
494| ECS task stops with `ResourceInitializationError` before the gateway logs anything | The execution role can't read the Secrets Manager secrets, or the private subnets have no path to Secrets Manager or ECR | Grant `secretsmanager:GetSecretValue` on the three `gateway-` secrets' ARNs to the execution role, and provide egress via the NAT gateway, or, without one, interface endpoints for Secrets Manager, ECR, and CloudWatch Logs, which the `awslogs` driver needs at the same stage, plus an S3 gateway endpoint |
495| Gateway boot exits with a Postgres connection-timeout error | The database security group doesn't admit the gateway's security group on 5432, or the service runs outside the database's VPC | Allow 5432 from the gateway's security group on the database's, and run the service in the same VPC as the DB subnet group |
496| Gateway boot exits with a Postgres TLS certificate verification error | The connection string sets `sslmode=verify-full` but the image doesn't trust the RDS CA bundle: the bundle wasn't copied into the image, or `NODE_EXTRA_CA_CERTS` doesn't point at it | Add the build step's two Dockerfile lines that copy the bundle and set `NODE_EXTRA_CA_CERTS`, then rebuild, push under a new tag, and redeploy |
497| Streaming responses drop mid-stream after a quiet period | A gateway older than v2.1.229 on a Bedrock or Claude Platform on AWS upstream sends nothing while the upstream is quiet, for example during extended thinking with no streamed output. The ALB closes a connection after 60 seconds with no data by default, so it cuts the stream at that gap. Gateways v2.1.229 and later keep a quiet stream under that timeout: on those upstreams the gateway emits an SSE `ping` event once about 15 seconds pass with no stream data, and on an Anthropic API upstream it relays the API's own pings | Update the gateway to v2.1.229 or later, or set the `idle_timeout.timeout_seconds` attribute to `3600`, via `modify-load-balancer-attributes` or the `load-balancer-attributes` Ingress annotation on EKS |
498498 
499499## Telemetry
500500 

claude-apps-gateway-on-gcp Changed · +18 / -18 lines

from line 140
140140 
141141 Set `trusted_proxies` to match your front end. An external GKE Ingress of class `gce` isn't listed: it provisions a public forwarding-rule address, which the `/login` [private-network check](/docs/en/claude-apps-gateway#prerequisites) rejects.
142142 
143 | Front end | `trusted_proxies` |
144 | -------------------------------------------------------- | --------------------------------------------------- |
145 | Cloud Run reached directly, no load balancer | `[169.254.0.0/16]` |
143 | Front end | `trusted_proxies` |
144 | - | - |
145 | Cloud Run reached directly, no load balancer | `[169.254.0.0/16]` |
146146 | Internal Application Load Balancer in front of Cloud Run | `169.254.0.0/16` plus your proxy-only subnet's CIDR |
147 | GKE internal Ingress, class `gce-internal` | Your proxy-only subnet's CIDR |
147 | GKE internal Ingress, class `gce-internal` | Your proxy-only subnet's CIDR |
148148 
149149 The example below uses the internal-load-balancer-in-front-of-Cloud-Run values.
150150 
from line 187
187187 <Step title="Store secrets in Secret Manager">
188188 Create four secrets and grant `roles/secretmanager.secretAccessor` to the `claude-gateway` service account:
189189 
190 | Secret | Source |
191 | ---------------------------- | ----------------------------------------------- |
192 | `gateway-jwt-secret` | `openssl rand -base64 32` |
193 | `gateway-oidc-client-secret` | Google Cloud Console → OAuth client |
194 | `gateway-postgres-url` | `$GATEWAY_POSTGRES_URL` from the Cloud SQL step |
195 | `gateway-config` | the full `gateway.yaml` from the previous step |
190 | Secret | Source |
191 | - | - |
192 | `gateway-jwt-secret` | `openssl rand -base64 32` |
193 | `gateway-oidc-client-secret` | Google Cloud Console → OAuth client |
194 | `gateway-postgres-url` | `$GATEWAY_POSTGRES_URL` from the Cloud SQL step |
195 | `gateway-config` | the full `gateway.yaml` from the previous step |
196196 
197197 How the secrets reach the container differs by track:
198198 
from line 301
301301 
302302For gateway boot and login errors, see the platform-agnostic [troubleshooting table](/docs/en/claude-apps-gateway-deploy#troubleshooting). The entries below are specific to Google Cloud.
303303 
304| Symptom | Cause | Fix |
305| ---------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
306| Cloud Run returns `403 Forbidden` before reaching the container | The invoker IAM check is still enabled | Deploy with `--no-invoker-iam-check`, or grant `allUsers` the `run.invoker` role with `--allow-unauthenticated` |
307| `--no-invoker-iam-check` rejected with `invoker_iam_disabled is not currently available` | Blocked by `constraints/run.managed.requireInvokerIam` | Use `--allow-unauthenticated`. If Domain Restricted Sharing via `constraints/iam.allowedPolicyMemberDomains` blocks that too, use the GKE track, which exposes the gateway at the network layer with no `allUsers` binding. |
308| `Container manifest type … must support amd64/linux` at deploy | Image was built on a non-amd64 host, or buildx emitted an OCI image index | Build with `--platform=linux/amd64 --provenance=false` |
309| Gateway boot exits with a Postgres connection-timeout error on Cloud Run | Service isn't attached to the VPC, or Cloud SQL has no private IP on that VPC | Deploy with `--network` and `--subnet` for Direct VPC egress, and create the Cloud SQL instance with `--no-assign-ip` and `--network` pointing at the same VPC |
310| Google Cloud's Agent Platform requests return `403 PERMISSION_DENIED` | Runtime isn't using the `claude-gateway` service account, or the model isn't enabled in Model Garden for the project | Set `--service-account` on Cloud Run or bind Workload Identity on GKE, and enable each Claude model in Model Garden for the target region |
311| Streaming responses cut off after a fixed duration | Front-end request timeout: the load balancer backend service behind GKE Ingress defaults to 30 seconds and Cloud Run to 300 seconds | Attach a BackendConfig with a raised `timeoutSec` on GKE, or deploy with `--timeout=3600` on Cloud Run |
304| Symptom | Cause | Fix |
305| - | - | - |
306| Cloud Run returns `403 Forbidden` before reaching the container | The invoker IAM check is still enabled | Deploy with `--no-invoker-iam-check`, or grant `allUsers` the `run.invoker` role with `--allow-unauthenticated` |
307| `--no-invoker-iam-check` rejected with `invoker_iam_disabled is not currently available` | Blocked by `constraints/run.managed.requireInvokerIam` | Use `--allow-unauthenticated`. If Domain Restricted Sharing via `constraints/iam.allowedPolicyMemberDomains` blocks that too, use the GKE track, which exposes the gateway at the network layer with no `allUsers` binding. |
308| `Container manifest type … must support amd64/linux` at deploy | Image was built on a non-amd64 host, or buildx emitted an OCI image index | Build with `--platform=linux/amd64 --provenance=false` |
309| Gateway boot exits with a Postgres connection-timeout error on Cloud Run | Service isn't attached to the VPC, or Cloud SQL has no private IP on that VPC | Deploy with `--network` and `--subnet` for Direct VPC egress, and create the Cloud SQL instance with `--no-assign-ip` and `--network` pointing at the same VPC |
310| Google Cloud's Agent Platform requests return `403 PERMISSION_DENIED` | Runtime isn't using the `claude-gateway` service account, or the model isn't enabled in Model Garden for the project | Set `--service-account` on Cloud Run or bind Workload Identity on GKE, and enable each Claude model in Model Garden for the target region |
311| Streaming responses cut off after a fixed duration | Front-end request timeout: the load balancer backend service behind GKE Ingress defaults to 30 seconds and Cloud Run to 300 seconds | Attach a BackendConfig with a raised `timeoutSec` on GKE, or deploy with `--timeout=3600` on Cloud Run |
312312 
313313## Next steps
314314 

claude-apps-gateway-spend-limits Changed · +24 / -24 lines

from line 28
2828 -d '{"scope": {"type": "rbac_group", "rbac_group_id": "contractors"}, "amount": "10000", "period": "daily"}'
2929```
3030 
31| Field | Values | Description |
32| ------------ | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
33| `scope.type` | `user`, `rbac_group`, `organization` | `user` targets one developer by their OpenID Connect (OIDC) `sub`, the stable user ID your identity provider assigns; pass it as `scope.user_id`. `rbac_group` targets an [IdP group](/docs/en/claude-apps-gateway-config#managed) by name; pass it as `scope.rbac_group_id`. `organization` is the org-wide default. The gateway accepts all three; Anthropic's public `POST` is user-only today. |
34| `amount` | Whole-number string of USD cents, or `null` | `null` is unlimited. `"0"` is a zero cap, which blocks every request. |
35| `period` | `daily`, `weekly`, `monthly` | A scope can hold one cap per period, and each enforces independently: a developer is blocked if over any of them. |
31| Field | Values | Description |
32| - | - | - |
33| `scope.type` | `user`, `rbac_group`, `organization` | `user` targets one developer by their OpenID Connect (OIDC) `sub`, the stable user ID your identity provider assigns; pass it as `scope.user_id`. `rbac_group` targets an [IdP group](/docs/en/claude-apps-gateway-config#managed) by name; pass it as `scope.rbac_group_id`. `organization` is the org-wide default. The gateway accepts all three; Anthropic's public `POST` is user-only today. |
34| `amount` | Whole-number string of USD cents, or `null` | `null` is unlimited. `"0"` is a zero cap, which blocks every request. |
35| `period` | `daily`, `weekly`, `monthly` | A scope can hold one cap per period, and each enforces independently: a developer is blocked if over any of them. |
3636 
3737A group or organization cap is a per-seat default that each member inherits, not a shared pool. Per period, a developer's effective cap resolves in this order: a per-user override, then the most restrictive of their group caps, then the org default, then unlimited. [`admin.group_limit_mode: max`](/docs/en/claude-apps-gateway-config#admin) flips the multi-group tie-break to least-restrictive instead.
3838 
from line 91
9191 
9292The endpoints below are served under `/v1/organizations/spend_limits`.
9393 
94| Method and path | Description |
95| ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
96| `GET /v1/organizations/spend_limits` | List configured caps, optionally filtered to one `scope_type` of `organization`, `rbac_group`, or `user`. Query: `?limit=&after_id=&before_id=&scope_type=`. |
97| `POST /v1/organizations/spend_limits` | Create or replace a cap for `{scope, period}`. |
98| `GET /v1/organizations/spend_limits/{id}` | Fetch one cap by its `spl_`-prefixed ID. |
99| `DELETE /v1/organizations/spend_limits/{id}` | Delete one cap. Returns `{type: "spend_limit_deleted", id}`. |
100| `GET /v1/organizations/spend_limits/effective` | Resolved cap and to-date spend per principal per period. |
101| `GET /v1/organizations/spend_limits/audit` | Admin mutation trail, newest-first. Query: `?limit=&after_id=`. |
94| Method and path | Description |
95| - | - |
96| `GET /v1/organizations/spend_limits` | List configured caps, optionally filtered to one `scope_type` of `organization`, `rbac_group`, or `user`. Query: `?limit=&after_id=&before_id=&scope_type=`. |
97| `POST /v1/organizations/spend_limits` | Create or replace a cap for `{scope, period}`. |
98| `GET /v1/organizations/spend_limits/{id}` | Fetch one cap by its `spl_`-prefixed ID. |
99| `DELETE /v1/organizations/spend_limits/{id}` | Delete one cap. Returns `{type: "spend_limit_deleted", id}`. |
100| `GET /v1/organizations/spend_limits/effective` | Resolved cap and to-date spend per principal per period. |
101| `GET /v1/organizations/spend_limits/audit` | Admin mutation trail, newest-first. Query: `?limit=&after_id=`. |
102102 
103103Conventions mirror Anthropic's Admin API:
104104 
from line 123
123123 
124124Group-sourced caps resolve against those last-seen groups with the same `group_limit_mode` tie-break that enforcement uses, so the viewer shows the cap that actually applies.
125125 
126| Query parameter | Description |
127| ---------------- | ------------------------------------------------------------------------------------------------------- |
128| `user_ids[]` | Repeatable. Filter to specific principals by OIDC `sub`. |
129| `period[]` | Repeatable. Filter to `daily`, `weekly`, or `monthly` rows. |
130| `sort` | `spend_desc` lists top spenders first. Requires exactly one `period[]`. |
131| `q` | Case-insensitive substring filter over the OIDC `sub`, last-seen email, and last-seen display name. |
126| Query parameter | Description |
127| - | - |
128| `user_ids[]` | Repeatable. Filter to specific principals by OIDC `sub`. |
129| `period[]` | Repeatable. Filter to `daily`, `weekly`, or `monthly` rows. |
130| `sort` | `spend_desc` lists top spenders first. Requires exactly one `period[]`. |
131| `q` | Case-insensitive substring filter over the OIDC `sub`, last-seen email, and last-seen display name. |
132132| `limit` / `page` | Page size, 1–1000 with a default of 20, and the opaque cursor from the previous response's `next_page`. |
133133 
134134<Warning>
from line 147
147147 
148148The gateway holds four spend-related tables; an hourly sweep enforces the retention windows:
149149 
150| Table | Contents | Retention |
151| ------------------ | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
152| `spend` | Per-principal period-to-date counters in cents | [`admin.spend_retention_months`](/docs/en/claude-apps-gateway-config#admin), default 13 |
153| `spend_limits` | The configured caps | Until deleted via the API |
154| `admin_audit` | The mutation trail | [`admin.audit_retention_days`](/docs/en/claude-apps-gateway-config#admin), default 365 |
150| Table | Contents | Retention |
151| - | - | - |
152| `spend` | Per-principal period-to-date counters in cents | [`admin.spend_retention_months`](/docs/en/claude-apps-gateway-config#admin), default 13 |
153| `spend_limits` | The configured caps | Until deleted via the API |
154| `admin_audit` | The mutation trail | [`admin.audit_retention_days`](/docs/en/claude-apps-gateway-config#admin), default 365 |
155155| `principal_emails` | Each principal's last-seen email, display name, and IdP groups. Contains PII. | [`admin.identity_retention_days`](/docs/en/claude-apps-gateway-config#admin) since last activity, default 90 |
156156 
157157When a developer leaves, delete any per-user cap via `DELETE /v1/organizations/spend_limits/{id}`; their spend and identity rows age out on the retention windows above. To erase one person immediately, for offboarding or a data subject access request (DSAR), run `DELETE FROM principal_emails WHERE principal = '<sub>'` directly against the gateway database. That removes the only table holding their email, name, and groups. The `spend` and `admin_audit` rows reference the pseudonymous OIDC `sub` only and age out on their own windows.

claude-code-on-the-web Changed · +21 / -21 lines

from line 44
4444 
4545Cloud sessions need access to your GitHub repositories to clone code and push branches. You can grant access in two ways:
4646 
47| Method | How you connect | Repositories sessions can reach | Best for |
48| :--------------- | :----------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------- |
49| **GitHub App** | Authorize the Claude GitHub App during [web onboarding](/docs/en/web-quickstart) | Any public repository, and private repositories that the Claude GitHub App is installed on | Browser onboarding; teams that want [Auto-fix](#auto-fix-pull-requests) |
50| **`/web-setup`** | Run `/web-setup` in your terminal to send your local `gh` CLI token to your Claude account | Any repository your `gh` token can access, whether or not the Claude GitHub App is installed | Individual developers who already use `gh` |
47| Method | How you connect | Repositories sessions can reach | Best for |
48| :- | :- | :- | :- |
49| **GitHub App** | Authorize the Claude GitHub App during [web onboarding](/docs/en/web-quickstart) | Any public repository, and private repositories that the Claude GitHub App is installed on | Browser onboarding; teams that want [Auto-fix](#auto-fix-pull-requests) |
50| **`/web-setup`** | Run `/web-setup` in your terminal to send your local `gh` CLI token to your Claude account | Any repository your `gh` token can access, whether or not the Claude GitHub App is installed | Individual developers who already use `gh` |
5151 
5252Installing the Claude GitHub App on a repository also enables [Auto-fix](#auto-fix-pull-requests) for pull requests in it.
5353 
from line 168
168168 
169169The CLI prefixes errors with `Error: `. A failed delivery is wrapped as `failed to send message to cloud session <id>: <reason>`.
170170 
171| Message | What it means |
172| --------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
171| Message | What it means |
172| - | - |
173173| `Cloud sessions aren't available with <provider>. They run on Anthropic's infrastructure and require an Anthropic account.` | Claude Code is configured for a third-party provider. The message names the provider with the label your configuration uses, such as `Amazon Bedrock` or `Google Vertex AI`. Remove that provider's configuration, for example by unsetting `CLAUDE_CODE_USE_BEDROCK`, and sign in with an Anthropic account (`claude auth login`). |
174| `Cloud sessions are disabled by your organization's policy. Contact your organization admin to enable them.` | The `allow_remote_sessions` organization policy is off. |
175| `Couldn't verify your organization's policy for cloud sessions. Check your network connection and try again.` | Claude Code couldn't fetch your organization's policy, so it refuses the send rather than assume cloud sessions are allowed. Check your network connection and retry. |
176| `Attaching to an existing cloud session is not enabled for your account.` | You ran `--cloud <session-id>` without `-p`. Send the message with `claude -p "your message" --cloud <session-id>`. |
177| `Session not found: <id>` | The ID or URL doesn't match a session you can access. Check it against the session's claude.ai/code URL. |
178| `cloud session <id> is archived and cannot accept new messages` | The session has been archived. Start a new session instead. |
174| `Cloud sessions are disabled by your organization's policy. Contact your organization admin to enable them.` | The `allow_remote_sessions` organization policy is off. |
175| `Couldn't verify your organization's policy for cloud sessions. Check your network connection and try again.` | Claude Code couldn't fetch your organization's policy, so it refuses the send rather than assume cloud sessions are allowed. Check your network connection and retry. |
176| `Attaching to an existing cloud session is not enabled for your account.` | You ran `--cloud <session-id>` without `-p`. Send the message with `claude -p "your message" --cloud <session-id>`. |
177| `Session not found: <id>` | The ID or URL doesn't match a session you can access. Check it against the session's claude.ai/code URL. |
178| `cloud session <id> is archived and cannot accept new messages` | The session has been archived. Start a new session instead. |
179179 
180180### From cloud to terminal
181181 
from line 195
195195 
196196Teleport checks these requirements before resuming a session. If any requirement isn't met, you'll see an error or be prompted to resolve the issue.
197197 
198| Requirement | Details |
199| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
200| Clean git state | Your working directory must have no uncommitted changes. Teleport prompts you to stash changes if needed. |
198| Requirement | Details |
199| - | - |
200| Clean git state | Your working directory must have no uncommitted changes. Teleport prompts you to stash changes if needed. |
201201| Correct repository | You must run `--teleport` from a checkout of the same repository, not a fork. If you run it from a checkout of a different repository, Claude Code shows an error that names both the session's repository and your checkout's. Before v2.1.219, the error didn't name your checkout's repository. If Claude Code can't parse your remote into a hostname, for example an SSH host alias like `git@work:owner/repo.git`, it asks you to confirm, and accepts the checkout when the remote's owner and repository name match the session's repository. |
202| Branch available | The branch from the cloud session must have been pushed to the remote. Teleport automatically fetches and checks it out. |
203| Same account | You must be authenticated to the same claude.ai account used in the cloud session. |
202| Branch available | The branch from the cloud session must have been pushed to the remote. Teleport automatically fetches and checks it out. |
203| Same account | You must be authenticated to the same claude.ai account used in the cloud session. |
204204 
205205#### `--teleport` is unavailable
206206 
from line 226
226226 
227227For context management specifically:
228228 
229| Command | Works in cloud sessions | Notes |
230| :--------- | :---------------------- | :----------------------------------------------------------------------------------------------------------------------- |
231| `/compact` | Yes | Summarizes the conversation to free up context. Accepts optional focus instructions like `/compact keep the test output` |
232| `/context` | Yes | Shows what's currently in the context window |
233| `/clear` | No | Start a new session from the sidebar instead |
229| Command | Works in cloud sessions | Notes |
230| :- | :- | :- |
231| `/compact` | Yes | Summarizes the conversation to free up context. Accepts optional focus instructions like `/compact keep the test output` |
232| `/context` | Yes | Shows what's currently in the context window |
233| `/clear` | No | Start a new session from the sidebar instead |
234234 
235235Auto-compaction runs automatically when the context window approaches capacity. Cloud sessions set [`CLAUDE_AUTOCOMPACT_PCT_OVERRIDE`](/docs/en/env-vars) themselves, so compaction triggers partway through the [auto-compact window](/docs/en/model-config#set-the-auto-compact-window) rather than when the window fills. That value overrides one you add in your [environment variables](/docs/en/cloud-environments#set-environment-variables), so adding the variable there doesn't change when compaction triggers.
236236 

claude-directory Changed · +89 / -89 lines

from line 1442
14421442 
14431443The explorer covers files you author and edit. A few related files live elsewhere:
14441444 
1445| File | Location | Purpose |
1446| ----------------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1447| `managed-settings.json` | System-level, varies by OS | Enterprise-enforced settings that you can't override, apart from [narrow exceptions](/docs/en/settings#security-keys-where-the-stricter-value-applies). See [where to save the file](/docs/en/managed-settings#deploy-a-managed-settings-file) and [which managed source Claude Code uses](/docs/en/managed-settings#precedence-within-the-managed-tier). |
1448| `CLAUDE.local.md` | Project root | Your private preferences for this project, loaded alongside CLAUDE.md. Create it manually and add it to `.gitignore`. |
1449| `AGENTS.md` | Project root, `.claude/`, or any directory | Project instructions you write for AI coding agents. Claude Code can [load it](/docs/en/memory#agents-md) on its own or alongside `CLAUDE.md`. |
1450| Installed plugins | `~/.claude/plugins` | Cloned marketplaces, installed plugin versions, the `installed_plugins.json` install record, and per-plugin data, managed by `claude plugin` commands. Plugins [synced from your claude.ai account](/docs/en/plugins/loading#synced-plugins) download into `~/.claude/plugins/synced/`. For a plugin installed from a marketplace [`command` source](/docs/en/plugins/marketplace-reference#command-plugin-source) in link mode, Claude Code stores links here instead of a copy, and the plugin's files stay in the directory the command prints. A `command` source requires Claude Code v2.1.229 or later. A plugin listed by relative path in a local-directory marketplace also [loads in place](/docs/en/plugins/loading#find-plugins-on-disk) from its source directory rather than from a cache copy. See [plugin caching](/docs/en/plugins/loading#find-plugins-on-disk) for how orphaned versions are cleaned up. |
1445| File | Location | Purpose |
1446| - | - | - |
1447| `managed-settings.json` | System-level, varies by OS | Enterprise-enforced settings that you can't override, apart from [narrow exceptions](/docs/en/settings#security-keys-where-the-stricter-value-applies). See [where to save the file](/docs/en/managed-settings#deploy-a-managed-settings-file) and [which managed source Claude Code uses](/docs/en/managed-settings#precedence-within-the-managed-tier). |
1448| `CLAUDE.local.md` | Project root | Your private preferences for this project, loaded alongside CLAUDE.md. Create it manually and add it to `.gitignore`. |
1449| `AGENTS.md` | Project root, `.claude/`, or any directory | Project instructions you write for AI coding agents. Claude Code can [load it](/docs/en/memory#agents-md) on its own or alongside `CLAUDE.md`. |
1450| Installed plugins | `~/.claude/plugins` | Cloned marketplaces, installed plugin versions, the `installed_plugins.json` install record, and per-plugin data, managed by `claude plugin` commands. Plugins [synced from your claude.ai account](/docs/en/plugins/loading#synced-plugins) download into `~/.claude/plugins/synced/`. For a plugin installed from a marketplace [`command` source](/docs/en/plugins/marketplace-reference#command-plugin-source) in link mode, Claude Code stores links here instead of a copy, and the plugin's files stay in the directory the command prints. A `command` source requires Claude Code v2.1.229 or later. A plugin listed by relative path in a local-directory marketplace also [loads in place](/docs/en/plugins/loading#find-plugins-on-disk) from its source directory rather than from a cache copy. See [plugin caching](/docs/en/plugins/loading#find-plugins-on-disk) for how orphaned versions are cleaned up. |
14511451 
14521452`~/.claude` also holds data Claude Code writes as you work: transcripts, prompt history, file snapshots, caches, and logs. See [application data](#application-data) below.
14531453 
from line 1455
14551455 
14561456Different kinds of customization live in different files. Use this table to find where a change belongs.
14571457 
1458| You want to | Edit | Scope | Reference |
1459| :------------------------------------------------- | :--------------------------------------- | :---------------- | :-------------------------------------------------- |
1460| Give Claude project context and conventions | `CLAUDE.md` | project or global | [Memory](/docs/en/memory) |
1461| Allow or block specific tool calls | `settings.json` `permissions` or `hooks` | project or global | [Permissions](/docs/en/permissions), [Hooks](/docs/en/hooks) |
1462| Run a script before or after tool calls | `settings.json` `hooks` | project or global | [Hooks](/docs/en/hooks) |
1463| Set environment variables for the session | `settings.json` `env` | project or global | [Settings](/docs/en/settings-reference#all-settings) |
1464| Keep personal overrides out of git | `settings.local.json` | project only | [Settings scopes](/docs/en/settings#where-settings-live) |
1465| Add a prompt or capability you invoke with `/name` | `skills/<name>/SKILL.md` | project or global | [Skills](/docs/en/skills) |
1466| Define a specialized subagent with its own tools | `agents/*.md` | project or global | [Subagents](/docs/en/sub-agents) |
1467| Orchestrate many subagents from a script | `workflows/*.js` | project or global | [Dynamic workflows](/docs/en/workflows) |
1468| Connect external tools over MCP | `.mcp.json` | project only | [MCP](/docs/en/mcp) |
1469| Change how Claude formats responses | `output-styles/*.md` | project or global | [Output styles](/docs/en/output-styles) |
1458| You want to | Edit | Scope | Reference |
1459| :- | :- | :- | :- |
1460| Give Claude project context and conventions | `CLAUDE.md` | project or global | [Memory](/docs/en/memory) |
1461| Allow or block specific tool calls | `settings.json` `permissions` or `hooks` | project or global | [Permissions](/docs/en/permissions), [Hooks](/docs/en/hooks) |
1462| Run a script before or after tool calls | `settings.json` `hooks` | project or global | [Hooks](/docs/en/hooks) |
1463| Set environment variables for the session | `settings.json` `env` | project or global | [Settings](/docs/en/settings-reference#all-settings) |
1464| Keep personal overrides out of git | `settings.local.json` | project only | [Settings scopes](/docs/en/settings#where-settings-live) |
1465| Add a prompt or capability you invoke with `/name` | `skills/<name>/SKILL.md` | project or global | [Skills](/docs/en/skills) |
1466| Define a specialized subagent with its own tools | `agents/*.md` | project or global | [Subagents](/docs/en/sub-agents) |
1467| Orchestrate many subagents from a script | `workflows/*.js` | project or global | [Dynamic workflows](/docs/en/workflows) |
1468| Connect external tools over MCP | `.mcp.json` | project only | [MCP](/docs/en/mcp) |
1469| Change how Claude formats responses | `output-styles/*.md` | project or global | [Output styles](/docs/en/output-styles) |
14701470 
14711471## File reference
14721472 
from line 1484
14841484 
14851485Click a filename to open that node in the explorer above.
14861486 
1487| File | Scope | Commit | What it does | Reference |
1488| --------------------------------------------------- | ------------------ | ------ | ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
1489| [`CLAUDE.md`](#ce-claude-md) | Project and global | ✓ | Instructions loaded every session | [Memory](/docs/en/memory) |
1490| [`rules/*.md`](#ce-rules) | Project and global | ✓ | Topic-scoped instructions, optionally path-gated | [Rules](/docs/en/memory#organize-rules-with-claude/rules/) |
1491| [`settings.json`](#ce-settings-json) | Project and global | ✓ | Permissions, hooks, env vars, model defaults | [Settings](/docs/en/settings) |
1492| [`settings.local.json`](#ce-settings-local-json) | Project only | | Your personal overrides, gitignored when Claude Code saves a setting to it | [Settings scopes](/docs/en/settings#where-settings-live) |
1493| [`.mcp.json`](#ce-mcp-json) | Project only | ✓ | Team-shared MCP servers | [MCP scopes](/docs/en/mcp#mcp-installation-scopes) |
1494| [`.worktreeinclude`](#ce-worktreeinclude) | Project only | ✓ | Gitignored files to copy into new worktrees | [Worktrees](/docs/en/worktrees#copy-gitignored-files-into-worktrees) |
1495| [`skills/<name>/SKILL.md`](#ce-skills) | Project and global | ✓ | Reusable prompts invoked with `/name` or auto-invoked | [Skills](/docs/en/skills) |
1496| [`commands/*.md`](#ce-commands) | Project and global | ✓ | Single-file prompts; same mechanism as skills | [Skills](/docs/en/skills) |
1497| [`output-styles/*.md`](#ce-output-styles) | Project and global | ✓ | Custom instruction sets that adjust how Claude works | [Output styles](/docs/en/output-styles) |
1498| [`agents/*.md`](#ce-agents) | Project and global | ✓ | Subagent definitions with their own prompt and tools | [Subagents](/docs/en/sub-agents) |
1499| [`workflows/*.js`](#ce-workflows) | Project and global | ✓ | Dynamic workflow scripts written by Claude and saved from `/workflows`; each file becomes a `/<name>` command | [Dynamic workflows](/docs/en/workflows) |
1500| [`agent-memory/<name>/`](#ce-agent-memory) | Project and global | ✓ | Persistent memory for subagents | [Persistent memory](/docs/en/sub-agents#enable-persistent-memory) |
1501| [`~/.claude.json`](#ce-claude-json) | Global only | | App state, OAuth, UI toggles, personal MCP servers | [Global config](/docs/en/settings-reference#global-config-settings) |
1502| [`projects/<project>/memory/`](#ce-global-projects) | Global only | | Auto memory: Claude's notes to itself across sessions | [Auto memory](/docs/en/memory#auto-memory) |
1503| [`keybindings.json`](#ce-keybindings) | Global only | | Custom keyboard shortcuts | [Keybindings](/docs/en/keybindings) |
1504| [`themes/*.json`](#ce-themes) | Global only | | Custom color themes | [Custom themes](/docs/en/terminal-config#create-a-custom-theme) |
1487| File | Scope | Commit | What it does | Reference |
1488| - | - | - | - | - |
1489| [`CLAUDE.md`](#ce-claude-md) | Project and global | ✓ | Instructions loaded every session | [Memory](/docs/en/memory) |
1490| [`rules/*.md`](#ce-rules) | Project and global | ✓ | Topic-scoped instructions, optionally path-gated | [Rules](/docs/en/memory#organize-rules-with-claude/rules/) |
1491| [`settings.json`](#ce-settings-json) | Project and global | ✓ | Permissions, hooks, env vars, model defaults | [Settings](/docs/en/settings) |
1492| [`settings.local.json`](#ce-settings-local-json) | Project only | | Your personal overrides, gitignored when Claude Code saves a setting to it | [Settings scopes](/docs/en/settings#where-settings-live) |
1493| [`.mcp.json`](#ce-mcp-json) | Project only | ✓ | Team-shared MCP servers | [MCP scopes](/docs/en/mcp#mcp-installation-scopes) |
1494| [`.worktreeinclude`](#ce-worktreeinclude) | Project only | ✓ | Gitignored files to copy into new worktrees | [Worktrees](/docs/en/worktrees#copy-gitignored-files-into-worktrees) |
1495| [`skills/<name>/SKILL.md`](#ce-skills) | Project and global | ✓ | Reusable prompts invoked with `/name` or auto-invoked | [Skills](/docs/en/skills) |
1496| [`commands/*.md`](#ce-commands) | Project and global | ✓ | Single-file prompts; same mechanism as skills | [Skills](/docs/en/skills) |
1497| [`output-styles/*.md`](#ce-output-styles) | Project and global | ✓ | Custom instruction sets that adjust how Claude works | [Output styles](/docs/en/output-styles) |
1498| [`agents/*.md`](#ce-agents) | Project and global | ✓ | Subagent definitions with their own prompt and tools | [Subagents](/docs/en/sub-agents) |
1499| [`workflows/*.js`](#ce-workflows) | Project and global | ✓ | Dynamic workflow scripts written by Claude and saved from `/workflows`; each file becomes a `/<name>` command | [Dynamic workflows](/docs/en/workflows) |
1500| [`agent-memory/<name>/`](#ce-agent-memory) | Project and global | ✓ | Persistent memory for subagents | [Persistent memory](/docs/en/sub-agents#enable-persistent-memory) |
1501| [`~/.claude.json`](#ce-claude-json) | Global only | | App state, OAuth, UI toggles, personal MCP servers | [Global config](/docs/en/settings-reference#global-config-settings) |
1502| [`projects/<project>/memory/`](#ce-global-projects) | Global only | | Auto memory: Claude's notes to itself across sessions | [Auto memory](/docs/en/memory#auto-memory) |
1503| [`keybindings.json`](#ce-keybindings) | Global only | | Custom keyboard shortcuts | [Keybindings](/docs/en/keybindings) |
1504| [`themes/*.json`](#ce-themes) | Global only | | Custom color themes | [Custom themes](/docs/en/terminal-config#create-a-custom-theme) |
15051505 
15061506## Frontmatter fields by file
15071507 
15081508Skills, command files, subagents, output styles, and rules read their configuration from YAML [frontmatter](/docs/en/glossary#frontmatter) at the top of the file, and each accepts its own set of fields. This table lists the field names for each file and links to the reference that describes them.
15091509 
1510| File | Frontmatter fields | Reference |
1511| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- |
1512| `skills/<name>/SKILL.md` | `name`, `description`, `when_to_use`, `argument-hint`, `arguments`, `disable-model-invocation`, `user-invocable`, `allowed-tools`, `disallowed-tools`, `model`, `effort`, `context`, `agent`, `background`, `hooks`, `paths`, `shell`, `metadata`, `license`, `compatibility` | [Skill frontmatter](/docs/en/skills#frontmatter-reference) |
1513| `commands/*.md` | The skill fields except `name` and `paths` | [Skill frontmatter](/docs/en/skills#frontmatter-reference) |
1514| `agents/*.md` | `name`, `description`, `tools`, `disallowedTools`, `model`, `permissionMode`, `maxTurns`, `skills`, `mcpServers`, `hooks`, `memory`, `background`, `effort`, `isolation`, `color`, `initialPrompt`, `omitClaudeMd`, `experimental` | [Subagent frontmatter](/docs/en/sub-agents#supported-frontmatter-fields) |
1515| `output-styles/*.md` | `name`, `description`, `keep-coding-instructions`, `force-for-plugin` | [Output style frontmatter](/docs/en/output-styles#frontmatter) |
1516| `rules/*.md` | `paths` | [Rule frontmatter](/docs/en/memory#rules-frontmatter-reference) |
1510| File | Frontmatter fields | Reference |
1511| - | - | - |
1512| `skills/<name>/SKILL.md` | `name`, `description`, `when_to_use`, `argument-hint`, `arguments`, `disable-model-invocation`, `user-invocable`, `allowed-tools`, `disallowed-tools`, `model`, `effort`, `context`, `agent`, `background`, `hooks`, `paths`, `shell`, `metadata`, `license`, `compatibility` | [Skill frontmatter](/docs/en/skills#frontmatter-reference) |
1513| `commands/*.md` | The skill fields except `name` and `paths` | [Skill frontmatter](/docs/en/skills#frontmatter-reference) |
1514| `agents/*.md` | `name`, `description`, `tools`, `disallowedTools`, `model`, `permissionMode`, `maxTurns`, `skills`, `mcpServers`, `hooks`, `memory`, `background`, `effort`, `isolation`, `color`, `initialPrompt`, `omitClaudeMd`, `experimental` | [Subagent frontmatter](/docs/en/sub-agents#supported-frontmatter-fields) |
1515| `output-styles/*.md` | `name`, `description`, `keep-coding-instructions`, `force-for-plugin` | [Output style frontmatter](/docs/en/output-styles#frontmatter) |
1516| `rules/*.md` | `paths` | [Rule frontmatter](/docs/en/memory#rules-frontmatter-reference) |
15171517 
15181518Agents shipped in a [plugin](/docs/en/plugins/components#agents) honor a subset of the subagent fields.
15191519 
from line 1529
15291529 
15301530Claude Code deletes the files in the paths below once they're older than [`cleanupPeriodDays`](/docs/en/settings-reference#cleanupperioddays), as long as it can safely determine the retention period. The default is 30 days and the minimum is 1; setting `0` fails with a validation error. The same age cutoff applies to automatic removal of [orphaned worktrees](/docs/en/worktrees#clean-up-subagent-and-background-session-worktrees).
15311531 
1532| Path under `~/.claude/` | Contents |
1533| ------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1534| `projects/<project>/<session>.jsonl` | Full conversation transcript: every message, tool call, and tool result |
1535| `projects/<project>/<session>.orphaned-<timestamp>-<suffix>.jsonl`, `projects/<project>/<session>.jsonl.superseded-<timestamp>` | A previous transcript for the session that Claude Code set aside instead of overwriting or deleting it. It doesn't appear in the session picker |
1536| `projects/<project>/<session>/subagents/` | [Subagent](/docs/en/sub-agents) conversation transcripts, removed with the parent session transcript when it ages out |
1537| `projects/<project>/<session>/tool-results/` | Large tool outputs spilled to separate files, and full-size copies of [images that MCP tools return](/docs/en/mcp#images-in-tool-results) |
1538| `file-history/<session>/` | Pre-edit snapshots of files Claude changed, used for [checkpoint restore](/docs/en/checkpointing). Holds snapshots for the 100 most recent checkpoints; snapshot files that no retained checkpoint references are deleted, except each file's first snapshot |
1539| `plans/` | Plan files written during [plan mode](/docs/en/permission-modes#analyze-before-you-edit-with-plan-mode) |
1540| `debug/` | Per-session debug logs, written while debug logging is on, such as when you start with [`--debug`](/docs/en/cli-reference#cli-flags) or run `/debug` |
1541| `paste-cache/` | Contents of large pastes |
1542| `image-cache/<session>/` | Attached images saved by Claude Code v2.1.274 and earlier. Later versions save pasted and attached images outside `~/.claude`, in an `images/` directory for each session under the temp directory that [`CLAUDE_CODE_TMPDIR`](/docs/en/env-vars) controls. The sweep removes other sessions' leftover directories here, whatever their age. |
1543| `uploads/<session>/` | Files you attach from the web or mobile app, and photos you attach from the mobile app, when messaging a [Remote Control](/docs/en/remote-control) session. An attachment to a [cloud session](/docs/en/claude-code-on-the-web) is saved in that session's own cloud environment instead, not on your machine. |
1544| `session-env/` | Per-session environment metadata |
1545| `tasks/` | Task lists written by the task tools, one directory per list |
1546| `shell-snapshots/` | Aliases, functions, and shell options captured at startup and applied by the [Bash tool](/docs/en/tools-reference#bash-tool-behavior) to each command. Removed on clean exit. The sweep clears any left after a crash. |
1547| `backups/` | Earlier versions of `~/.claude.json`, copied when Claude Code rewrites the file. Claude Code keeps the five newest, plus a copy of any version it couldn't parse. |
1548| `feedback-bundles/` | Redacted transcript archives written by `/feedback` on third-party providers or when no Anthropic credentials are configured, for sending to your Anthropic account team |
1549| `feedback/drafts/` | Queued [Claude-drafted feedback](/docs/en/tools-reference#sendfeedback-tool-behavior) awaiting your review in `/feedback`. Swept after `cleanupPeriodDays` or 30 days, whichever is shorter. When the queue is at its 10-draft limit, Claude Code deletes the oldest draft to make room. |
1550| `usage-data/` | `report.html` and timestamped report copies written by [`/insights`](/docs/en/costs#analyze-your-usage-patterns), plus cached per-session analysis data used to build them |
1551| `skills/.trash/`, `plugins/.trash/` | [Skills](/docs/en/skills#how-synced-skills-behave) and [plugins](/docs/en/plugins/loading#synced-plugins) that the claude.ai sync removed, such as after you turn one off on claude.ai or stop syncing. The files stay here so you can recover them until the sweep deletes them |
1552| `todos/`, `statsig/`, `logs/` | Legacy directories from older versions. No longer written. The sweep removes their contents and then the empty directory. |
1532| Path under `~/.claude/` | Contents |
1533| - | - |
1534| `projects/<project>/<session>.jsonl` | Full conversation transcript: every message, tool call, and tool result |
1535| `projects/<project>/<session>.orphaned-<timestamp>-<suffix>.jsonl`, `projects/<project>/<session>.jsonl.superseded-<timestamp>` | A previous transcript for the session that Claude Code set aside instead of overwriting or deleting it. It doesn't appear in the session picker |
1536| `projects/<project>/<session>/subagents/` | [Subagent](/docs/en/sub-agents) conversation transcripts, removed with the parent session transcript when it ages out |
1537| `projects/<project>/<session>/tool-results/` | Large tool outputs spilled to separate files, and full-size copies of [images that MCP tools return](/docs/en/mcp#images-in-tool-results) |
1538| `file-history/<session>/` | Pre-edit snapshots of files Claude changed, used for [checkpoint restore](/docs/en/checkpointing). Holds snapshots for the 100 most recent checkpoints; snapshot files that no retained checkpoint references are deleted, except each file's first snapshot |
1539| `plans/` | Plan files written during [plan mode](/docs/en/permission-modes#analyze-before-you-edit-with-plan-mode) |
1540| `debug/` | Per-session debug logs, written while debug logging is on, such as when you start with [`--debug`](/docs/en/cli-reference#cli-flags) or run `/debug` |
1541| `paste-cache/` | Contents of large pastes |
1542| `image-cache/<session>/` | Attached images saved by Claude Code v2.1.274 and earlier. Later versions save pasted and attached images outside `~/.claude`, in an `images/` directory for each session under the temp directory that [`CLAUDE_CODE_TMPDIR`](/docs/en/env-vars) controls. The sweep removes other sessions' leftover directories here, whatever their age. |
1543| `uploads/<session>/` | Files you attach from the web or mobile app, and photos you attach from the mobile app, when messaging a [Remote Control](/docs/en/remote-control) session. An attachment to a [cloud session](/docs/en/claude-code-on-the-web) is saved in that session's own cloud environment instead, not on your machine. |
1544| `session-env/` | Per-session environment metadata |
1545| `tasks/` | Task lists written by the task tools, one directory per list |
1546| `shell-snapshots/` | Aliases, functions, and shell options captured at startup and applied by the [Bash tool](/docs/en/tools-reference#bash-tool-behavior) to each command. Removed on clean exit. The sweep clears any left after a crash. |
1547| `backups/` | Earlier versions of `~/.claude.json`, copied when Claude Code rewrites the file. Claude Code keeps the five newest, plus a copy of any version it couldn't parse. |
1548| `feedback-bundles/` | Redacted transcript archives written by `/feedback` on third-party providers or when no Anthropic credentials are configured, for sending to your Anthropic account team |
1549| `feedback/drafts/` | Queued [Claude-drafted feedback](/docs/en/tools-reference#sendfeedback-tool-behavior) awaiting your review in `/feedback`. Swept after `cleanupPeriodDays` or 30 days, whichever is shorter. When the queue is at its 10-draft limit, Claude Code deletes the oldest draft to make room. |
1550| `usage-data/` | `report.html` and timestamped report copies written by [`/insights`](/docs/en/costs#analyze-your-usage-patterns), plus cached per-session analysis data used to build them |
1551| `skills/.trash/`, `plugins/.trash/` | [Skills](/docs/en/skills#how-synced-skills-behave) and [plugins](/docs/en/plugins/loading#synced-plugins) that the claude.ai sync removed, such as after you turn one off on claude.ai or stop syncing. The files stay here so you can recover them until the sweep deletes them |
1552| `todos/`, `statsig/`, `logs/` | Legacy directories from older versions. No longer written. The sweep removes their contents and then the empty directory. |
15531553 
15541554Session files in `sessions/`, auto memory, and Claude Desktop and Cowork transcripts each follow their own retention rule:
15551555 
from line 1586
15861586 
15871587The retention cleanup sweep doesn't remove the paths below. Claude Code keeps them until you delete them, apart from the two caches it deletes when you log out.
15881588 
1589| Path under `~/.claude/` | Contents |
1590| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1591| `history.jsonl` | Every prompt you've typed, with timestamp and project path. Used for up-arrow recall, `Ctrl+R` history search, and `!` shell-command completion. |
1592| `stats-cache.json` | Aggregated token and cost counts shown by `/usage` |
1593| `remote-settings.json` | Cached copy of [server-managed settings](/docs/en/server-managed-settings) for your organization, or `{}` when your organization has configured none. Only present when the session [fetches them](/docs/en/server-managed-settings#platform-availability). Claude Code checks for updates at startup and hourly during a session. Claude Code deletes it when you log out. |
1594| `cache/changelog.md` | Cached copy of the Claude Code changelog, shown by `/release-notes`. Refreshed in the background. |
1595| `policy-limits.json` | Cached feature policy settings for your organization. Only present for some account types. Refreshed automatically. A `policy-limits.json.stamp.json` sidecar records which account or API key the cache belongs to. Claude Code deletes both files when you log out. |
1589| Path under `~/.claude/` | Contents |
1590| - | - |
1591| `history.jsonl` | Every prompt you've typed, with timestamp and project path. Used for up-arrow recall, `Ctrl+R` history search, and `!` shell-command completion. |
1592| `stats-cache.json` | Aggregated token and cost counts shown by `/usage` |
1593| `remote-settings.json` | Cached copy of [server-managed settings](/docs/en/server-managed-settings) for your organization, or `{}` when your organization has configured none. Only present when the session [fetches them](/docs/en/server-managed-settings#platform-availability). Claude Code checks for updates at startup and hourly during a session. Claude Code deletes it when you log out. |
1594| `cache/changelog.md` | Cached copy of the Claude Code changelog, shown by `/release-notes`. Refreshed in the background. |
1595| `policy-limits.json` | Cached feature policy settings for your organization. Only present for some account types. Refreshed automatically. A `policy-limits.json.stamp.json` sidecar records which account or API key the cache belongs to. Claude Code deletes both files when you log out. |
15961596 
15971597<span id="state-files-to-keep" />
15981598 
from line 1671
16711671 
16721672You can also delete any of the application-data paths above by hand, apart from the [state files to keep](#state-files-to-keep). New sessions are unaffected. The table below shows what you lose for past sessions.
16731673 
1674| Delete | You lose |
1675| -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1676| `~/.claude/projects/` | Resume, continue, and rewind for past sessions, and auto memory for every project |
1677| `~/.claude/history.jsonl` | Up-arrow prompt recall, `Ctrl+R` history search, and `!` shell-command completion |
1678| `~/.claude/paste-cache/` | Pasted text in recalled prompts; see [paste large content](/docs/en/terminal-config#paste-large-content) |
1679| `~/.claude/uploads/` | Attachments that past [Remote Control](/docs/en/remote-control) sessions refer to by path |
1680| `~/.claude/file-history/` | Checkpoint restore for past sessions |
1681| `~/.claude/stats-cache.json` | Historical totals shown by `/usage` |
1682| `~/.claude/usage-data/` | Past [`/insights`](/docs/en/costs#analyze-your-usage-patterns) reports and the cached analysis data used to build them |
1683| `~/.claude/feedback-bundles/` | Feedback and bug-report archives you haven't yet sent to your Anthropic account team |
1684| `~/.claude/feedback/drafts/` | [Claude-drafted feedback](/docs/en/tools-reference#sendfeedback-tool-behavior) you haven't sent |
1685| `~/.claude/remote-settings.json` | Nothing. Re-fetched on next launch. |
1686| `~/.claude/cache/changelog.md` | Nothing. Refreshed in the background. |
1687| `~/.claude/policy-limits.json` | Nothing. Refreshed automatically. |
1688| `~/.claude/tasks/` | Task lists that a resumed session would pick up |
1689| `~/.claude/skills/.trash/`, `~/.claude/plugins/.trash/` | The chance to recover [synced skills](/docs/en/skills#how-synced-skills-behave) and [synced plugins](/docs/en/plugins/loading#synced-plugins) that Claude Code removed |
1690| `~/.claude/debug/`, `~/.claude/plans/`, `~/.claude/session-env/`, `~/.claude/shell-snapshots/`, `~/.claude/backups/` | Nothing user-facing |
1691| `~/.claude/todos/`, `~/.claude/statsig/`, `~/.claude/logs/`, `~/.claude/image-cache/` | Nothing. Legacy directories not written by current versions. |
1674| Delete | You lose |
1675| - | - |
1676| `~/.claude/projects/` | Resume, continue, and rewind for past sessions, and auto memory for every project |
1677| `~/.claude/history.jsonl` | Up-arrow prompt recall, `Ctrl+R` history search, and `!` shell-command completion |
1678| `~/.claude/paste-cache/` | Pasted text in recalled prompts; see [paste large content](/docs/en/terminal-config#paste-large-content) |
1679| `~/.claude/uploads/` | Attachments that past [Remote Control](/docs/en/remote-control) sessions refer to by path |
1680| `~/.claude/file-history/` | Checkpoint restore for past sessions |
1681| `~/.claude/stats-cache.json` | Historical totals shown by `/usage` |
1682| `~/.claude/usage-data/` | Past [`/insights`](/docs/en/costs#analyze-your-usage-patterns) reports and the cached analysis data used to build them |
1683| `~/.claude/feedback-bundles/` | Feedback and bug-report archives you haven't yet sent to your Anthropic account team |
1684| `~/.claude/feedback/drafts/` | [Claude-drafted feedback](/docs/en/tools-reference#sendfeedback-tool-behavior) you haven't sent |
1685| `~/.claude/remote-settings.json` | Nothing. Re-fetched on next launch. |
1686| `~/.claude/cache/changelog.md` | Nothing. Refreshed in the background. |
1687| `~/.claude/policy-limits.json` | Nothing. Refreshed automatically. |
1688| `~/.claude/tasks/` | Task lists that a resumed session would pick up |
1689| `~/.claude/skills/.trash/`, `~/.claude/plugins/.trash/` | The chance to recover [synced skills](/docs/en/skills#how-synced-skills-behave) and [synced plugins](/docs/en/plugins/loading#synced-plugins) that Claude Code removed |
1690| `~/.claude/debug/`, `~/.claude/plans/`, `~/.claude/session-env/`, `~/.claude/shell-snapshots/`, `~/.claude/backups/` | Nothing user-facing |
1691| `~/.claude/todos/`, `~/.claude/statsig/`, `~/.claude/logs/`, `~/.claude/image-cache/` | Nothing. Legacy directories not written by current versions. |
16921692 
16931693Don't delete `~/.claude.json`, `~/.claude/settings.json`, or `~/.claude/plugins/`: those hold your auth, preferences, and installed plugins.
16941694 
Feedback