SpyBara
Go Premium

Documentation 2026-10-08 22:58 UTC to 2026-10-09 21:01 UTC

57 files changed +852 −240. View all changes and history on the product overview
2026
Fri 9 22:01 Thu 8 22:58 Wed 7 23:59 Tue 6 23:59 Mon 5 23:58 Sun 4 23:58 Sat 3 23:57 Fri 2 22:59 Thu 1 23:59
Details

196| Option | What it controls | Default |196| Option | What it controls | Default |

197| :- | :- | :- |197| :- | :- | :- |

198| Max turns (`max_turns` / `maxTurns`) | Maximum tool-use round trips | No limit |198| Max turns (`max_turns` / `maxTurns`) | Maximum tool-use round trips | No limit |

199| Max budget (`max_budget_usd` / `maxBudgetUsd`) | Maximum cost before stopping | No limit |199| Max budget (`max_budget_usd` / `maxBudgetUsd`) | Estimated spend at which the loop stops | No limit |

200 200 

201When either limit is hit, the SDK returns a `ResultMessage` with a corresponding error subtype (`error_max_turns` or `error_max_budget_usd`). See [Handle the result](#handle-the-result) for how to check these subtypes and [`ClaudeAgentOptions`](/docs/en/agent-sdk/python#claudeagentoptions) / [`Options`](/docs/en/agent-sdk/typescript#options) for syntax.201When either limit is hit, the SDK returns a `ResultMessage` with a corresponding error subtype (`error_max_turns` or `error_max_budget_usd`). See [Handle the result](#handle-the-result) for how to check these subtypes and [`ClaudeAgentOptions`](/docs/en/agent-sdk/python#claudeagentoptions) / [`Options`](/docs/en/agent-sdk/typescript#options) for syntax.

202 202 


204 204 

205With [streaming input](/docs/en/agent-sdk/streaming-vs-single-mode), a message that is still queued when a turn ends at the max-turns limit stays queued. Claude Code doesn't add it to that turn's last model call. It starts a new turn for the message, and the max-turns count starts over for that turn. The budget total keeps accumulating across messages, and once spend reaches `maxBudgetUsd`, later messages in the same conversation end with the `error_max_budget_usd` result. A [`/clear`](/docs/en/agent-sdk/cost-tracking) starts the budget over.205With [streaming input](/docs/en/agent-sdk/streaming-vs-single-mode), a message that is still queued when a turn ends at the max-turns limit stays queued. Claude Code doesn't add it to that turn's last model call. It starts a new turn for the message, and the max-turns count starts over for that turn. The budget total keeps accumulating across messages, and once spend reaches `maxBudgetUsd`, later messages in the same conversation end with the `error_max_budget_usd` result. A [`/clear`](/docs/en/agent-sdk/cost-tracking) starts the budget over.

206 206 

207#### Budget headroom

208 

209Claude Code compares spend with the `max_budget_usd` / `maxBudgetUsd` cap after model responses arrive, because each response's cost comes from the token usage the API returns with it. The response that reaches the cap still completes and counts toward [`total_cost_usd`](/docs/en/agent-sdk/cost-tracking#get-the-total-cost-of-a-query). Spend can therefore pass the cap by up to the cost of that one response, plus anything that subagents still running at that moment spend before they stop. Leave headroom for this when you set the cap.

210 

207### Effort level211### Effort level

208 212 

209The `effort` option controls how much reasoning Claude applies. Lower effort levels use fewer tokens per turn and reduce cost. Not all models support the effort parameter. See [Effort](https://platform.claude.com/docs/en/build-with-claude/effort) for which models support it.213The `effort` option controls how much reasoning Claude applies. Lower effort levels use fewer tokens per turn and reduce cost. Not all models support the effort parameter. See [Effort](https://platform.claude.com/docs/en/build-with-claude/effort) for which models support it.

Details

74 74 

75You can configure MCP servers in code when calling `query()`, or in a `.mcp.json` file loaded via [`settingSources`](#from-a-config-file).75You can configure MCP servers in code when calling `query()`, or in a `.mcp.json` file loaded via [`settingSources`](#from-a-config-file).

76 76 

77### In code77<span id="in-code" />

78 

79### Add a server in code

78 80 

79Pass MCP servers directly in the `mcpServers` option. This example starts a local filesystem MCP server for `/Users/me/projects`. Replace that path with a directory on your machine:81Pass MCP servers directly in the `mcpServers` option. This example starts a local filesystem MCP server for `/Users/me/projects`. Replace that path with a directory on your machine:

80 82 


129 ```131 ```

130</CodeGroup>132</CodeGroup>

131 133 

132### From a config file134<span id="from-a-config-file" />

135 

136### Add a server from a config file

133 137 

134Create a `.mcp.json` file at your project root. The file is picked up when the `project` setting source is enabled, which it is for default `query()` options. If you set `settingSources` explicitly, include `"project"` for this file to load. Replace `/Users/me/projects` with a directory on your machine:138Create a `.mcp.json` file at your project root. The file is picked up when the `project` setting source is enabled, which it is for default `query()` options. If you set `settingSources` explicitly, include `"project"` for this file to load. Replace `/Users/me/projects` with a directory on your machine:

135 139 


279 283 

280### stdio servers284### stdio servers

281 285 

282Local processes that communicate via stdin/stdout. Use this for MCP servers you run on the same machine. For the `.mcp.json` form, use the same fields shown at [From a config file](#from-a-config-file). In code, pass the command and its arguments. Replace `/Users/me/projects` with a directory on your machine:286Local processes that communicate via stdin/stdout. Use this for MCP servers you run on the same machine. For the `.mcp.json` form, use the same fields shown at [Add a server from a config file](#from-a-config-file). In code, pass the command and its arguments. Replace `/Users/me/projects` with a directory on your machine:

283 287 

284<CodeGroup>288<CodeGroup>

285 ```typescript TypeScript hidelines={1,-1} theme={null}289 ```typescript TypeScript hidelines={1,-1} theme={null}

Details

22 22 

23## Migration Steps23## Migration Steps

24 24 

25### For TypeScript/JavaScript Projects25<span id="for-typescript/javascript-projects" />

26 

27### Migrate a TypeScript or JavaScript project

26 28 

27**1. Uninstall the old package:**29**1. Uninstall the old package:**

28 30 


56 58 

57Make any code changes needed to complete the migration.59Make any code changes needed to complete the migration.

58 60 

59### For Python Projects61<span id="for-python-projects" />

62 

63### Migrate a Python project

60 64 

61**1. Uninstall the old package:**65**1. Uninstall the old package:**

62 66 

Details

138| `auto` | Model-classified approvals | A model classifier reviews actions such as shell commands and network requests, allowing or blocking each one it reviews. See [Auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) for availability and the decision order |138| `auto` | Model-classified approvals | A model classifier reviews actions such as shell commands and network requests, allowing or blocking each one it reviews. See [Auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) for availability and the decision order |

139 139 

140<Warning>140<Warning>

141 **Subagent inheritance:** A subagent runs in the parent session's permission mode unless you set `permissionMode` on its [`AgentDefinition`](/docs/en/agent-sdk/typescript#agentdefinition) and the parent session is in `default`, `dontAsk`, or `plan` mode. Even then, Claude Code never applies a `"bypassPermissions"` value. A subagent runs in `bypassPermissions` mode only when the parent session itself does. The `bypassPermissions` exception requires Claude Code v2.1.267 or later.141 **Subagent inheritance:** A subagent runs in the parent session's permission mode unless you set `permissionMode` on its [`AgentDefinition`](/docs/en/agent-sdk/typescript#agentdefinition) and the parent session is in `default`, `dontAsk`, or `plan` mode. Even then, Claude Code never applies a `"bypassPermissions"` value, and applies an `"auto"` value only when [auto mode is available](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) to that subagent. A subagent runs in `bypassPermissions` mode only when the parent session itself does. The `bypassPermissions` exception requires Claude Code v2.1.267 or later.

142 142 

143 Subagents may have different system prompts and less constrained behavior than your main agent, so inheriting `bypassPermissions` grants them full, autonomous system access. The [actions no mode auto-approves](/docs/en/permission-modes#actions-no-mode-auto-approves) still apply.143 Subagents may have different system prompts and less constrained behavior than your main agent, so inheriting `bypassPermissions` grants them full, autonomous system access. The [actions no mode auto-approves](/docs/en/permission-modes#actions-no-mode-auto-approves) still apply.

144</Warning>144</Warning>

Details

836| `resume` | `str \| None` | `None` | Session ID to resume |836| `resume` | `str \| None` | `None` | Session ID to resume |

837| `session_id` | `str \| None` | `None` | Use a specific session ID instead of an auto-generated one. Must be a valid UUID. Can't be combined with `continue_conversation` or `resume` unless `fork_session` is also set |837| `session_id` | `str \| None` | `None` | Use a specific session ID instead of an auto-generated one. Must be a valid UUID. Can't be combined with `continue_conversation` or `resume` unless `fork_session` is also set |

838| `max_turns` | `int \| None` | `None` | Maximum agentic turns (tool-use round trips) |838| `max_turns` | `int \| None` | `None` | Maximum agentic turns (tool-use round trips) |

839| `max_budget_usd` | `float \| None` | `None` | 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) |839| `max_budget_usd` | `float \| None` | `None` | Stop the query when the client-side cost estimate reaches this USD value. The estimate can pass this value, so [leave headroom](/docs/en/agent-sdk/agent-loop#budget-headroom). 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) |

840| `disallowed_tools` | `list[str]` | `[]` | 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) |840| `disallowed_tools` | `list[str]` | `[]` | 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) |

841| `enable_file_checkpointing` | `bool` | `False` | Enable file change tracking for rewinding. See [File checkpointing](/docs/en/agent-sdk/file-checkpointing) |841| `enable_file_checkpointing` | `bool` | `False` | Enable file change tracking for rewinding. See [File checkpointing](/docs/en/agent-sdk/file-checkpointing) |

842| `model` | `str \| None` | `None` | Claude model alias or full model name. See [accepted values and provider-specific IDs](/docs/en/model-config#available-models) |842| `model` | `str \| None` | `None` | Claude model alias or full model name. See [accepted values and provider-specific IDs](/docs/en/model-config#available-models) |


893```893```

894 894 

895* `API_TIMEOUT_MS`: per-request timeout on the Anthropic client, in milliseconds. Default `600000`. Applies to the main loop and all subagents.895* `API_TIMEOUT_MS`: per-request timeout on the Anthropic client, in milliseconds. Default `600000`. Applies to the main loop and all subagents.

896* `CLAUDE_CODE_MAX_RETRIES`: maximum API retries. Default `10`, capped at `15`. Each retry gets its own `API_TIMEOUT_MS` window, so worst-case wall time is roughly `API_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1)` plus backoff. For unattended runs that need to wait through longer outages, set [`CLAUDE_CODE_RETRY_WATCHDOG=1`](/docs/en/errors#tune-retry-behavior): it retries transient capacity errors indefinitely and, on Claude Code v2.1.199 or later, raises the default for other transient errors to `300` and removes the cap on this variable.896* `CLAUDE_CODE_MAX_RETRIES`: maximum API retries. Default `10`, capped at `15`. Each retry gets its own `API_TIMEOUT_MS` window.

897 

898 For unattended runs that need to wait through longer outages, set [`CLAUDE_CODE_RETRY_WATCHDOG=1`](/docs/en/errors#tune-retry-behavior): it retries transient capacity errors indefinitely and, on Claude Code v2.1.199 or later, raises the default for other transient errors to `300` and removes the cap on this variable.

897* `CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS`: stall watchdog for subagents. While the stream watchdog is on, the default is `CLAUDE_STREAM_IDLE_TIMEOUT_MS` plus 5 minutes, which comes to `600000` unless you raise that variable. With the stream watchdog off, the default is `600000`. Before v2.1.257, the default was always `600000`.899* `CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS`: stall watchdog for subagents. While the stream watchdog is on, the default is `CLAUDE_STREAM_IDLE_TIMEOUT_MS` plus 5 minutes, which comes to `600000` unless you raise that variable. With the stream watchdog off, the default is `600000`. Before v2.1.257, the default was always `600000`.

898 900 

899 The timer resets on each stream event. On a stall, Claude Code aborts the subagent and reports the stall to the parent. For a background subagent, it also marks the task failed and attaches any partial result.901 The timer resets on each stream event. On a stall, Claude Code aborts the subagent and reports the stall to the parent. For a background subagent, it also marks the task failed and attaches any partial result.


3045{3047{

3046 "url": str, # The URL to fetch content from3048 "url": str, # The URL to fetch content from

3047 "prompt": str, # The prompt to run on the fetched content3049 "prompt": str, # The prompt to run on the fetched content

3050 "offset": int | None, # Number of characters to skip from the start of the page. Requires Python Agent SDK 0.2.164 or later

3048}3051}

3049```3052```

3050 3053 

Details

299 299 

300## Detect subagent invocation300## Detect subagent invocation

301 301 

302Claude invokes subagents through the Agent tool. To detect when a subagent is invoked, check for `tool_use` blocks where `name` is `"Agent"`. Messages from within a subagent's context include a `parent_tool_use_id` field.302Claude invokes subagents through the Agent tool. To detect when a subagent is invoked, check for `tool_use` blocks where `name` is `"Agent"`.

303 

304Messages from within a subagent's context include a `parent_tool_use_id` field. In TypeScript, each assistant and user message a subagent produces also carries [`agent_id`](/docs/en/agent-sdk/typescript#sdkassistantmessage): the `task_id` of that subagent's [task events](/docs/en/agent-sdk/typescript#sdktaskstartedmessage). `agent_id` requires TypeScript Agent SDK v0.3.292 or later.

303 305 

304<Note>306<Note>

305 The tool appears as `"Agent"` in `tool_use` blocks but as `"Task"` in the `system:init` tools list. Before Claude Code v2.1.63, `tool_use` blocks also named it `"Task"`. To keep detection working across SDK versions, match both values in `block.name`.307 The tool appears as `"Agent"` in `tool_use` blocks but as `"Task"` in the `system:init` tools list. Before Claude Code v2.1.63, `tool_use` blocks also named it `"Task"`. To keep detection working across SDK versions, match both values in `block.name`.


307 309 

308The message structure differs between SDKs. In Python, you access content blocks directly via `message.content`. In TypeScript, `SDKAssistantMessage` wraps the Claude API message, so you access content via `message.message.content`.310The message structure differs between SDKs. In Python, you access content blocks directly via `message.content`. In TypeScript, `SDKAssistantMessage` wraps the Claude API message, so you access content via `message.message.content`.

309 311 

310This example iterates through streamed messages, logging when a subagent is invoked and when subsequent messages originate from within that subagent's execution context.312This example iterates through streamed messages, logging when a subagent is invoked and when subsequent messages originate from within that subagent's execution context. The TypeScript version also logs the `agent_id` of each subagent message that carries one.

311 313 

312<CodeGroup>314<CodeGroup>

313 ```python Python theme={null}315 ```python Python theme={null}


379 // Check if this message is from within a subagent's context381 // Check if this message is from within a subagent's context

380 if (msg.parent_tool_use_id) {382 if (msg.parent_tool_use_id) {

381 console.log(" (running inside subagent)");383 console.log(" (running inside subagent)");

384 // On assistant and user messages, agent_id matches the task_id

385 // on that subagent's task_started and other task events

386 if (msg.agent_id) {

387 console.log(` agent_id: ${msg.agent_id}`);

388 }

382 }389 }

383 390 

384 if ("result" in message) {391 if ("result" in message) {

Details

493| `includePartialMessages` | `boolean` | `false` | Include partial message events |493| `includePartialMessages` | `boolean` | `false` | Include partial message events |

494| `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 |494| `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 |

495| `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 |495| `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 |

496| `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) |496| `maxBudgetUsd` | `number` | `undefined` | Stop the query when the client-side cost estimate reaches this USD value. The estimate can pass this value, so [leave headroom](/docs/en/agent-sdk/agent-loop#budget-headroom). 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) |

497| `maxThinkingTokens` | `number` | `undefined` | *Deprecated:* Use `thinking` instead. Maximum tokens for thinking process |497| `maxThinkingTokens` | `number` | `undefined` | *Deprecated:* Use `thinking` instead. Maximum tokens for thinking process |

498| `maxTurns` | `number` | `undefined` | Maximum agentic turns (tool-use round trips) |498| `maxTurns` | `number` | `undefined` | Maximum agentic turns (tool-use round trips) |

499| `mcpServers` | `Record<string, [`McpServerConfig`](#mcpserverconfig)>` | `{}` | MCP server configurations |499| `mcpServers` | `Record<string, [`McpServerConfig`](#mcpserverconfig)>` | `{}` | MCP server configurations |


553```553```

554 554 

555* `API_TIMEOUT_MS`: per-request timeout on the Anthropic client, in milliseconds. Default `600000`. Applies to the main loop and all subagents.555* `API_TIMEOUT_MS`: per-request timeout on the Anthropic client, in milliseconds. Default `600000`. Applies to the main loop and all subagents.

556* `CLAUDE_CODE_MAX_RETRIES`: maximum API retries. Default `10`, capped at `15`. Each retry gets its own `API_TIMEOUT_MS` window, so worst-case wall time is roughly `API_TIMEOUT_MS × (CLAUDE_CODE_MAX_RETRIES + 1)` plus backoff. For unattended runs that need to wait through longer outages, set [`CLAUDE_CODE_RETRY_WATCHDOG=1`](/docs/en/errors#tune-retry-behavior): it retries transient capacity errors indefinitely and, on Claude Code v2.1.199 or later, raises the default for other transient errors to `300` and removes the cap on this variable.556* `CLAUDE_CODE_MAX_RETRIES`: maximum API retries. Default `10`, capped at `15`. Each retry gets its own `API_TIMEOUT_MS` window.

557 

558 For unattended runs that need to wait through longer outages, set [`CLAUDE_CODE_RETRY_WATCHDOG=1`](/docs/en/errors#tune-retry-behavior): it retries transient capacity errors indefinitely and, on Claude Code v2.1.199 or later, raises the default for other transient errors to `300` and removes the cap on this variable.

557* `CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS`: stall watchdog for subagents. While the stream watchdog is on, the default is `CLAUDE_STREAM_IDLE_TIMEOUT_MS` plus 5 minutes, which comes to `600000` unless you raise that variable. With the stream watchdog off, the default is `600000`. Before v2.1.257, the default was always `600000`.559* `CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS`: stall watchdog for subagents. While the stream watchdog is on, the default is `CLAUDE_STREAM_IDLE_TIMEOUT_MS` plus 5 minutes, which comes to `600000` unless you raise that variable. With the stream watchdog off, the default is `600000`. Before v2.1.257, the default was always `600000`.

558 560 

559 The timer resets on each stream event. On a stall, Claude Code aborts the subagent and reports the stall to the parent. For a background subagent, it also marks the task failed and attaches any partial result.561 The timer resets on each stream event. On a stall, Claude Code aborts the subagent and reports the stall to the parent. For a background subagent, it also marks the task failed and attaches any partial result.


1409 parent_tool_use_id: string | null;1411 parent_tool_use_id: string | null;

1410 error?: SDKAssistantMessageError;1412 error?: SDKAssistantMessageError;

1411 aborted?: true;1413 aborted?: true;

1414 agent_id?: string;

1412 timestamp?: string;1415 timestamp?: string;

1413 context_usage?: SDKContextUsage;1416 context_usage?: SDKContextUsage;

1414 user_message_uuid?: string;1417 user_message_uuid?: string;


1428 1431 

1429`aborted` is `true` when an interrupt or abort truncated the assistant message before the stream completed: the message has no `stop_reason` and the content may end mid-word. The field is absent on normally completed messages. It requires Agent SDK v0.3.214 or later.1432`aborted` is `true` when an interrupt or abort truncated the assistant message before the stream completed: the message has no `stop_reason` and the content may end mid-word. The field is absent on normally completed messages. It requires Agent SDK v0.3.214 or later.

1430 1433 

1434`agent_id` identifies the subagent that produced the message and is absent on main-thread messages. The value equals the `task_id` on that subagent's [`task_started`](#sdktaskstartedmessage) and other task events, and is unchanged when the subagent is [resumed](/docs/en/agent-sdk/subagents#resume-subagents). The field requires Agent SDK v0.3.292 or later.

1435 

1436Match a subagent's messages to its task events on `agent_id` rather than pairing a message's `parent_tool_use_id` with a task event's `tool_use_id`. When a tool call resumes the subagent, the task events carry that call's `tool_use_id`, while the messages keep the `parent_tool_use_id` of the tool call that first started the subagent, so the two no longer match.

1437 

1431Claude Code sets `user_message_uuid` and `user_message_uuids` on the turn's first assistant message, under the conditions in [`user_message_uuid`](#user_message_uuid). When Claude Code re-runs a turn that a restart interrupted, the re-run's assistant messages that carry those fields also carry [`resume_reason`](#resume_reason).1438Claude Code sets `user_message_uuid` and `user_message_uuids` on the turn's first assistant message, under the conditions in [`user_message_uuid`](#user_message_uuid). When Claude Code re-runs a turn that a restart interrupted, the re-run's assistant messages that carry those fields also carry [`resume_reason`](#resume_reason).

1432 1439 

1433`timestamp` is the ISO 8601 time when the message's content finished generating on the process that produced it. The value comes from that machine's clock, so use it for display only and don't order messages by it. One API turn can produce several assistant messages that share a `message.id`, each with its own `timestamp`. When the field is absent, fall back to the time you received the message.1440`timestamp` is the ISO 8601 time when the message's content finished generating on the process that produced it. The value comes from that machine's clock, so use it for display only and don't order messages by it. One API turn can produce several assistant messages that share a `message.id`, each with its own `timestamp`. When the field is absent, fall back to the time you received the message.


1443 type: "user";1450 type: "user";

1444 uuid?: UUID;1451 uuid?: UUID;

1445 session_id?: string;1452 session_id?: string;

1453 agent_id?: string;

1446 message: MessageParam; // From Anthropic SDK1454 message: MessageParam; // From Anthropic SDK

1447 pasted_content?: MessageParam["content"][];1455 pasted_content?: MessageParam["content"][];

1448 parent_tool_use_id: string | null;1456 parent_tool_use_id: string | null;


1482};1490};

1483```1491```

1484 1492 

1493A user message that a subagent produces, such as the `tool_result` for one of its own tool calls, carries `agent_id`. See [`SDKAssistantMessage`](#sdkassistantmessage), which defines the field and its version requirement.

1494 

1485On a message that carries a `tool_result` block, `tool_use_result` is the tool's structured output object rather than the text sent to the model. Its shape depends on the tool named by the matching `tool_use` block, so the field is typed `unknown`; the built-in shapes are listed under [Tool Output Types](#tool-output-types). These results need handling beyond their listed shape:1495On a message that carries a `tool_result` block, `tool_use_result` is the tool's structured output object rather than the text sent to the model. Its shape depends on the tool named by the matching `tool_use` block, so the field is typed `unknown`; the built-in shapes are listed under [Tool Output Types](#tool-output-types). These results need handling beyond their listed shape:

1486 1496 

1487* The `Agent` tool: `tool_use_result` is [`AgentOutput`](#agent-2). Render from it rather than parsing the `tool_result` text. A `completed` result's `content` holds the subagent's report, or, for a subagent whose report goes through a `SubagentHandback` tool call, a short note about that hand-back in place of the report. In [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) on Claude Code v2.1.271 or later, every subagent that produces a `completed` result reports that way unless it is a [fork](/docs/en/sub-agents#fork-the-current-conversation), and Claude receives the report as a separate message from the subagent.1497* The `Agent` tool: `tool_use_result` is [`AgentOutput`](#agent-2). Render from it rather than parsing the `tool_result` text. A `completed` result's `content` holds the subagent's report, or, for a subagent whose report goes through a `SubagentHandback` tool call, a short note about that hand-back in place of the report. In [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) on Claude Code v2.1.271 or later, every subagent that produces a `completed` result reports that way unless it is a [fork](/docs/en/sub-agents#fork-the-current-conversation), and Claude receives the report as a separate message from the subagent.


1820 1830 

1821### `SDKPartialAssistantMessage`1831### `SDKPartialAssistantMessage`

1822 1832 

1823Streaming partial message (only when `includePartialMessages` is true). The `parent_tool_use_id` field is always `null`: stream events are emitted for the main session only. For subagent attribution, use complete messages, which carry `parent_tool_use_id`, or enable [`forwardSubagentText`](#options) to receive subagent text and thinking as complete messages.1833Streaming partial message (only when `includePartialMessages` is true).

1834 

1835The `parent_tool_use_id` field is always `null`: stream events are emitted for the main session only. For subagent attribution, use complete messages, which carry [`agent_id`](#sdkassistantmessage) and `parent_tool_use_id`, or enable [`forwardSubagentText`](#options) to receive subagent text and thinking as complete messages.

1824 1836 

1825```typescript theme={null}1837```typescript theme={null}

1826type SDKPartialAssistantMessage = {1838type SDKPartialAssistantMessage = {


3108type WebFetchInput = {3120type WebFetchInput = {

3109 url: string;3121 url: string;

3110 prompt: string;3122 prompt: string;

3123 offset?: number;

3111};3124};

3112```3125```

3113 3126 

3114Fetches content from a URL and processes it with an AI model.3127Fetches content from a URL and processes it with an AI model.

3115 3128 

3129`offset` is the number of characters to skip from the start of the page. Claude sets it to keep reading a long page. The field requires Agent SDK v0.3.290 or later.

3130 

3116### WebSearch3131### WebSearch

3117 3132 

3118**Tool name:** `WebSearch`3133**Tool name:** `WebSearch`


5263 task_type?: string;5278 task_type?: string;

5264 is_backgrounded?: boolean;5279 is_backgrounded?: boolean;

5265 spawn_depth?: number;5280 spawn_depth?: number;

5281 parent_task_id?: string;

5266 ambient?: boolean;5282 ambient?: boolean;

5267 uuid: UUID;5283 uuid: UUID;

5268 session_id: string;5284 session_id: string;


5280 5296 

5281A [resumed subagent](/docs/en/agent-sdk/subagents#resume-subagents) always reports `is_backgrounded: true`, because Claude Code runs every resumed subagent in the background. When a foreground task moves to the background later, Claude Code reports the new `is_backgrounded` value in a [`task_updated`](#sdktaskupdatedmessage) message rather than sending a second `task_started`.5297A [resumed subagent](/docs/en/agent-sdk/subagents#resume-subagents) always reports `is_backgrounded: true`, because Claude Code runs every resumed subagent in the background. When a foreground task moves to the background later, Claude Code reports the new `is_backgrounded` value in a [`task_updated`](#sdktaskupdatedmessage) message rather than sending a second `task_started`.

5282 5298 

5299`parent_task_id` holds the `task_id` of the subagent that launched this task. Use it to group each task under the subagent that started it. Claude Code sets it on subagent, Bash, and [Monitor](#monitor) tasks. The field requires Agent SDK v0.3.292 or later. It is absent when:

5300 

5301* The main thread launched the task

5302* Claude Code no longer tracks the parent task

5303* A [teammate](/docs/en/agent-teams) or an agent inside a workflow launched the task

5304 

5305The parent can be a foreground task or one that already ended, so treat an ID you don't recognize as no parent.

5306 

5283### `SDKTaskProgressMessage`5307### `SDKTaskProgressMessage`

5284 5308 

5285Emitted periodically while a subagent or background task is running.5309Emitted periodically while a subagent or background task is running.


5330 5354 

5331### `SDKBackgroundTasksChangedMessage`5355### `SDKBackgroundTasksChangedMessage`

5332 5356 

5333Emitted whenever the set of live background tasks changes: a task starts, completes, is killed, a foreground agent is backgrounded, or a task's `description` or `ambient` field changes.5357Emitted whenever the set of live background tasks changes: a task starts, completes, or is killed; a foreground agent is backgrounded; or a task's `description`, `ambient`, or `parent_task_id` field changes. For the `parent_task_id` field on each entry, see [`SDKTaskStartedMessage`](#sdktaskstartedmessage), which defines it and its version requirement.

5334 5358 

5335The `tasks` array is the full live set. Replace any cached set with each payload instead of pairing `task_started` and `task_notification` events, so the next membership change corrects any event you missed.5359The `tasks` array is the full live set. Replace any cached set with each payload instead of pairing `task_started` and `task_notification` events, so the next membership change corrects any event you missed.

5336 5360 

5337Ordering relative to those per-task events is unspecified, so don't correlate the two streams.5361When a task ends, its [`task_updated`](#sdktaskupdatedmessage) and [`task_notification`](#sdktasknotificationmessage) arrive before the `background_tasks_changed` that drops it from the list. Ordering relative to the per-task events is otherwise unspecified.

5338 5362 

5339Nothing is emitted at startup. Reset to an empty set whenever the session's CLI process starts or restarts and let the next membership change repopulate it.5363Nothing is emitted at startup. Reset to an empty set whenever the session's CLI process starts or restarts and let the next membership change repopulate it.

5340 5364 


5351 task_type: string;5375 task_type: string;

5352 subagent_type?: string;5376 subagent_type?: string;

5353 description: string;5377 description: string;

5378 parent_task_id?: string;

5354 ambient?: boolean;5379 ambient?: boolean;

5355 }[];5380 }[];

5356 uuid: UUID;5381 uuid: UUID;

Details

34 ```34 ```

35 35 

36 ```typescript TypeScript theme={null}36 ```typescript TypeScript theme={null}

37 async function handleToolRequest(toolName, input, options) {37 import type { CanUseTool } from "@anthropic-ai/claude-agent-sdk";

38 

39 const handleToolRequest: CanUseTool = async (toolName, input, options) => {

38 // options includes { signal: AbortSignal, suggestions?: PermissionUpdate[] }40 // options includes { signal: AbortSignal, suggestions?: PermissionUpdate[] }

39 // Prompt user and return allow or deny41 // Prompt the user here, then return allow or deny

40 }42 return { behavior: "deny", message: "User declined" };

43 };

41 44 

42 const options = { canUseTool: handleToolRequest };45 const options = { canUseTool: handleToolRequest };

43 ```46 ```


432 // Include AskUserQuestion in your tools list435 // Include AskUserQuestion in your tools list

433 tools: ["Read", "Glob", "Grep", "AskUserQuestion"],436 tools: ["Read", "Glob", "Grep", "AskUserQuestion"],

434 canUseTool: async (toolName, input) => {437 canUseTool: async (toolName, input) => {

435 // Handle clarifying questions here438 // Placeholder that approves every call. The Detect AskUserQuestion step replaces it.

439 return { behavior: "allow", updatedInput: input };

436 }440 }

437 }441 }

438 })) {442 })) {


745 749 

746 ```typescript TypeScript theme={null}750 ```typescript TypeScript theme={null}

747 import { query } from "@anthropic-ai/claude-agent-sdk";751 import { query } from "@anthropic-ai/claude-agent-sdk";

752 import type { PermissionResult } from "@anthropic-ai/claude-agent-sdk";

748 import * as readline from "readline/promises";753 import * as readline from "readline/promises";

749 754 

750 // Helper to prompt user for input in the terminal755 // Helper to prompt user for input in the terminal


765 }770 }

766 771 

767 // Display Claude's questions and collect user answers772 // Display Claude's questions and collect user answers

768 async function handleAskUserQuestion(input: any) {773 async function handleAskUserQuestion(input: any): Promise<PermissionResult> {

769 const answers: Record<string, string> = {};774 const answers: Record<string, string> = {};

770 775 

771 for (const q of input.questions) {776 for (const q of input.questions) {

agent-view.md +18 −9

Details

365 365 

366You can dispatch new background sessions from agent view, send or copy an existing interactive session to the background, or start one directly from the shell.366You can dispatch new background sessions from agent view, send or copy an existing interactive session to the background, or start one directly from the shell.

367 367 

368### From agent view368<span id="from-agent-view" />

369 

370### Dispatch an agent from agent view

369 371 

370Type a prompt in the input at the bottom of agent view and press `Enter` to start a new background session. The session is named automatically from the prompt; rename it later with `Ctrl+R`.372Type a prompt in the input at the bottom of agent view and press `Enter` to start a new background session. The session is named automatically from the prompt; rename it later with `Ctrl+R`.

371 373 


416 418 

417When agent view is grouped by directory, dispatching sends the prompt to the selected row's directory, so you can select a group and dispatch into it without retyping the path.419When agent view is grouped by directory, dispatching sends the prompt to the selected row's directory, so you can select a group and dispatch into it without retyping the path.

418 420 

419### From inside a session421<span id="from-inside-a-session" />

422 

423### Send or copy a session to the background

420 424 

421Two commands move work from the session you're in to the background: `/background` sends the current conversation there and frees your terminal, and `/fork` sends a copy while you keep working where you are.425Two commands move work from the session you're in to the background: `/background` sends the current conversation there and frees your terminal, and `/fork` sends a copy while you keep working where you are.

422 426 


473 477 

474Directories you added during the session with [`/add-dir`](/docs/en/permissions#additional-directories-grant-file-access-not-configuration) also carry through. Carrying `--allow-dangerously-skip-permissions` keeps `bypassPermissions` reachable in the backgrounded session, but it doesn't grant anything new: the mode still requires the one-time interactive acceptance described in [Permission mode, model, and effort](#permission-mode-model-and-effort).478Directories you added during the session with [`/add-dir`](/docs/en/permissions#additional-directories-grant-file-access-not-configuration) also carry through. Carrying `--allow-dangerously-skip-permissions` keeps `bypassPermissions` reachable in the backgrounded session, but it doesn't grant anything new: the mode still requires the one-time interactive acceptance described in [Permission mode, model, and effort](#permission-mode-model-and-effort).

475 479 

476### From your shell480<span id="from-your-shell" />

481 

482### Dispatch an agent from your shell

477 483 

478Pass `--bg` or its long form `--background` to start a session that goes straight to the background:484Pass `--bg` or its long form `--background` to start a session that goes straight to the background:

479 485 


559 565 

560Outside a git repository, sessions write to the working directory directly and aren't isolated from each other, so avoid dispatching parallel sessions that edit the same files. If you use a different version control system, configure a [`WorktreeCreate` hook](/docs/en/worktrees#non-git-version-control) and Claude isolates edits the same way it does for git.566Outside a git repository, sessions write to the working directory directly and aren't isolated from each other, so avoid dispatching parallel sessions that edit the same files. If you use a different version control system, configure a [`WorktreeCreate` hook](/docs/en/worktrees#non-git-version-control) and Claude isolates edits the same way it does for git.

561 567 

562When the hook fails in a directory that isn't a git repository, Claude skips isolation for that directory and edits the working directory in place. Inside a git repository, a session that Claude moves into a worktree before editing can't edit files in the shared checkout until that move happens.568When the hook fails in a directory that isn't a git repository, Claude skips isolation for that directory and edits the working directory in place. Inside a git repository, a session that Claude moves into a worktree before editing can't use the `Edit`, `Write`, or `NotebookEdit` tools on the shared checkout until that move happens.

563 569 

564To find a session's worktree path, attach and check its working directory.570To find a session's worktree path, attach and check its working directory.

565 571 


761| `claude daemon logs` | Follow the supervisor's log file, [`~/.claude/daemon.log`](#where-state-is-stored), printing new lines as they arrive until you press `Ctrl+C` |767| `claude daemon logs` | Follow the supervisor's log file, [`~/.claude/daemon.log`](#where-state-is-stored), printing new lines as they arrive until you press `Ctrl+C` |

762| `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 |768| `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 |

763 769 

764`claude attach` and `claude logs` can take part of a running session's name in place of the ID, as in `claude logs "auth refactor"`. Passing a name requires Claude Code v2.1.290 or later.770`claude attach` and `claude logs` can take part of a session's name in place of the ID, as in `claude logs "auth refactor"`. Passing a name requires Claude Code v2.1.290 or later.

765 771 

766### List sessions as JSON772### List sessions as JSON

767 773 


889 895 

890### Opening a session says it has no saved transcript896### Opening a session says it has no saved transcript

891 897 

892A stopped session that was [backgrounded from another conversation](#from-inside-a-session) and stopped before its first response finished has nothing to resume: until that first response finishes, the conversation still lives only in the session it was backgrounded from. `claude attach` refuses to open it with `This session has no saved transcript`.898When you open a session that you [backgrounded from another conversation](#from-inside-a-session) and that stopped before it ran a turn of its own, Claude Code resumes that conversation. If Claude Code can't find the conversation, it refuses to open the session:

899 

900* `claude attach` prints `This session has no saved transcript`.

901* Agent view shows `Press enter again to restart this session fresh` below the list.

893 902 

894In agent view, opening that row shows `Press enter again to restart this session fresh` below the list. Press `Enter` on the same row again to restart the session with an empty conversation, or run `claude respawn <id>` from the shell.903Press `Enter` on the same row again to restart the session with an empty conversation, or run `claude respawn <id>` from the shell.

895 904 

896The original conversation is intact; resume it with `claude --resume` or keep working in it. See the [error reference](/docs/en/errors#this-session-has-no-saved-transcript) for details.905See the [error reference](/docs/en/errors#this-session-has-no-saved-transcript) for details.

897 906 

898### The terminal host died or the session stopped responding907### The terminal host died or the session stopped responding

899 908 


983 992 

984| Version | Change |993| Version | Change |

985| - | - |994| - | - |

986| v2.1.290 | [`claude attach` and `claude logs`](#manage-sessions-from-the-shell) can take part of a running session's name in place of the ID. |995| v2.1.290 | [`claude attach` and `claude logs`](#manage-sessions-from-the-shell) can take part of a session's name in place of the ID. |

987| v2.1.290 | `/model`, `/effort`, `/rename`, and `/usage` sent as a [peek reply](#peek-and-reply) to a working session run right away. |996| v2.1.290 | `/model`, `/effort`, `/rename`, and `/usage` sent as a [peek reply](#peek-and-reply) to a working session run right away. |

988| v2.1.290 | A [peek reply](#peek-and-reply) that can't be delivered is no longer saved for the next restart when it starts with `/`, or when it answers a question with predefined choices while the session's process is running. |997| v2.1.290 | A [peek reply](#peek-and-reply) that can't be delivered is no longer saved for the next restart when it starts with `/`, or when it answers a question with predefined choices while the session's process is running. |

989| v2.1.288 | `Ctrl+F` finds sessions by name, and `Alt+↑` / `Alt+↓` jump between group headers. Both, and `Ctrl+R`, can be [rebound](/docs/en/keybindings#agents-actions). |998| v2.1.288 | `Ctrl+F` finds sessions by name, and `Alt+↑` / `Alt+↓` jump between group headers. Both, and `Ctrl+R`, can be [rebound](/docs/en/keybindings#agents-actions). |

chrome.md +35 −2

Details

176and attach logs/session.log to it176and attach logs/session.log to it

177```177```

178 178 

179Three restrictions apply to uploads:179If Claude refuses to attach a file or an upload fails, check for these causes:

180 180 

181* **Permissions**: Claude can upload a file only when the session is allowed to read it, so [permission rules](/docs/en/settings-reference#permission-settings) that deny `Read` access to a file also block uploading it.181* **Permissions**: Claude can upload a file only when the session is allowed to read it, so [permission rules](/docs/en/settings-reference#permission-settings) that deny `Read` access to a file also block uploading it.

182* **Size**: a single upload can include up to 10 MB of files in total.182* **Size**: a single upload can include up to 10 MB of files in total.

183* **Hard links**: Claude refuses files that have multiple hard links, which is common inside package-manager stores like `node_modules`. Copy the file and upload the copy.183* **Hard links**: Claude refuses files that have multiple hard links, which is common inside package-manager stores like `node_modules`. Copy the file and upload the copy.

184* **Credential names**: Claude refuses a file whose name or folder is one that credentials are kept under, such as `.env`, a `.pem` or `.key` file, or anything under `.ssh`. Requires Claude Code v2.1.293 or later.

184 185 

185### Draft content in Google Docs186### Draft content in Google Docs

186 187 


269 270 

270Other Chromium-based browsers read the same file from their own configuration directory, named after the browser. For example, Brave on macOS uses `~/Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts/`, and on Windows each browser has its own registry key, such as `HKCU\Software\BraveSoftware\Brave-Browser\NativeMessagingHosts\`.271Other Chromium-based browsers read the same file from their own configuration directory, named after the browser. For example, Brave on macOS uses `~/Library/Application Support/BraveSoftware/Brave-Browser/NativeMessagingHosts/`, and on Windows each browser has its own registry key, such as `HKCU\Software\BraveSoftware\Brave-Browser\NativeMessagingHosts\`.

271 272 

273### Project settings can't turn on Chrome

274 

275This warning in your terminal means the project you're working in tried to turn on Chrome integration, and Claude Code didn't allow it:

276 

277```text wrap theme={null}

278Claude Code ignored CLAUDE_CODE_ENABLE_CFC in this project's settings: a project can't turn on Claude in Chrome. To turn it on yourself, run /chrome or start with --chrome.

279```

280 

281The project's `.claude/settings.json` or `.claude/settings.local.json` sets [`CLAUDE_CODE_ENABLE_CFC`](/docs/en/env-vars#variables) to `1` in its `env` block to turn Chrome integration on. Claude Code didn't apply that setting, so Chrome integration is off in this session and Claude has no browser tools.

282 

283Claude Code skips the setting because those files are stored in the project directory, and a repository you check out must not be able to connect Claude to your browser.

284 

285You can keep working as you are. If you want browser tools, or want the warning gone, do one of these:

286 

287* **To get browser tools now**: exit and start again with `claude --chrome` in your shell.

288* **To get browser tools in later sessions**: run `/chrome` at the Claude Code prompt and select [**Enabled by default**](#enable-chrome-by-default). This applies to sessions you start afterward, not the one that's running.

289* **To stop the warning without browser tools**: remove the `CLAUDE_CODE_ENABLE_CFC` line from the project's settings file.

290 

272### Browser not responding291### Browser not responding

273 292 

274If Claude's browser commands stop working:293If Claude's browser commands stop working:


281 300 

282The Chrome extension's service worker can go idle during extended sessions, which breaks the connection. If browser tools stop working after a period of inactivity, run `/chrome` and select "Reconnect extension".301The Chrome extension's service worker can go idle during extended sessions, which breaks the connection. If browser tools stop working after a period of inactivity, run `/chrome` and select "Reconnect extension".

283 302 

303When you run `/chrome`, check its `Status` line. If it reads "Not connected", the running session's own connection to Chrome has failed. Select "Reconnect extension" to restart that connection. After the connection succeeds, the extension's reconnect page opens in Chrome. Before v2.1.290, "Reconnect extension" only opened that page and didn't restart a failed connection, so if browser tools don't return on an earlier version, update Claude Code.

304 

305### Extension signed in to a different organization

306 

307If you belong to more than one claude.ai organization, the extension must be signed in to the same organization as Claude Code. If the two differ, Claude's browser tools return "Browser extension is not connected", even when both use the same claude.ai account.

308 

309To see which organization Claude Code is signed in to, run [`/status`](/docs/en/commands) at the Claude Code prompt and read the `Organization` row.

310 

311<Warning>

312 If you log out of the extension, you lose the shortcuts and scheduled tasks saved in it. Try the other fixes under [Common error messages](#common-error-messages) first.

313</Warning>

314 

315To change the extension's organization, log out in the extension's settings, then log in and select the organization that `/status` shows.

316 

284### Windows-specific issues317### Windows-specific issues

285 318 

286On Windows, you may encounter:319On Windows, you may encounter:


295 328 

296| Error | Cause | Fix |329| Error | Cause | Fix |

297| - | - | - |330| - | - | - |

298| "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` | Check that the extension is signed in to the same claude.ai account as Claude Code, 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) |331| "Browser extension is not connected" | The extension isn't installed and running in Chrome, the extension is signed in to a different claude.ai account or organization than Claude Code, or your organization's IP allowlist rejects the connection to `bridge.claudeusercontent.com` | Check that the extension is signed in to the same claude.ai account and [organization](#extension-signed-in-to-a-different-organization) as Claude Code, 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) |

299| Extension shows "Not detected" in `/chrome` | Chrome extension is not installed or is disabled | Install or enable the extension in `chrome://extensions` |332| Extension shows "Not detected" in `/chrome` | Chrome extension is not installed or is disabled | Install or enable the extension in `chrome://extensions` |

300| "No tab available" | Claude tried to act before a tab was ready | Ask Claude to create a new tab and retry |333| "No tab available" | Claude tried to act before a tab was ready | Ask Claude to create a new tab and retry |

301| "Receiving end does not exist" | Extension service worker went idle | Run `/chrome` and select "Reconnect extension" |334| "Receiving end does not exist" | Extension service worker went idle | Run `/chrome` and select "Reconnect extension" |

Details

1139 1139 

1140The CLI sends metrics, logs, and, when enabled, traces to the gateway, which relays them verbatim to each configured destination. The exports use OpenTelemetry Protocol (OTLP) over HTTP. To skip the relay and have sessions export straight to your collector, [name the collector in a policy](#export-directly-to-your-collector). See [Monitoring usage](/docs/en/monitoring-usage) for the metrics and events the CLI emits.1140The CLI sends metrics, logs, and, when enabled, traces to the gateway, which relays them verbatim to each configured destination. The exports use OpenTelemetry Protocol (OTLP) over HTTP. To skip the relay and have sessions export straight to your collector, [name the collector in a policy](#export-directly-to-your-collector). See [Monitoring usage](/docs/en/monitoring-usage) for the metrics and events the CLI emits.

1141 1141 

1142In sessions signed in through `/login`, the CLI stamps each export with the authenticated user's identity, read from the gateway-issued JWT: the `user.id`, `user.email`, and `user.groups` attributes. Per-developer cost and usage attribution therefore works with no developer-side configuration.1142In sessions signed in through `/login`, the CLI stamps each export with the authenticated user's identity, read from the gateway-issued JWT: the `user.id`, `user.email`, and `user.groups` attributes. Per-developer cost and usage attribution therefore works with no developer-side configuration. Events that Claude Code logs before the developer signs in [don't carry this identity](/docs/en/monitoring-usage#standard-attributes).

1143 1143 

1144[Claude Desktop](#claude-desktop-overlay) and Cowork sessions signed in through the gateway stamp their telemetry with `user.email` and `user.groups` alongside `enduser.id`, so you can cover terminal, Desktop, and Cowork usage with one query on `user.email` or `user.groups`. `user.groups` is the comma-separated IdP group list.1144[Claude Desktop](#claude-desktop-overlay) and Cowork sessions signed in through the gateway stamp their telemetry with `user.email` and `user.groups` alongside `enduser.id`, so you can cover terminal, Desktop, and Cowork usage with one query on `user.email` or `user.groups`. `user.groups` is the comma-separated IdP group list.

1145 1145 

Details

502 502 

503## Telemetry503## Telemetry

504 504 

505The gateway gives you per-developer usage metrics without any per-machine OTEL configuration. Claude Code emits OpenTelemetry (OTLP) metrics, logs, and opt-in traces; [Monitoring usage](/docs/en/monitoring-usage) covers everything the CLI reports. In sessions signed in through `/login`, the CLI stamps each export with the authenticated IdP identity attributes `user.id`, `user.email`, and `user.groups`, so usage rolls up per developer.505The gateway gives you per-developer usage metrics without any per-machine OTEL configuration. Claude Code emits OpenTelemetry (OTLP) metrics, logs, and opt-in traces; [Monitoring usage](/docs/en/monitoring-usage) covers everything the CLI reports. In sessions signed in through `/login`, the CLI [stamps each export](/docs/en/monitoring-usage#standard-attributes) with the authenticated IdP identity attributes `user.id`, `user.email`, and `user.groups`, so usage rolls up per developer.

506 506 

507The gateway itself is an authenticated OTLP relay. Set [`telemetry.forward_to`](/docs/en/claude-apps-gateway-config#telemetry) together with `listen.public_url`, and it pushes the OTEL exporter settings to every connected client and forwards their OTLP traffic verbatim to each destination you list. Each destination opts into metrics, logs, and traces independently, and the default is metrics only; see the [`telemetry` reference](/docs/en/claude-apps-gateway-config#telemetry) for the per-signal fields and their sensitivity tradeoffs. The gateway doesn't buffer, aggregate, or store telemetry, so where the data lands is entirely the collector's exporter configuration.507The gateway itself is an authenticated OTLP relay. Set [`telemetry.forward_to`](/docs/en/claude-apps-gateway-config#telemetry) together with `listen.public_url`, and it pushes the OTEL exporter settings to every connected client and forwards their OTLP traffic verbatim to each destination you list. Each destination opts into metrics, logs, and traces independently, and the default is metrics only; see the [`telemetry` reference](/docs/en/claude-apps-gateway-config#telemetry) for the per-signal fields and their sensitivity tradeoffs. The gateway doesn't buffer, aggregate, or store telemetry, so where the data lands is entirely the collector's exporter configuration.

508 508 

Details

83 From the CLI, session handoff is one-way: you can pull cloud sessions into your terminal with `--teleport`, but you can't push an existing terminal session to the cloud. The `--cloud` flag with a task description creates a new cloud session for your current repository; with `-p` and a session ID or claude.ai/code URL it instead [queues a message into that existing session](/docs/en/claude-code-on-the-web#send-follow-ups-from-the-cli). The [Desktop app](/docs/en/desktop#continue-in-another-surface) can send a local session in its Code tab to the cloud from its **Open in** menu.83 From the CLI, session handoff is one-way: you can pull cloud sessions into your terminal with `--teleport`, but you can't push an existing terminal session to the cloud. The `--cloud` flag with a task description creates a new cloud session for your current repository; with `-p` and a session ID or claude.ai/code URL it instead [queues a message into that existing session](/docs/en/claude-code-on-the-web#send-follow-ups-from-the-cli). The [Desktop app](/docs/en/desktop#continue-in-another-surface) can send a local session in its Code tab to the cloud from its **Open in** menu.

84</Note>84</Note>

85 85 

86### From terminal to cloud86<span id="from-terminal-to-cloud" />

87 

88### Start a cloud session from your terminal

87 89 

88Start a cloud session from the command line with the `--cloud` flag:90Start a cloud session from the command line with the `--cloud` flag:

89 91 


197 199 

198If the send fails, see [Errors when sending to a cloud session](#errors-when-sending-to-a-cloud-session).200If the send fails, see [Errors when sending to a cloud session](#errors-when-sending-to-a-cloud-session).

199 201 

200### From cloud to terminal202<span id="from-cloud-to-terminal" />

203 

204### Continue a cloud session in your terminal

201 205 

202Pull a cloud session into your terminal using any of these:206Pull a cloud session into your terminal using any of these:

203 207 


421Reopen the session from [claude.ai/code](https://claude.ai/code) to provision a fresh VM:425Reopen the session from [claude.ai/code](https://claude.ai/code) to provision a fresh VM:

422 426 

423* **Restored**: your conversation history427* **Restored**: your conversation history

424* **Not restored**: background work that was still running when the VM was reclaimed, such as subagents and shell commands428* **Not restored**: background work that was still running when the VM was reclaimed, such as subagents and shell commands, and the pending wakeup of a [self-paced `/loop`](/docs/en/scheduled-tasks#let-claude-choose-the-interval). To restart the loop, run `/loop` again.

425 429 

426## Limitations430## Limitations

427 431 

Details

427* **Routines**: when you ask for scheduled work in a project, Claude creates a [routine](/docs/en/routines) that runs as threads in that project and appears on its **Routines** tab. Routines you create outside a project keep working on their own.427* **Routines**: when you ask for scheduled work in a project, Claude creates a [routine](/docs/en/routines) that runs as threads in that project and appears on its **Routines** tab. Routines you create outside a project keep working on their own.

428* **Remote Control**: [Remote Control](/docs/en/remote-control) connects claude.ai to a Claude Code session running on your machine. When you ask Claude in a project to run a thread on your computer, the project [uses Remote Control to do it](#run-a-thread-on-your-own-computer).428* **Remote Control**: [Remote Control](/docs/en/remote-control) connects claude.ai to a Claude Code session running on your machine. When you ask Claude in a project to run a thread on your computer, the project [uses Remote Control to do it](#run-a-thread-on-your-own-computer).

429* **Local sessions and agent view**: a session you start yourself in your terminal, IDE, or the desktop app's local environment can't be added to a project. [Agent view](/docs/en/agent-view) is a screen for tracking several local sessions side by side, and you still start each one and give it its task yourself.429* **Local sessions and agent view**: a session you start yourself in your terminal, IDE, or the desktop app's local environment can't be added to a project. [Agent view](/docs/en/agent-view) is a screen for tracking several local sessions side by side, and you still start each one and give it its task yourself.

430* **Worktrees**: a [worktree](/docs/en/worktrees) gives each local session its own working copy of a repository so parallel sessions on your machine don't overwrite each other. Cloud threads don't need them: each clones its repositories into its own cloud sandbox and works on its own branch.430* **Worktrees**: a [worktree](/docs/en/worktrees) gives each local session its own working copy of a repository. Cloud threads don't need them: each clones its repositories into its own cloud sandbox and works on its own branch.

431* **Agent teams**: an [agent team](/docs/en/agent-teams) is one session that starts teammate sessions for a single task, on your machine or inside a cloud session, and ends with that task.431* **Agent teams**: an [agent team](/docs/en/agent-teams) is one session that starts teammate sessions for a single task, on your machine or inside a cloud session, and ends with that task.

432* **Subagents**: a [subagent](/docs/en/sub-agents) runs inside one session, does a side task in its own context window, and returns a summary to that session. A project's threads are whole sessions that Claude starts and that report back to the project conversation, and a thread can still use subagents for its own side tasks.432* **Subagents**: a [subagent](/docs/en/sub-agents) runs inside one session, does a side task in its own context window, and returns a summary to that session. A project's threads are whole sessions that Claude starts and that report back to the project conversation, and a thread can still use subagents for its own side tasks.

433* **Projects in claude.ai chat and Cowork**: the [earlier Projects experience](https://support.claude.com/en/articles/9517075-what-are-projects), which groups conversations and reference files without threads or a coordinator. Those projects keep working as they do today until the redesigned experience reaches them.433* **Projects in claude.ai chat and Cowork**: the [earlier Projects experience](https://support.claude.com/en/articles/9517075-what-are-projects), which groups conversations and reference files without threads or a coordinator. Those projects keep working as they do today until the redesigned experience reaches them.

Details

26| `claude auth logout` | Log out from your Anthropic account | `claude auth logout` |26| `claude auth logout` | Log out from your Anthropic account | `claude auth logout` |

27| `claude auth status` | Show authentication status as JSON. Use `--text` for human-readable output. Exits with code 0 if logged in, 1 if not. The JSON includes a `configDirectory` field naming the [configuration directory](/docs/en/claude-directory) the CLI uses. The field requires Claude Code v2.1.268 or later. The JSON's `authMethod` field is one of `none`, `claude.ai`, `oauth_token`, `api_key`, `api_key_helper`, or `third_party` | `claude auth status` |27| `claude auth status` | Show authentication status as JSON. Use `--text` for human-readable output. Exits with code 0 if logged in, 1 if not. The JSON includes a `configDirectory` field naming the [configuration directory](/docs/en/claude-directory) the CLI uses. The field requires Claude Code v2.1.268 or later. The JSON's `authMethod` field is one of `none`, `claude.ai`, `oauth_token`, `api_key`, `api_key_helper`, or `third_party` | `claude auth status` |

28| `claude agents` | Open [agent view](/docs/en/agent-view) to monitor and dispatch parallel background sessions. Use `--cwd <path>` to show only sessions started under that directory, or `--json` to print active sessions as a JSON array for scripting (`--json --all` also includes completed background sessions). Pass `--permission-mode`, `--model`, `--effort`, or `--agent` to set [defaults for dispatched sessions](/docs/en/agent-view#permission-mode-model-and-effort). Accepts `--settings`, `--add-dir`, `--plugin-dir`, and `--mcp-config` like the top-level `claude` command. Opening agent view requires an interactive terminal | `claude agents --json` |28| `claude agents` | Open [agent view](/docs/en/agent-view) to monitor and dispatch parallel background sessions. Use `--cwd <path>` to show only sessions started under that directory, or `--json` to print active sessions as a JSON array for scripting (`--json --all` also includes completed background sessions). Pass `--permission-mode`, `--model`, `--effort`, or `--agent` to set [defaults for dispatched sessions](/docs/en/agent-view#permission-mode-model-and-effort). Accepts `--settings`, `--add-dir`, `--plugin-dir`, and `--mcp-config` like the top-level `claude` command. Opening agent view requires an interactive terminal | `claude agents --json` |

29| `claude attach <id\|name>` | Attach to a [background session](/docs/en/agent-view#manage-sessions-from-the-shell) in this terminal. Passing part of a running session's name in place of the ID requires Claude Code v2.1.290 or later | `claude attach 7c5dcf5d` |29| `claude attach <id\|name>` | Attach to a [background session](/docs/en/agent-view#manage-sessions-from-the-shell) in this terminal. Passing part of a session's name in place of the ID requires Claude Code v2.1.290 or later | `claude attach 7c5dcf5d` |

30| `claude auto-mode defaults` | Print the built-in [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) classifier rules as JSON. Use `claude auto-mode config` to see your effective config with settings applied. `--label <prefix>` prints only the rules whose label starts with that prefix, matched case-insensitively. Requires Claude Code v2.1.208 or later | `claude auto-mode defaults --label 'Git Destructive'` |30| `claude auto-mode defaults` | Print the built-in [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) classifier rules as JSON. Use `claude auto-mode config` to see your effective config with settings applied. `--label <prefix>` prints only the rules whose label starts with that prefix, matched case-insensitively. Requires Claude Code v2.1.208 or later | `claude auto-mode defaults --label 'Git Destructive'` |

31| `claude auto-mode reset` | Restore the default [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) configuration by removing the `autoMode` section from your user settings file. Prompts for confirmation before writing; pass `-y`/`--yes` to skip the prompt. Rules from [managed settings](/docs/en/server-managed-settings) or the `--settings` flag still apply. Requires Claude Code v2.1.212 or later. See [Inspect the defaults and your effective config](/docs/en/auto-mode-config#inspect-the-defaults-and-your-effective-config) | `claude auto-mode reset --yes` |31| `claude auto-mode reset` | Restore the default [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) configuration by removing the `autoMode` section from your user settings file. Prompts for confirmation before writing; pass `-y`/`--yes` to skip the prompt. Rules from [managed settings](/docs/en/server-managed-settings) or the `--settings` flag still apply. Requires Claude Code v2.1.212 or later. See [Inspect the defaults and your effective config](/docs/en/auto-mode-config#inspect-the-defaults-and-your-effective-config) | `claude auto-mode reset --yes` |

32| `claude daemon logs` | Follow the background-session [supervisor's](/docs/en/agent-view#the-supervisor-process) log file, `~/.claude/daemon.log`, printing new lines as they arrive until you press `Ctrl+C` | `claude daemon logs` |32| `claude daemon logs` | Follow the background-session [supervisor's](/docs/en/agent-view#the-supervisor-process) log file, `~/.claude/daemon.log`, printing new lines as they arrive until you press `Ctrl+C` | `claude daemon logs` |


35| `claude daemon stop --any` | Stop the background-session [supervisor](/docs/en/agent-view#the-supervisor-process) and the sessions it hosts. Pass `--keep-workers` to leave background sessions running so the next supervisor reconnects to them. `--any` confirms stopping an on-demand supervisor, which is the default. Use this to recover from an [unresponsive supervisor](/docs/en/agent-view#agent-view-says-the-background-service-did-not-respond) | `claude daemon stop --any --keep-workers` |35| `claude daemon stop --any` | Stop the background-session [supervisor](/docs/en/agent-view#the-supervisor-process) and the sessions it hosts. Pass `--keep-workers` to leave background sessions running so the next supervisor reconnects to them. `--any` confirms stopping an on-demand supervisor, which is the default. Use this to recover from an [unresponsive supervisor](/docs/en/agent-view#agent-view-says-the-background-service-did-not-respond) | `claude daemon stop --any --keep-workers` |

36| `claude doctor` | Print read-only installation and settings diagnostics from the terminal without starting a session, including install health, settings-file validation errors, and Remote Control eligibility. For the in-session setup checkup that can also apply fixes, run [`/doctor`](/docs/en/commands#all-commands) | `claude doctor` |36| `claude doctor` | Print read-only installation and settings diagnostics from the terminal without starting a session, including install health, settings-file validation errors, and Remote Control eligibility. For the in-session setup checkup that can also apply fixes, run [`/doctor`](/docs/en/commands#all-commands) | `claude doctor` |

37| `claude import [source]` | Start an interactive session that runs [`/import`](/docs/en/commands#all-commands) to bring configuration from other coding agents into Claude Code. Accepts the same `--dry-run` and `--yes` options as the command. Not available on Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, or Claude Platform on AWS. Also unavailable when you turn off [feature-flag fetching](/docs/en/env-vars#features-that-need-feature-flag-fetching). Requires Claude Code v2.1.213 or later | `claude import codex --dry-run` |37| `claude import [source]` | Start an interactive session that runs [`/import`](/docs/en/commands#all-commands) to bring configuration from other coding agents into Claude Code. Accepts the same `--dry-run` and `--yes` options as the command. Not available on Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, or Claude Platform on AWS. Also unavailable when you turn off [feature-flag fetching](/docs/en/env-vars#features-that-need-feature-flag-fetching). Requires Claude Code v2.1.213 or later | `claude import codex --dry-run` |

38| `claude logs <id\|name>` | Print recent output from a [background session](/docs/en/agent-view#manage-sessions-from-the-shell). Passing part of a running session's name in place of the ID requires Claude Code v2.1.290 or later | `claude logs 7c5dcf5d` |38| `claude logs <id\|name>` | Print recent output from a [background session](/docs/en/agent-view#manage-sessions-from-the-shell). Passing part of a session's name in place of the ID requires Claude Code v2.1.290 or later | `claude logs 7c5dcf5d` |

39| `claude mcp` | Configure Model Context Protocol (MCP) servers | See the [Claude Code MCP documentation](/docs/en/mcp). |39| `claude mcp` | Configure Model Context Protocol (MCP) servers | See the [Claude Code MCP documentation](/docs/en/mcp). |

40| `claude mcp login <name>` | Run a configured MCP server's OAuth flow without opening the interactive `/mcp` panel. Works for HTTP, SSE, and claude.ai connector servers. Add `--no-browser` over SSH to print the authorization URL instead of opening a browser, then paste the redirect URL back at the prompt. See [Authenticate from the command line](/docs/en/mcp#authenticate-from-the-command-line) | `claude mcp login sentry` |40| `claude mcp login <name>` | Run a configured MCP server's OAuth flow without opening the interactive `/mcp` panel. Works for HTTP, SSE, and claude.ai connector servers. Add `--no-browser` over SSH to print the authorization URL instead of opening a browser, then paste the redirect URL back at the prompt. See [Authenticate from the command line](/docs/en/mcp#authenticate-from-the-command-line) | `claude mcp login sentry` |

41| `claude mcp logout <name>` | Clear stored OAuth credentials for an MCP server | `claude mcp logout sentry` |41| `claude mcp logout <name>` | Clear stored OAuth credentials for an MCP server | `claude mcp logout sentry` |


102| `--input-format` | Specify input format for print mode (options: `text`, `stream-json`) | `claude -p --output-format json --input-format stream-json` |102| `--input-format` | Specify input format for print mode (options: `text`, `stream-json`) | `claude -p --output-format json --input-format stream-json` |

103| `--json-schema` | Get validated JSON output matching a JSON Schema after the agent completes its workflow (print mode only). See [structured outputs](/docs/en/agent-sdk/structured-outputs). Claude Code exits with an error on an invalid schema and accepts the `format` keyword as an annotation without client-side validation | `claude -p --json-schema '{"type":"object","properties":{...}}' "query"` |103| `--json-schema` | Get validated JSON output matching a JSON Schema after the agent completes its workflow (print mode only). See [structured outputs](/docs/en/agent-sdk/structured-outputs). Claude Code exits with an error on an invalid schema and accepts the `format` keyword as an annotation without client-side validation | `claude -p --json-schema '{"type":"object","properties":{...}}' "query"` |

104| `--maintenance` | Run [Setup hooks](/docs/en/hooks#setup) with the `maintenance` matcher before the session (print mode only) | `claude -p --maintenance "query"` |104| `--maintenance` | Run [Setup hooks](/docs/en/hooks#setup) with the `maintenance` matcher before the session (print mode only) | `claude -p --maintenance "query"` |

105| `--max-budget-usd` | Maximum dollar amount to spend on API calls before stopping (print mode only). Claude Code checks the cap against its [client-side cost estimate](/docs/en/agent-sdk/cost-tracking#estimates-not-billing), which can differ from your bill. Spend from [subagents](/docs/en/sub-agents) counts toward the cap. When you return to a conversation with `--continue` or `--resume`, totals [restored from earlier runs](/docs/en/agent-sdk/cost-tracking#accumulate-costs-across-multiple-calls) don't count toward it. Once spend reaches the cap, spawning another subagent fails with `Budget limit reached`, and Claude Code stops background subagents that are still running; the cap-enforcement behaviors require Claude Code v2.1.217 or later | `claude -p --max-budget-usd 5.00 "query"` |105| `--max-budget-usd` | Stop the run once estimated spend on API calls reaches this amount (print mode only). Claude Code checks the cap against its [client-side cost estimate](/docs/en/agent-sdk/cost-tracking#estimates-not-billing), which can differ from your bill. Spend from [subagents](/docs/en/sub-agents) counts toward the cap. Spend can pass the cap, so [leave headroom](/docs/en/agent-sdk/agent-loop#budget-headroom). When you return to a conversation with `--continue` or `--resume`, totals [restored from earlier runs](/docs/en/agent-sdk/cost-tracking#accumulate-costs-across-multiple-calls) don't count toward it. Once spend reaches the cap, spawning another subagent fails with `Budget limit reached`, and Claude Code stops background subagents that are still running; the cap-enforcement behaviors require Claude Code v2.1.217 or later | `claude -p --max-budget-usd 5.00 "query"` |

106| `--max-turns` | Limit the number of agentic turns (print mode only). Exits with an error when the limit is reached. No limit by default. With `--input-format stream-json`, a message still queued when the limit ends a turn stays queued and starts a new turn with its own limit | `claude -p --max-turns 3 "query"` |106| `--max-turns` | Limit the number of agentic turns (print mode only). Exits with an error when the limit is reached. No limit by default. With `--input-format stream-json`, a message still queued when the limit ends a turn stays queued and starts a new turn with its own limit | `claude -p --max-turns 3 "query"` |

107| `--mcp-config` | Load MCP servers from JSON files or strings (space-separated). When you pass this flag with `-p`, Claude Code waits for still-pending servers to connect before running the first turn, up to the [`MCP_TIMEOUT`](/docs/en/env-vars) startup timeout, 30 seconds by default; a server with a [cached tool list](/docs/en/mcp#managing-your-servers) skips the wait and connects on first use. The wait requires Claude Code v2.1.221 or later | `claude --mcp-config ./mcp.json` |107| `--mcp-config` | Load MCP servers from JSON files or strings (space-separated). When you pass this flag with `-p`, Claude Code waits for still-pending servers to connect before running the first turn, up to the [`MCP_TIMEOUT`](/docs/en/env-vars) startup timeout, 30 seconds by default; a server with a [cached tool list](/docs/en/mcp#managing-your-servers) skips the wait and connects on first use. The wait requires Claude Code v2.1.221 or later | `claude --mcp-config ./mcp.json` |

108| `--model` | Sets the model for the current session with a [model alias](/docs/en/model-config#model-aliases) such as `sonnet`, `opus`, `haiku`, or `fable`, or a model's full name. Overrides the [`model`](/docs/en/settings-reference#model) setting and [`ANTHROPIC_MODEL`](/docs/en/model-config#environment-variables) | `claude --model claude-sonnet-5` |108| `--model` | Sets the model for the current session with a [model alias](/docs/en/model-config#model-aliases) such as `sonnet`, `opus`, `haiku`, or `fable`, or a model's full name. Overrides the [`model`](/docs/en/settings-reference#model) setting and [`ANTHROPIC_MODEL`](/docs/en/model-config#environment-variables) | `claude --model claude-sonnet-5` |

Details

277| | Available in cloud sessions | Why |277| | Available in cloud sessions | Why |

278| :- | :- | :- |278| :- | :- | :- |

279| Your repo's `CLAUDE.md` | Yes | Part of the clone |279| Your repo's `CLAUDE.md` | Yes | Part of the clone |

280| Your repo's `.claude/settings.json` hooks and permission rules | Yes, in a session with one repository | Part of the clone. A session with several repositories, including a [project](/docs/en/claude-projects#what-threads-pick-up-from-your-repositories) thread, starts above the clones and doesn't read them |280| Your repo's `.claude/settings.json` hooks and permission rules | Yes, in a session with one repository | Part of the clone. For a session with several repositories, see [which settings it reads](/docs/en/settings#settings-in-cloud-sessions) |

281| Your repo's `.mcp.json` MCP servers | Yes, in a session with one repository | Part of the clone, found from the session's working directory |281| Your repo's `.mcp.json` MCP servers | Yes, in a session with one repository | Part of the clone, found from the session's working directory. For a self-hosted environment, see [which repository's settings apply](/docs/en/self-hosted-environments-configuration#repository-settings-in-sessions-with-several-repositories) |

282| Your repo's `.claude/rules/` | Yes | Part of the clone |282| Your repo's `.claude/rules/` | Yes | Part of the clone |

283| Your repo's `.claude/skills/`, `.claude/agents/`, `.claude/commands/` | Yes | Part of the clone |283| Your repo's `.claude/skills/`, `.claude/agents/`, `.claude/commands/` | Yes | Part of the clone |

284| Plugins and marketplaces declared in your repo's `.claude/settings.json` | No | A cloud session doesn't install the plugins a repository turns on under [`enabledPlugins`](/docs/en/settings-reference#enabledplugins), including ones from the marketplaces it lists under [`extraKnownMarketplaces`](/docs/en/settings-reference#extraknownmarketplaces) |284| Plugins and marketplaces declared in your repo's `.claude/settings.json` | No | A cloud session doesn't install the plugins a repository turns on under [`enabledPlugins`](/docs/en/settings-reference#enabledplugins), including ones from the marketplaces it lists under [`extraKnownMarketplaces`](/docs/en/settings-reference#extraknownmarketplaces) |


513 513 

514SessionStart hooks behave the same in the cloud as locally, with these caveats:514SessionStart hooks behave the same in the cloud as locally, with these caveats:

515 515 

516* **One repository per session**: a session with several repositories doesn't load hooks from any repository's `.claude/settings.json`, so a SessionStart hook you define there doesn't run. Install dependencies for those sessions with a [setup script](#setup-scripts) instead.516* **One repository per session**: in an Anthropic-hosted environment, a session with several repositories doesn't load hooks from any repository's `.claude/settings.json`, so a SessionStart hook you define there doesn't run. Install dependencies for those sessions with a [setup script](#setup-scripts) instead. For a self-hosted environment, see [which repository's settings apply](/docs/en/self-hosted-environments-configuration#repository-settings-in-sessions-with-several-repositories).

517* **No cloud-only scoping**: hooks run in both local and cloud sessions. To skip local execution, exit early unless the `CLAUDE_CODE_REMOTE` environment variable is `true`, the way the [dependency install script](#install-dependencies-with-a-sessionstart-hook) does.517* **No cloud-only scoping**: hooks run in both local and cloud sessions. To skip local execution, exit early unless the `CLAUDE_CODE_REMOTE` environment variable is `true`, the way the [dependency install script](#install-dependencies-with-a-sessionstart-hook) does.

518* **Requires network access**: install commands need to reach package registries. If your environment uses **None** network access, these hooks fail. The [default allowlist](#default-allowed-domains) under **Trusted** covers npm, PyPI, RubyGems, and crates.io.518* **Requires network access**: install commands need to reach package registries. If your environment uses **None** network access, these hooks fail. The [default allowlist](#default-allowed-domains) under **Trusted** covers npm, PyPI, RubyGems, and crates.io.

519* **Proxy compatibility**: in Anthropic-hosted environments, all outbound traffic passes through a [security proxy](#security-proxy), and some package managers don't work correctly with it; Bun is a known example. In a [self-hosted environment](/docs/en/self-hosted-environments-deploy#default-deny-egress), outbound traffic goes through your own network boundary instead.519* **Proxy compatibility**: in Anthropic-hosted environments, all outbound traffic passes through a [security proxy](#security-proxy), and some package managers don't work correctly with it; Bun is a known example. In a [self-hosted environment](/docs/en/self-hosted-environments-deploy#default-deny-egress), outbound traffic goes through your own network boundary instead.

desktop.md +1 −1

Details

342 342 

343### Work in parallel with sessions343### Work in parallel with sessions

344 344 

345Click **+ New session** in the sidebar, or press **Cmd+N** on macOS or **Ctrl+N** on Windows, to work on multiple tasks in parallel. Press **Ctrl+Tab** and **Ctrl+Shift+Tab** to cycle through sessions in the sidebar. For Git repositories, select the **worktree** option next to the branch name to give the session its own isolated copy of your project using [Git worktrees](/docs/en/worktrees), so changes in one session don't affect other sessions until you commit them.345Click **+ New session** in the sidebar, or press **Cmd+N** on macOS or **Ctrl+N** on Windows, to work on multiple tasks in parallel. Press **Ctrl+Tab** and **Ctrl+Shift+Tab** to cycle through sessions in the sidebar. For Git repositories, select the **worktree** option next to the branch name to give the session its own isolated copy of your project using [Git worktrees](/docs/en/worktrees).

346 346 

347To view two sessions at once, hold **Cmd** on macOS or **Ctrl** on Windows and click a session in the sidebar. The session opens in a second pane alongside the one you already have open. While the split is active, clicking another sidebar session replaces whichever pane has focus. Press **Cmd+\\** on macOS or **Ctrl+\\** on Windows to close the focused pane and return to a single session.347To view two sessions at once, hold **Cmd** on macOS or **Ctrl** on Windows and click a session in the sidebar. The session opens in a second pane alongside the one you already have open. While the split is active, clicking another sidebar session replaces whichever pane has focus. Press **Cmd+\\** on macOS or **Ctrl+\\** on Windows to close the focused pane and return to a single session.

348 348 

env-vars.md +10 −5

Details

19 19 

20A variable you set in your shell lasts for that terminal session, while a variable in a settings file applies every time `claude` runs.20A variable you set in your shell lasts for that terminal session, while a variable in a settings file applies every time `claude` runs.

21 21 

22### In your shell22<span id="in-your-shell" />

23 

24### Set variables in your shell

23 25 

24Set the variable before launching `claude`:26Set the variable before launching `claude`:

25 27 


74 </Tab>76 </Tab>

75</Tabs>77</Tabs>

76 78 

77### In settings files79<span id="in-settings-files" />

80 

81### Set variables in settings files

78 82 

79Add variables under the `env` key in a `settings.json` file, creating the file if it doesn't exist. Claude Code reads them directly from the file, so they take effect no matter how `claude` was launched. A running session applies new and changed values to its environment when you save the file, but a feature that reads its variables once at startup, such as [OpenTelemetry monitoring](/docs/en/monitoring-usage), keeps its startup values until you relaunch. Removing a variable from the file doesn't unset it in a running session; the removal takes effect the next time you launch `claude`.83Add variables under the `env` key in a `settings.json` file, creating the file if it doesn't exist. Claude Code reads them directly from the file, so they take effect no matter how `claude` was launched. A running session applies new and changed values to its environment when you save the file, but a feature that reads its variables once at startup, such as [OpenTelemetry monitoring](/docs/en/monitoring-usage), keeps its startup values until you relaunch. Removing a variable from the file doesn't unset it in a running session; the removal takes effect the next time you launch `claude`.

80 84 


112 116 

113How an environment variable interacts with CLI flags and in-session commands varies per feature: `--model` and `/model` override `ANTHROPIC_MODEL`, while `CLAUDE_CODE_EFFORT_LEVEL` overrides `--effort` and `/effort`. When a variable interacts with another configuration source, its row in the [Variables](#variables) list states the precedence or links to the page that documents it.117How an environment variable interacts with CLI flags and in-session commands varies per feature: `--model` and `/model` override `ANTHROPIC_MODEL`, while `CLAUDE_CODE_EFFORT_LEVEL` overrides `--effort` and `/effort`. When a variable interacts with another configuration source, its row in the [Variables](#variables) list states the precedence or links to the page that documents it.

114 118 

115Claude Code reads shell environment variables at startup, so changes to them take effect the next time you launch `claude`. Variables set under the `env` key in settings files are reapplied to a running session when the file changes, with the startup-only exception described in [In settings files](#in-settings-files).119Claude Code reads shell environment variables at startup, so changes to them take effect the next time you launch `claude`. Variables set under the `env` key in settings files are reapplied to a running session when the file changes, with the startup-only exception described in [Set variables in settings files](#in-settings-files).

116 120 

117## Variables121## Variables

118 122 


194| `CLAUDE_AFK_TIMEOUT_MS` | How many milliseconds of idle time before an unanswered [`AskUserQuestion`](/docs/en/tools-reference) dialog auto-continues without you. Auto-continue is off by default; opt in with the [`askUserQuestionTimeout`](/docs/en/settings-reference#askuserquestiontimeout) setting. This variable is an override for demos and automated tests: when set, it takes precedence over that setting and turns auto-continue on even when the setting is unset or `never`. Setting `0` doesn't turn the timeout off; it closes the dialog immediately. Ignored in [project and local settings](/docs/en/settings-reference#variables-claude-code-ignores-in-env). Before v2.1.200, auto-continue was on by default with a `60000` (60 seconds) timeout. Requires Claude Code v2.1.198 or later |198| `CLAUDE_AFK_TIMEOUT_MS` | How many milliseconds of idle time before an unanswered [`AskUserQuestion`](/docs/en/tools-reference) dialog auto-continues without you. Auto-continue is off by default; opt in with the [`askUserQuestionTimeout`](/docs/en/settings-reference#askuserquestiontimeout) setting. This variable is an override for demos and automated tests: when set, it takes precedence over that setting and turns auto-continue on even when the setting is unset or `never`. Setting `0` doesn't turn the timeout off; it closes the dialog immediately. Ignored in [project and local settings](/docs/en/settings-reference#variables-claude-code-ignores-in-env). Before v2.1.200, auto-continue was on by default with a `60000` (60 seconds) timeout. Requires Claude Code v2.1.198 or later |

195| `CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS` | Set to `1` to disable all built-in [subagent](/docs/en/sub-agents) types such as Explore and Plan. Only applies in non-interactive mode (the `-p` flag). Useful for SDK users who want a blank slate. This also removes `general-purpose`, the subagent Claude Code runs when an Agent tool call omits `subagent_type`. Such a call then fails with [`subagent_type is required`](/docs/en/errors#subagent-type-is-required) |199| `CLAUDE_AGENT_SDK_DISABLE_BUILTIN_AGENTS` | Set to `1` to disable all built-in [subagent](/docs/en/sub-agents) types such as Explore and Plan. Only applies in non-interactive mode (the `-p` flag). Useful for SDK users who want a blank slate. This also removes `general-purpose`, the subagent Claude Code runs when an Agent tool call omits `subagent_type`. Such a call then fails with [`subagent_type is required`](/docs/en/errors#subagent-type-is-required) |

196| `CLAUDE_AGENT_SDK_MCP_NO_PREFIX` | Set to `1` to skip the `mcp__<server>__` prefix on tool names from SDK-created MCP servers. Tools use their original names. SDK usage only |200| `CLAUDE_AGENT_SDK_MCP_NO_PREFIX` | Set to `1` to skip the `mcp__<server>__` prefix on tool names from SDK-created MCP servers. Tools use their original names. SDK usage only |

197| `CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS` | Stall timeout in milliseconds for subagents. Default `600000` (10 minutes); if you raise `CLAUDE_STREAM_IDLE_TIMEOUT_MS` while the stream watchdog is on, the default rises with it, as [Handle slow or stalled API responses](/docs/en/agent-sdk/typescript#handle-slow-or-stalled-api-responses) describes. The timer resets on each streaming progress event; if no progress arrives within the window, Claude Code aborts the subagent and reports the stall to the parent |201| `CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS` | Stall timeout in milliseconds for subagents. Also covers [workflow agents](/docs/en/workflows#when-an-agent-stalls-and-restarts) on Claude Code v2.1.286 or later. Default `600000` (10 minutes); if you raise `CLAUDE_STREAM_IDLE_TIMEOUT_MS` while the stream watchdog is on, the default rises with it, as [Handle slow or stalled API responses](/docs/en/agent-sdk/typescript#handle-slow-or-stalled-api-responses) describes |

198| `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` | Set the percentage (1-100) of the auto-compact window at which auto-compaction triggers. Use lower values like `50` to compact earlier; the variable can't raise the threshold, so values above the default percentage are ignored. It applies only in sessions that [compact before the model's context limit](/docs/en/model-config#context-window-and-auto-compaction). Applies to both main conversations and subagents |202| `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` | Set the percentage (1-100) of the auto-compact window at which auto-compaction triggers. Use lower values like `50` to compact earlier; the variable can't raise the threshold, so values above the default percentage are ignored. It applies only in sessions that [compact before the model's context limit](/docs/en/model-config#context-window-and-auto-compaction). Applies to both main conversations and subagents |

199| `CLAUDE_AUTO_BACKGROUND_TASKS` | Set to `1` to force-enable automatic backgrounding of long-running agent tasks. When enabled, subagents are moved to the background after running for approximately two minutes. Also enables [automatic backgrounding of long MCP tool calls](/docs/en/mcp#automatic-backgrounding-of-long-tool-calls) in non-interactive mode on Claude Code v2.1.212 or later |203| `CLAUDE_AUTO_BACKGROUND_TASKS` | Set to `1` to force-enable automatic backgrounding of long-running agent tasks. When enabled, subagents are moved to the background after running for approximately two minutes. Also enables [automatic backgrounding of long MCP tool calls](/docs/en/mcp#automatic-backgrounding-of-long-tool-calls) in non-interactive mode on Claude Code v2.1.212 or later |

200| `CLAUDE_AX_PREPARK_MS` | In [screen reader mode](/docs/en/accessibility), how many milliseconds Claude Code waits before it writes a new or changed line. Default `0`, so Claude Code doesn't wait. Before v2.1.287, the default was `50`. Claude Code caps the wait at `5000`. Requires Claude Code v2.1.233 or later |204| `CLAUDE_AX_PREPARK_MS` | In [screen reader mode](/docs/en/accessibility), how many milliseconds Claude Code waits before it writes a new or changed line. Default `0`, so Claude Code doesn't wait. Before v2.1.287, the default was `50`. Claude Code caps the wait at `5000`. Requires Claude Code v2.1.233 or later |


283| `CLAUDE_CODE_ENABLE_AUTO_MODE` | Accepted for compatibility with older releases and has no effect. Auto mode is available by default on every provider, including Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, and signed-in [Claude apps gateway](/docs/en/claude-apps-gateway) sessions. In v2.1.158 through v2.1.206, setting this to `1` was required to make [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) available on those providers |287| `CLAUDE_CODE_ENABLE_AUTO_MODE` | Accepted for compatibility with older releases and has no effect. Auto mode is available by default on every provider, including Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, and signed-in [Claude apps gateway](/docs/en/claude-apps-gateway) sessions. In v2.1.158 through v2.1.206, setting this to `1` was required to make [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) available on those providers |

284| `CLAUDE_CODE_ENABLE_AWAY_SUMMARY` | Override [session recap](/docs/en/interactive-mode#session-recap) availability. Set to `0` to force recaps off regardless of the `/config` toggle. Set to `1` to force recaps on when [`awaySummaryEnabled`](/docs/en/settings-reference#awaysummaryenabled) is `false`. Takes precedence over the setting and `/config` toggle |288| `CLAUDE_CODE_ENABLE_AWAY_SUMMARY` | Override [session recap](/docs/en/interactive-mode#session-recap) availability. Set to `0` to force recaps off regardless of the `/config` toggle. Set to `1` to force recaps on when [`awaySummaryEnabled`](/docs/en/settings-reference#awaysummaryenabled) is `false`. Takes precedence over the setting and `/config` toggle |

285| `CLAUDE_CODE_ENABLE_BACKGROUND_PLUGIN_REFRESH` | Set to `1` to refresh plugin state at turn boundaries in [non-interactive mode](/docs/en/headless) after a background install completes. Off by default because the refresh changes the system prompt mid-session, which invalidates [prompt caching](/docs/en/prompt-caching) for that turn |289| `CLAUDE_CODE_ENABLE_BACKGROUND_PLUGIN_REFRESH` | Set to `1` to refresh plugin state at turn boundaries in [non-interactive mode](/docs/en/headless) after a background install completes. Off by default because the refresh changes the system prompt mid-session, which invalidates [prompt caching](/docs/en/prompt-caching) for that turn |

290| `CLAUDE_CODE_ENABLE_CFC` | Set to `1` to start a CLI session with [Chrome integration](/docs/en/chrome) on, or `0` to start with it off. Takes precedence over the [`claudeInChromeDefaultEnabled`](/docs/en/settings-reference#claudeinchromedefaultenabled) setting. The `--chrome` and `--no-chrome` flags take precedence over both. Claude Code [ignores `1` in project and local settings](/docs/en/chrome#project-settings-can’t-turn-on-chrome) |

286| `CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL` | Set to `1` to route the "How is Claude doing?" session quality survey to your own [OpenTelemetry collector](/docs/en/monitoring-usage) when Anthropic-bound nonessential traffic is blocked. Survey ratings are emitted only as OTEL events to your configured collector. No survey data is sent to Anthropic in this mode. Applies when `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`, `DISABLE_TELEMETRY`, or `DO_NOT_TRACK` is set, and has no effect otherwise. `CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY` and the organization product feedback policy take precedence |291| `CLAUDE_CODE_ENABLE_FEEDBACK_SURVEY_FOR_OTEL` | Set to `1` to route the "How is Claude doing?" session quality survey to your own [OpenTelemetry collector](/docs/en/monitoring-usage) when Anthropic-bound nonessential traffic is blocked. Survey ratings are emitted only as OTEL events to your configured collector. No survey data is sent to Anthropic in this mode. Applies when `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`, `DISABLE_TELEMETRY`, or `DO_NOT_TRACK` is set, and has no effect otherwise. `CLAUDE_CODE_DISABLE_FEEDBACK_SURVEY` and the organization product feedback policy take precedence |

287| `CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING` | Controls whether tool call inputs stream from the API as Claude generates them. With this off, a large tool input such as a long file write arrives only after Claude finishes generating it, which can look like it's hanging. Enabled by default on the Anthropic API. On Amazon Bedrock and Google Cloud's Agent Platform, enabled per model where the deployed container supports it. Set to `0` to opt out. Set to `1` to force on when routing through a proxy via `ANTHROPIC_BASE_URL`, `ANTHROPIC_VERTEX_BASE_URL`, or `ANTHROPIC_BEDROCK_BASE_URL`. Off by default on Microsoft Foundry and [gateway](/docs/en/llm-gateway) connections |292| `CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING` | Controls whether tool call inputs stream from the API as Claude generates them. With this off, a large tool input such as a long file write arrives only after Claude finishes generating it, which can look like it's hanging. Enabled by default on the Anthropic API. On Amazon Bedrock and Google Cloud's Agent Platform, enabled per model where the deployed container supports it. Set to `0` to opt out. Set to `1` to force on when routing through a proxy via `ANTHROPIC_BASE_URL`, `ANTHROPIC_VERTEX_BASE_URL`, or `ANTHROPIC_BEDROCK_BASE_URL`. Off by default on Microsoft Foundry and [gateway](/docs/en/llm-gateway) connections |

288| `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY` | Set to `1` to populate the `/model` picker from your gateway's `/v1/models` endpoint when `ANTHROPIC_BASE_URL` points at an Anthropic-compatible gateway such as LiteLLM, Kong, or an internal proxy. Off by default because gateways backed by a shared API key would otherwise show every user every model the key can access. Discovered models are still filtered by an [`availableModels`](/docs/en/settings-reference#availablemodels) allowlist the session receives; deliver the list through [MDM or a managed settings file](/docs/en/managed-settings#delivery-mechanisms), since [server-managed delivery is not available on gateway configurations](/docs/en/server-managed-settings#platform-availability) |293| `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY` | Set to `1` to populate the `/model` picker from your gateway's `/v1/models` endpoint when `ANTHROPIC_BASE_URL` points at an Anthropic-compatible gateway such as LiteLLM, Kong, or an internal proxy. Off by default because gateways backed by a shared API key would otherwise show every user every model the key can access. Discovered models are still filtered by an [`availableModels`](/docs/en/settings-reference#availablemodels) allowlist the session receives; deliver the list through [MDM or a managed settings file](/docs/en/managed-settings#delivery-mechanisms), since [server-managed delivery is not available on gateway configurations](/docs/en/server-managed-settings#platform-availability) |


368| `CLAUDE_CODE_RESUME_INTERRUPTED_TURN_MAX_AGE_MS` | Maximum age in milliseconds of the last transcript message for a session that ended mid-turn to continue automatically on resume. When the last message is older than this bound, Claude Code skips the `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` automatic resume and its `CLAUDE_CODE_RESUME_PROMPT` continuation message, and the session starts idle so you continue explicitly. Unset or `0` means no bound, except that a turn whose last request failed with an API error resumes only while that error is less than six hours old. A positive value bounds every turn, including those; a negative or non-numeric value applies a one-hour bound. Spawn scripts for long-running agents can set this so a restart against an old transcript doesn't re-run a stale prompt. Claude Code sets a one-hour bound itself when it restarts a crashed [agent view](/docs/en/agent-view) session that inherited its conversation from an interactive session. Requires Claude Code v2.1.211 or later |373| `CLAUDE_CODE_RESUME_INTERRUPTED_TURN_MAX_AGE_MS` | Maximum age in milliseconds of the last transcript message for a session that ended mid-turn to continue automatically on resume. When the last message is older than this bound, Claude Code skips the `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` automatic resume and its `CLAUDE_CODE_RESUME_PROMPT` continuation message, and the session starts idle so you continue explicitly. Unset or `0` means no bound, except that a turn whose last request failed with an API error resumes only while that error is less than six hours old. A positive value bounds every turn, including those; a negative or non-numeric value applies a one-hour bound. Spawn scripts for long-running agents can set this so a restart against an old transcript doesn't re-run a stale prompt. Claude Code sets a one-hour bound itself when it restarts a crashed [agent view](/docs/en/agent-view) session that inherited its conversation from an interactive session. Requires Claude Code v2.1.211 or later |

369| `CLAUDE_CODE_RESUME_PROMPT` | Override the continuation message Claude Code sends to Claude when `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` continues an interrupted turn instead of resending its prompt, or when you resume a [deferred tool call](/docs/en/hooks#defer-a-tool-call-for-later) with `-p`. Defaults to `Continue from where you left off.`. An empty string uses the default |374| `CLAUDE_CODE_RESUME_PROMPT` | Override the continuation message Claude Code sends to Claude when `CLAUDE_CODE_RESUME_INTERRUPTED_TURN` continues an interrupted turn instead of resending its prompt, or when you resume a [deferred tool call](/docs/en/hooks#defer-a-tool-call-for-later) with `-p`. Defaults to `Continue from where you left off.`. An empty string uses the default |

370| `CLAUDE_CODE_RETRY_WATCHDOG` | Set to `1` for unattended sessions such as eval harnesses, CI jobs, or remote workers. Retries `429` and `529` capacity errors indefinitely instead of failing after `CLAUDE_CODE_MAX_RETRIES` attempts. Claude Code fails at once when a standard-speed request gets a `429` that reports a spend limit or exhausted usage credits, even one from a [gateway spend cap](/docs/en/errors#spend-limit-reached) that resets on a schedule. Before v2.1.239, the watchdog retried these indefinitely. For fast mode requests, see [Handle rate limits](/docs/en/fast-mode#handle-rate-limits). The watchdog backs off up to 5 minutes between attempts, or until the limit resets when the response carries a rate-limit reset time, so a session that hits a usage limit waits out the remaining window. On v2.1.199 or later it also raises the default retry count for other transient errors, such as server errors, timeouts, and dropped connections, to 300, roughly three hours of backoff, and removes the cap of 15 on `CLAUDE_CODE_MAX_RETRIES` if you set that variable explicitly. Requires Claude Code v2.1.186 or later |375| `CLAUDE_CODE_RETRY_WATCHDOG` | Set to `1` for unattended sessions such as eval harnesses, CI jobs, or remote workers. Retries `429` and `529` capacity errors indefinitely instead of failing after `CLAUDE_CODE_MAX_RETRIES` attempts. Claude Code fails at once when a standard-speed request gets a `429` that reports a spend limit or exhausted usage credits, even one from a [gateway spend cap](/docs/en/errors#spend-limit-reached) that resets on a schedule. Before v2.1.239, the watchdog retried these indefinitely. For fast mode requests, see [Handle rate limits](/docs/en/fast-mode#handle-rate-limits). The watchdog backs off up to 5 minutes between attempts, or until the limit resets when the response carries a rate-limit reset time, so a session that hits a usage limit waits out the remaining window. On v2.1.199 or later it also raises the default retry count for other transient errors, such as server errors, timeouts, and dropped connections, to 300, roughly three hours of backoff, and removes the cap of 15 on `CLAUDE_CODE_MAX_RETRIES` if you set that variable explicitly. Requires Claude Code v2.1.186 or later |

376| `CLAUDE_CODE_RETRY_WATCHDOG_MAX_WAIT_MS` | Maximum time in milliseconds that each API request spends waiting out `429` and `529` errors when `CLAUDE_CODE_RETRY_WATCHDOG` is set. Once that time is spent, the next such error ends the request. Give a positive whole number in plain digits, such as `1800000` for 30 minutes. When unset, the wait has no limit. Requires Claude Code v2.1.295 or later |

371| `CLAUDE_CODE_SAFE_MODE` | Set to `1` to start in safe mode: CLAUDE.md, skills, plugins, hooks, MCP servers, custom commands and agents, output styles, workflows, custom themes, custom keybindings, status line and file-suggestion commands, LSP servers, and auto memory do not load, for troubleshooting a broken configuration. Managed settings policy still applies, including policy-configured hooks, status line, and file-suggestion commands; managed plugins, managed skills, managed CLAUDE.md, and policy-configured MCP servers do not. Equivalent to passing [`--safe-mode`](/docs/en/cli-reference#cli-flags). Directly spawned child processes inherit the variable |377| `CLAUDE_CODE_SAFE_MODE` | Set to `1` to start in safe mode: CLAUDE.md, skills, plugins, hooks, MCP servers, custom commands and agents, output styles, workflows, custom themes, custom keybindings, status line and file-suggestion commands, LSP servers, and auto memory do not load, for troubleshooting a broken configuration. Managed settings policy still applies, including policy-configured hooks, status line, and file-suggestion commands; managed plugins, managed skills, managed CLAUDE.md, and policy-configured MCP servers do not. Equivalent to passing [`--safe-mode`](/docs/en/cli-reference#cli-flags). Directly spawned child processes inherit the variable |

372| `CLAUDE_CODE_SCRIPT_CAPS` | JSON object limiting how many times specific scripts may be invoked per session when `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB` is set. Keys are substrings matched against the command text; values are integer call limits. For example, `{"deploy.sh": 2}` allows `deploy.sh` to be called at most twice. Matching is substring-based so shell-expansion tricks like `./scripts/deploy.sh $(evil)` still count against the cap. Runtime fan-out via `xargs` or `find -exec` is not detected; this is a defense-in-depth control |378| `CLAUDE_CODE_SCRIPT_CAPS` | JSON object limiting how many times specific scripts may be invoked per session when `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB` is set. Keys are substrings matched against the command text; values are integer call limits. For example, `{"deploy.sh": 2}` allows `deploy.sh` to be called at most twice. Matching is substring-based so shell-expansion tricks like `./scripts/deploy.sh $(evil)` still count against the cap. Runtime fan-out via `xargs` or `find -exec` is not detected; this is a defense-in-depth control |

373| `CLAUDE_CODE_SCROLL_SPEED` | Set the mouse wheel scroll multiplier in [fullscreen rendering](/docs/en/fullscreen#mouse-wheel-scrolling). Accepts any positive value up to 20, including fractional values below 1 such as `0.5` to slow accelerated trackpad and wheel scrolling in terminals that already amplify wheel events. Set to `3` to match `vim` if your terminal sends one wheel event per notch without amplification. Ignored in the JetBrains IDE terminal, where Claude Code uses its own scroll handling |379| `CLAUDE_CODE_SCROLL_SPEED` | Set the mouse wheel scroll multiplier in [fullscreen rendering](/docs/en/fullscreen#mouse-wheel-scrolling). Accepts any positive value up to 20, including fractional values below 1 such as `0.5` to slow accelerated trackpad and wheel scrolling in terminals that already amplify wheel events. Set to `3` to match `vim` if your terminal sends one wheel event per notch without amplification. Ignored in the JetBrains IDE terminal, where Claude Code uses its own scroll handling |


576* Use [the advisor tool](/docs/en/advisor#requirements)582* Use [the advisor tool](/docs/en/advisor#requirements)

577* Read or reply to [comments on an artifact](/docs/en/artifacts#collect-comments-on-an-artifact)583* Read or reply to [comments on an artifact](/docs/en/artifacts#collect-comments-on-an-artifact)

578* Have Claude read [another organization's public artifact](/docs/en/artifacts#read-an-artifact-shared-with-you)584* Have Claude read [another organization's public artifact](/docs/en/artifacts#read-an-artifact-shared-with-you)

579* Have Claude Code probe claude.ai connector servers for [MCP protocol revision 2026-07-28](/docs/en/mcp#mcp-client-runtimes) unless you set `MCP_PROTOCOL_NEGOTIATION=auto`

580* Get the [PowerShell tool](/docs/en/tools-reference#powershell-tool) by default for claude.ai and Console accounts on Windows with Git Bash installed; Claude Code routes shell commands through Git Bash unless you set `CLAUDE_CODE_USE_POWERSHELL_TOOL=1`. On Windows without Git Bash, the tool stays on585* Get the [PowerShell tool](/docs/en/tools-reference#powershell-tool) by default for claude.ai and Console accounts on Windows with Git Bash installed; Claude Code routes shell commands through Git Bash unless you set `CLAUDE_CODE_USE_POWERSHELL_TOOL=1`. On Windows without Git Bash, the tool stays on

581* Get [Claude-drafted feedback](/docs/en/tools-reference#sendfeedback-tool-behavior), which Claude Code turns on through a fetched flag586* Get [Claude-drafted feedback](/docs/en/tools-reference#sendfeedback-tool-behavior), which Claude Code turns on through a fetched flag

582* Have Claude [treat large pastes as pasted rather than typed text](/docs/en/terminal-config#how-claude-treats-pasted-text); the content behind a `[Pasted text #N]` placeholder reaches Claude unmarked587* Have Claude [treat large pastes as pasted rather than typed text](/docs/en/terminal-config#how-claude-treats-pasted-text); the content behind a `[Pasted text #N]` placeholder reaches Claude unmarked

errors.md +9 −48

Details

187| `<model> has safety measures that flagged this message for a cybersecurity topic` | [Request errors](#safety-measures-flagged-a-cybersecurity-topic) |187| `<model> has safety measures that flagged this message for a cybersecurity topic` | [Request errors](#safety-measures-flagged-a-cybersecurity-topic) |

188| `` Details: `[reasoning_extraction]` `` | [Request errors](#safeguards-flagged-a-request-for-claudes-reasoning) |188| `` Details: `[reasoning_extraction]` `` | [Request errors](#safeguards-flagged-a-request-for-claudes-reasoning) |

189| `API Error: Output blocked by content filtering policy` | [Request errors](#output-blocked-by-content-filtering-policy) |189| `API Error: Output blocked by content filtering policy` | [Request errors](#output-blocked-by-content-filtering-policy) |

190| `Installation was killed before it could finish (exit code 137)` | [Installation errors](#installation-was-killed-before-it-could-finish) |190| `Installation was killed before it could finish (exit code 137)` | [Troubleshoot installation and login](/docs/en/troubleshoot-install#installation-was-killed-before-it-could-finish) |

191| `The connection dropped while downloading the update` | [Installation errors](#the-connection-dropped-while-downloading-the-update) |191| `The connection dropped while downloading the update` | [Troubleshoot installation and login](/docs/en/troubleshoot-install#the-connection-dropped-while-downloading-the-update) |

192| `Download timed out: exceeded the total deadline` | [Installation errors](#the-connection-dropped-while-downloading-the-update) |192| `Download timed out: exceeded the total deadline` | [Troubleshoot installation and login](/docs/en/troubleshoot-install#the-connection-dropped-while-downloading-the-update) |

193| `--bg and --print conflict` | [Command-line errors](#conflict-between-bg-and-print) |193| `--bg and --print conflict` | [Command-line errors](#conflict-between-bg-and-print) |

194| `Error: Cannot use both --append-subagent-system-prompt and --append-subagent-system-prompt-file. Please use only one.` | [Command-line errors](#conflict-between-a-system-prompt-flag-and-its-file-form) |194| `Error: Cannot use both --append-subagent-system-prompt and --append-subagent-system-prompt-file. Please use only one.` | [Command-line errors](#conflict-between-a-system-prompt-flag-and-its-file-form) |

195| `Cloud sessions cannot be created from a --restricted session` | [Command-line errors](#cloud-sessions-cannot-be-created-from-a-restricted-session) |195| `Cloud sessions cannot be created from a --restricted session` | [Command-line errors](#cloud-sessions-cannot-be-created-from-a-restricted-session) |


259| `Marketplace name impersonates an official Anthropic/Claude marketplace` | [Plugin errors](#claude-code-refuses-the-marketplace-name) |259| `Marketplace name impersonates an official Anthropic/Claude marketplace` | [Plugin errors](#claude-code-refuses-the-marketplace-name) |

260| `Marketplace "<name>" is already added from a different source` | [Plugin errors](#marketplace-is-already-added-from-a-different-source) |260| `Marketplace "<name>" is already added from a different source` | [Plugin errors](#marketplace-is-already-added-from-a-different-source) |

261| `"<name>" is another spelling of "<reserved>", a reserved marketplace name` | [Plugin errors](#marketplace-name-is-another-spelling-of-a-reserved-name) |261| `"<name>" is another spelling of "<reserved>", a reserved marketplace name` | [Plugin errors](#marketplace-name-is-another-spelling-of-a-reserved-name) |

262| `Cannot add marketplace "<name>": Claude Code cannot install plugins from a marketplace with this name` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#cannot-install-plugins-from-a-marketplace-with-this-name) |

262| `Marketplace "<name>" is added but ignored` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#marketplace-is-added-but-ignored) |263| `Marketplace "<name>" is added but ignored` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#marketplace-is-added-but-ignored) |

263| `Marketplace "<name>" is registered but was refused (see the debug log)` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#marketplace-is-added-but-ignored) |264| `Marketplace "<name>" is registered but was refused (see the debug log)` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#marketplace-is-added-but-ignored) |

264| `references ${user_config.*} in a shell-form command` | [Plugin errors](#plugin-command-references-user-config) |265| `references ${user_config.*} in a shell-form command` | [Plugin errors](#plugin-command-references-user-config) |


267| `Plugin archive integrity check failed` | [Plugin errors](#plugin-archive-integrity-check-failed) |268| `Plugin archive integrity check failed` | [Plugin errors](#plugin-archive-integrity-check-failed) |

268| `An npm plugin source must name a registry package` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#an-npm-plugin-source-must-name-a-registry-package) |269| `An npm plugin source must name a registry package` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#an-npm-plugin-source-must-name-a-registry-package) |

269| `The packages it lists are not installed` / `The packages it lists were not installed, because` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#the-packages-it-lists-are-not-installed) |270| `The packages it lists are not installed` / `The packages it lists were not installed, because` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#the-packages-it-lists-are-not-installed) |

271| `does not load (...), so Claude Code ignores the whole file` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#does-not-load-so-claude-code-ignores-the-whole-file) |

270| `path escapes plugin directory` | [Plugin errors](#path-escapes-plugin-directory) |272| `path escapes plugin directory` | [Plugin errors](#path-escapes-plugin-directory) |

271| `path could not be checked` | [Plugin errors](#path-could-not-be-checked) |273| `path could not be checked` | [Plugin errors](#path-could-not-be-checked) |

272| `its marketplace entry path does not stay inside the marketplace directory` | [Plugin errors](#marketplace-entry-path-does-not-stay-inside-the-marketplace-directory) |274| `its marketplace entry path does not stay inside the marketplace directory` | [Plugin errors](#marketplace-entry-path-does-not-stay-inside-the-marketplace-directory) |


277| `"<plugin>" was not uninstalled: it is still switched on in <file>` | [Plugin errors](#plugin-was-not-uninstalled) |279| `"<plugin>" was not uninstalled: it is still switched on in <file>` | [Plugin errors](#plugin-was-not-uninstalled) |

278| `"<plugin>" was not uninstalled: <file> is there and could not be read` | [Plugin errors](#plugin-was-not-uninstalled) |280| `"<plugin>" was not uninstalled: <file> is there and could not be read` | [Plugin errors](#plugin-was-not-uninstalled) |

279| `Plugin "<plugin>" was not uninstalled: installed_plugins.json` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#installed-plugins-json-holds-a-record-this-version-cannot-read) |281| `Plugin "<plugin>" was not uninstalled: installed_plugins.json` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#installed-plugins-json-holds-a-record-this-version-cannot-read) |

282| `Plugin directory does not exist: <path>` | [Plugin troubleshooting](/docs/en/plugins/troubleshooting#plugin-directory-does-not-exist) |

280| `Error: No such tool available: <tool name>` | [Tool errors](#no-such-tool-available) |283| `Error: No such tool available: <tool name>` | [Tool errors](#no-such-tool-available) |

281| `would be spawned with zero tools — refusing` | [Tool errors](#agent-would-be-spawned-with-zero-tools) |284| `would be spawned with zero tools — refusing` | [Tool errors](#agent-would-be-spawned-with-zero-tools) |

282| `File is covered by a Read deny rule in your permission settings` | [Tool errors](#file-is-covered-by-a-read-deny-rule) |285| `File is covered by a Read deny rule in your permission settings` | [Tool errors](#file-is-covered-by-a-read-deny-rule) |


382* A server error or overloaded response that arrives after Claude has finished thinking but before it has started any text or tool call. Claude Code retries a server error at that point up to two times. Before v2.1.284, Claude Code ended the turn with the error at that point.385* A server error or overloaded response that arrives after Claude has finished thinking but before it has started any text or tool call. Claude Code retries a server error at that point up to two times. Before v2.1.284, Claude Code ended the turn with the error at that point.

383* Dropped connections. When a connection drops partway through a request before Claude has completed any part of its response, including its thinking, Claude Code re-issues the request with the same backoff and the turn continues, even if some text had already started streaming. When it drops after Claude has finished thinking but before it has started any text or tool call, Claude Code instead re-issues the request up to two times in quick succession, and ends the turn with `Connection lost before a response was produced` if the connection keeps dropping at that point.386* Dropped connections. When a connection drops partway through a request before Claude has completed any part of its response, including its thinking, Claude Code re-issues the request with the same backoff and the turn continues, even if some text had already started streaming. When it drops after Claude has finished thinking but before it has started any text or tool call, Claude Code instead re-issues the request up to two times in quick succession, and ends the turn with `Connection lost before a response was produced` if the connection keeps dropping at that point.

384* A connection that Claude Code detects was broken by your computer going to sleep partway through a request. Claude Code counts it as a dropped connection under the rules above; once the retry label names the specific reason, it reads `Connection lost while your computer was asleep`, and if the turn ends after Claude has finished thinking but before any text or tool call, the message reads `Your computer went to sleep before a response was produced`.387* A connection that Claude Code detects was broken by your computer going to sleep partway through a request. Claude Code counts it as a dropped connection under the rules above; once the retry label names the specific reason, it reads `Connection lost while your computer was asleep`, and if the turn ends after Claude has finished thinking but before any text or tool call, the message reads `Your computer went to sleep before a response was produced`.

385* A stalled response stream, when the response headers have arrived but none of Claude's response has arrived, or when Claude has finished thinking but hasn't started any text or tool call: Claude Code aborts the stalled connection and re-issues the request at most once, outside the 10-attempt budget above. If the response stalls a second time after Claude has finished thinking but before any text or tool call, Claude Code ends the turn with `The response stalled before a response was produced`.388* A stalled response stream, when the response headers have arrived but none of Claude's response has arrived, or when Claude has finished thinking but hasn't started any text or tool call: Claude Code aborts the stalled connection and streams the request again at most once. If the response stalls a second time after Claude has finished thinking but before any text or tool call, Claude Code ends the turn with `The response stalled before a response was produced`.

386* A streaming request the API never answers with response headers, on a connection where the [first-byte deadline runs](/docs/en/network-config#streaming-idle-watchdogs): Claude Code aborts it at the deadline and re-sends it at most once per model request, within the retry budget, then ends the turn with [No response from API](#no-response-from-api) if that attempt goes unanswered too. On other connections, the request waits out `API_TIMEOUT_MS`. When you set `CLAUDE_CODE_RETRY_WATCHDOG`, the one-retry cap doesn't apply.389* A streaming request the API never answers with response headers, on a connection where the [first-byte deadline runs](/docs/en/network-config#streaming-idle-watchdogs): Claude Code aborts it at the deadline and re-sends it at most once per model request, within the retry budget, then ends the turn with [No response from API](#no-response-from-api) if that attempt goes unanswered too. On other connections, the request waits out `API_TIMEOUT_MS`. When you set `CLAUDE_CODE_RETRY_WATCHDOG`, the one-retry cap doesn't apply.

387* A streaming response that the API's output content filter stops before Claude has either finished thinking or started any text or tool call. Claude Code re-sends the request once, within the retry budget, and shows [Output blocked by content filtering policy](#output-blocked-by-content-filtering-policy) if the filter stops the second response too.390* A streaming response that the API's output content filter stops before Claude has either finished thinking or started any text or tool call. Claude Code re-sends the request once, within the retry budget, and shows [Output blocked by content filtering policy](#output-blocked-by-content-filtering-policy) if the filter stops the second response too.

388* Temporary 429 throttles, but not a gateway's spend-limit `429`, which isn't a throttle; see [Spend limit reached](#spend-limit-reached).391* Temporary 429 throttles, but not a gateway's spend-limit `429`, which isn't a throttle; see [Spend limit reached](#spend-limit-reached).


2740* Rephrase your last message or take a different approach2743* Rephrase your last message or take a different approach

2741* To step back to a checkpoint before the turn that triggered the block, press Esc twice or run `/rewind`. See [Checkpointing](/docs/en/checkpointing)2744* To step back to a checkpoint before the turn that triggered the block, press Esc twice or run `/rewind`. See [Checkpointing](/docs/en/checkpointing)

2742 2745 

2743## Installation errors

2744 

2745These errors appear while installing or updating Claude Code, from the [install script](/docs/en/setup#install-claude-code), `claude install`, or `claude update`. For `command not found`, PATH, permission, and TLS problems during setup, see [Troubleshoot installation and login](/docs/en/troubleshoot-install).

2746 

2747### Installation was killed before it could finish

2748 

2749The install script reports when the `claude install` step is terminated by a signal. On Linux, exit code 137 means the process received SIGKILL, and on a low-memory host that's usually the kernel out-of-memory (OOM) killer. The script prints this explanation and exits with code 137:

2750 

2751```text theme={null}

2752Installation was killed before it could finish (exit code 137). This usually means the system ran out of memory.

2753Claude Code needs roughly 512MB of free memory to install. Free up memory, then run this script again.

2754```

2755 

2756For any other fatal signal, and for exit code 137 on macOS, the script prints `Installation was killed before it could finish (exit code <N>)` with the actual exit code and omits the out-of-memory explanation. The message comes from the install script macOS and Linux use, which also covers installs inside WSL; the native Windows install scripts never print it. Before v2.1.200, the script exited with only the shell's bare `Killed` line.

2757 

2758**What to do:**

2759 

2760* Stop other processes to free memory, then rerun the installer

2761* Add swap space or move to a larger instance. See [Install killed on low-memory Linux servers](/docs/en/troubleshoot-install#install-killed-on-low-memory-linux-servers) for the swap-file commands.

2762 

2763### The connection dropped while downloading the update

2764 

2765The connection to the download server closed while `claude install` or `claude update` was fetching the Claude Code binary, and the retries didn't recover. Claude Code retries the download when the connection drops, the transfer stalls, or the downloaded file fails its checksum, up to three attempts in total. A completed HTTP error, such as a 404, isn't retried because the server already answered. Before v2.1.202, a single dropped connection failed the download immediately with the bare error `aborted` instead of retrying.

2766 

2767```text theme={null}

2768The connection dropped while downloading the update (attempt 3/3: aborted). Check your network — proxies sometimes cut off large downloads.

2769```

2770 

2771The text in parentheses names which attempt failed and the underlying network error. `claude update` precedes the message with `Error: Failed to install native update` on stderr.

2772 

2773A download that stays connected but doesn't finish within 10 minutes fails with `Download timed out: exceeded the total deadline` instead. Claude Code doesn't retry a timed-out download, because a connection too slow to finish inside the deadline won't finish on an immediate retry either. The steps below apply to both messages.

2774 

2775A proxy or gateway can close a long transfer before it finishes, and the Claude Code binary is a large download.

2776 

2777**What to do:**

2778 

2779* Run `claude update` again. On an otherwise healthy network, the download usually succeeds on the next run. For the timed-out message, run it again from a faster or less throttled network.

2780* If your network requires a proxy, set `HTTPS_PROXY` before running the installer or `claude update`. See [Check network connectivity](/docs/en/troubleshoot-install#check-network-connectivity).

2781* If a corporate proxy keeps closing the transfer, ask your network team to allow the full download from `downloads.claude.ai`. See [Network access requirements](/docs/en/network-config#network-access-requirements).

2782* Run `claude doctor` from your shell for installation diagnostics

2783 

2784## Command-line errors2746## Command-line errors

2785 2747 

2786These errors come from the `claude` command line and its subcommands, from a command name you submit at the prompt, and from commands such as `/security-review` that gather context by running shell commands before their prompt runs. They also come from `/tui`, which relaunches the CLI.2748These errors come from the `claude` command line and its subcommands, from a command name you submit at the prompt, and from commands such as `/security-review` that gather context by running shell commands before their prompt runs. They also come from `/tui`, which relaunches the CLI.


4557 4519 

4558### This session has no saved transcript4520### This session has no saved transcript

4559 4521 

4560You attached to a stopped [background session](/docs/en/agent-view) that was backgrounded from another conversation with `←` or `/background` and stopped before its first response finished. Until that first response finishes, the conversation still lives only in the session it was backgrounded from, so `claude attach` refuses to start the stopped session rather than begin a blank conversation under the same session ID. The message ends with the `claude respawn` command for this session:4522You attached to a session that you [moved to the background](/docs/en/agent-view#from-inside-a-session) with `←` or `/background` and that stopped before it ran a turn of its own. Claude Code couldn't find the conversation you moved it from, so the session has nothing to resume. The message ends with the `claude respawn` command for this session:

4561 4523 

4562```text theme={null}4524```text theme={null}

4563This session has no saved transcript — it was stopped before its first response finished. If it was backgrounded from another conversation, that one is still intact; `claude respawn <id>` starts this one fresh.4525This session has no saved transcript — it was stopped before its first response finished. If it was backgrounded from another conversation, that one is still intact; `claude respawn <id>` starts this one fresh.


4567 4529 

4568**What to do:**4530**What to do:**

4569 4531 

4570* The conversation you backgrounded from is intact: resume it with [`claude --resume`](/docs/en/sessions) or keep working in it4532* To start the stopped session fresh, run `claude respawn <id>` with the ID from the message, or press `Enter` twice on its row in agent view

4571* To start the stopped session fresh anyway, run `claude respawn <id>` with the ID from the message, or press `Enter` twice on its row in agent view

4572* If the session did finish a response and you still see this refusal on a version before v2.1.214, an unreadable folder in `~/.claude/projects` could make the transcript scan miss the saved conversation; update to v2.1.214 or later, which tolerates unreadable folders during the scan4533* If the session did finish a response and you still see this refusal on a version before v2.1.214, an unreadable folder in `~/.claude/projects` could make the transcript scan miss the saved conversation; update to v2.1.214 or later, which tolerates unreadable folders during the scan

4573 4534 

4574<h3 id="this-session-is-running-in-another-terminal">4535<h3 id="this-session-is-running-in-another-terminal">

glossary.md +2 −2

Details

343 343 

344A command, `/teleport`, that pulls a cloud Claude Code session into your local terminal. Claude fetches the branch, loads the conversation history, and resumes from the cloud session's last state. The reverse direction is `--cloud`, which sends a local task to run in the cloud.344A command, `/teleport`, that pulls a cloud Claude Code session into your local terminal. Claude fetches the branch, loads the conversation history, and resumes from the cloud session's last state. The reverse direction is `--cloud`, which sends a local task to run in the cloud.

345 345 

346Learn more: [From cloud to terminal](/docs/en/claude-code-on-the-web#from-cloud-to-terminal)346Learn more: [Continue a cloud session in your terminal](/docs/en/claude-code-on-the-web#from-cloud-to-terminal)

347 347 

348### Tool348### Tool

349 349 


375 375 

376### Worktree isolation376### Worktree isolation

377 377 

378An isolation mode that runs Claude in a separate git worktree under `.claude/worktrees/`, enabled with the `-w` flag or `isolation: worktree` in subagent config. Changes stay on a separate branch in a separate directory, so parallel agents don't overwrite each other's files.378An isolation mode that runs Claude in a separate git worktree under `.claude/worktrees/`, enabled with the `-w` flag or `isolation: worktree` in subagent config. Changes stay on a separate branch in a separate directory, so parallel agents each edit their own copy of the files.

379 379 

380Learn more: [Run parallel sessions with git worktrees](/docs/en/worktrees)380Learn more: [Run parallel sessions with git worktrees](/docs/en/worktrees)

381 381 

goal.md +1 −1

Details

111claude -p "/goal CHANGELOG.md has an entry for every PR merged this week"111claude -p "/goal CHANGELOG.md has an entry for every PR merged this week"

112```112```

113 113 

114With the default text output, nothing prints until the run ends, so a goal that runs many turns can look stuck. Add `--output-format stream-json --verbose` to emit each message as the loop runs.114With the default text output, Claude's final response prints when the loop ends, so a goal that runs many turns can look stuck. Add `--output-format stream-json --verbose` to emit each message as the loop runs.

115 115 

116Interrupt the process with Ctrl+C to stop a non-interactive goal before it resolves.116Interrupt the process with Ctrl+C to stop a non-interactive goal before it resolves.

117 117 

headless.md +5 −3

Details

78 78 

79The run waits for background work such as background commands, subagents and workflows, Monitor watches, and pending `/loop` wakeups:79The run waits for background work such as background commands, subagents and workflows, Monitor watches, and pending `/loop` wakeups:

80 80 

81* **[Background commands](/docs/en/tools-reference#background-commands)**: for a command that the main conversation started, for example a dev server or a watch build, the run waits until the command exits or reaches its [time limit](/docs/en/tools-reference#time-limit-for-background-commands). Claude then takes one more turn with the outcome, and that turn's result becomes the run's last, which is the one `text` and `json` output print. While the command runs, the 10-minute cap doesn't end the wait.81* **[Background commands](/docs/en/tools-reference#background-commands)**: for a command that the main conversation started, for example a dev server or a watch build, the run waits until the command exits or reaches its [time limit](/docs/en/tools-reference#time-limit-for-background-commands). Claude then takes one more turn with the outcome. While the command runs, the 10-minute cap doesn't end the wait.

82* **Background [subagents](/docs/en/sub-agents) and workflows**: the run stays open until that work completes, because its result is part of the final output.82* **Background [subagents](/docs/en/sub-agents) and workflows**: the run stays open until that work completes, because its result is part of the final output.

83* **[Monitor](/docs/en/tools-reference#monitor-tool) watches**: the run waits until the watch times out or the 10-minute cap ends the wait, whichever comes first. While it waits, Claude keeps responding to what the watch reports. By default, a watch times out five minutes after Claude starts it.83* **[Monitor](/docs/en/tools-reference#monitor-tool) watches**: the run waits until the watch times out or the 10-minute cap ends the wait, whichever comes first. While it waits, Claude keeps responding to what the watch reports. By default, a watch times out five minutes after Claude starts it.

84* **Pending wakeups**: in a run whose prompt you passed as text rather than with `--input-format stream-json`, when Claude has scheduled a [self-paced `/loop` wakeup](/docs/en/scheduled-tasks#let-claude-choose-the-interval), the run waits for each wakeup to fire and runs its iteration until the [loop ends](/docs/en/scheduled-tasks#stop-a-loop), even past the 10-minute cap.84* **Pending wakeups**: in a run whose prompt you passed as text rather than with `--input-format stream-json`, when Claude has scheduled a [self-paced `/loop` wakeup](/docs/en/scheduled-tasks#let-claude-choose-the-interval), the run waits for each wakeup to fire and runs its iteration until the [loop ends](/docs/en/scheduled-tasks#stop-a-loop), even past the 10-minute cap.

85 85 

86If the run reaches its [`--max-budget-usd`](/docs/en/cli-reference#cli-flags) cap, Claude Code stops the remaining background work instead of waiting.86If the run reaches its [`--max-budget-usd`](/docs/en/cli-reference#cli-flags) cap, Claude Code stops the remaining background work instead of waiting.

87 87 

88When background work starts another turn, the run prints each turn's result with the default `text` output and the last turn's result with `json` output. Before v2.1.295, the run printed only the last turn's result with `text` output too.

89 

88### Stop a run with SIGTERM90### Stop a run with SIGTERM

89 91 

90If you stop a `claude -p` run with SIGTERM, for example with `kill` or from a process supervisor, Claude Code exits with code 143. Claude Code leaves the turn that was in progress unfinished and records no result for it. To end the turn instead, send SIGINT, or call the Agent SDK's `interrupt()`, before you stop the process.92If you stop a `claude -p` run with SIGTERM, for example with `kill` or from a process supervisor, Claude Code exits with code 143. Claude Code leaves the turn that was in progress unfinished and records no result for it. To end the turn instead, send SIGINT, or call the Agent SDK's `interrupt()`, before you stop the process.


238| `type` | `"system"` | message type |240| `type` | `"system"` | message type |

239| `subtype` | `"api_retry"` | identifies this as a retry event |241| `subtype` | `"api_retry"` | identifies this as a retry event |

240| `attempt` | integer | current attempt number, starting at 1 |242| `attempt` | integer | current attempt number, starting at 1 |

241| `max_retries` | integer | total retries permitted for this failure's cause, which can be fewer than the session-wide budget |243| `max_retries` | integer | total retries permitted for this failure's cause |

242| `retry_delay_ms` | integer | milliseconds until the next attempt |244| `retry_delay_ms` | integer | milliseconds until the next attempt |

243| `error_status` | integer or null | HTTP status code of the failed attempt, or `null` when the attempt got no HTTP response from the API |245| `error_status` | integer or null | HTTP status code of the failed attempt, or `null` when the attempt got no HTTP response from the API |

244| `no_response` | object, optional | present only when the failed attempt got [no response headers in time](/docs/en/errors#no-response-from-api). `waited_ms` is how long that attempt waited and `retry_wait_ms` is how long the retry will wait. In these events, `max_retries` reflects the one retry this cause normally gets, not the session-wide budget. Requires Claude Code v2.1.261 or later |246| `no_response` | object, optional | present only when the failed attempt got [no response headers in time](/docs/en/errors#no-response-from-api). `waited_ms` is how long that attempt waited and `retry_wait_ms` is how long the retry will wait. Requires Claude Code v2.1.261 or later |

245| `error` | string | error category: `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `rate_limit`, `overloaded`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, or `unknown` |247| `error` | string | error category: `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `rate_limit`, `overloaded`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, or `unknown` |

246| `uuid` | string | unique event identifier |248| `uuid` | string | unique event identifier |

247| `session_id` | string | session the event belongs to |249| `session_id` | string | session the event belongs to |

hooks.md +105 −28

Details

458| `async` | no | If `true`, runs in the background without blocking. See [Run hooks in the background](#run-hooks-in-the-background) |458| `async` | no | If `true`, runs in the background without blocking. See [Run hooks in the background](#run-hooks-in-the-background) |

459| `asyncRewake` | no | If `true`, runs in the background and wakes Claude on exit code 2. The hook's stderr, or stdout if stderr is empty, is shown to Claude as a [system reminder](/docs/en/glossary#system-reminder) so it can react to a long-running background failure |459| `asyncRewake` | no | If `true`, runs in the background and wakes Claude on exit code 2. The hook's stderr, or stdout if stderr is empty, is shown to Claude as a [system reminder](/docs/en/glossary#system-reminder) so it can react to a long-running background failure |

460| `shell` | no | Shell to use for this hook. Accepts `"bash"` or `"powershell"`. Defaults to `"bash"`, or to `"powershell"` on Windows when Git Bash isn't installed. Setting `"powershell"` runs the command via PowerShell on Windows. Does not require `CLAUDE_CODE_USE_POWERSHELL_TOOL` since hooks spawn PowerShell directly. Ignored when `args` is set |460| `shell` | no | Shell to use for this hook. Accepts `"bash"` or `"powershell"`. Defaults to `"bash"`, or to `"powershell"` on Windows when Git Bash isn't installed. Setting `"powershell"` runs the command via PowerShell on Windows. Does not require `CLAUDE_CODE_USE_POWERSHELL_TOOL` since hooks spawn PowerShell directly. Ignored when `args` is set |

461| `onFailure` | no | What happens to the action when the hook fails: `"continue"`, the default, or `"block"`. See [Block the action when a hook fails](#block-the-action-when-a-hook-fails). Requires Claude Code v2.1.295 or later |

461 462 

462<a id="exec-form-and-shell-form" />463<a id="exec-form-and-shell-form" />

463 464 


511| `url` | yes | URL to send the POST request to |512| `url` | yes | URL to send the POST request to |

512| `headers` | no | Additional HTTP headers as key-value pairs. Values support environment variable interpolation using `$VAR_NAME` or `${VAR_NAME}` syntax. Only variables listed in `allowedEnvVars` are resolved |513| `headers` | no | Additional HTTP headers as key-value pairs. Values support environment variable interpolation using `$VAR_NAME` or `${VAR_NAME}` syntax. Only variables listed in `allowedEnvVars` are resolved |

513| `allowedEnvVars` | no | List of environment variable names that may be interpolated into header values. References to unlisted variables are replaced with empty strings. Required for any env var interpolation to work |514| `allowedEnvVars` | no | List of environment variable names that may be interpolated into header values. References to unlisted variables are replaced with empty strings. Required for any env var interpolation to work |

515| `onFailure` | no | What happens to the action when the hook fails: `"continue"`, the default, or `"block"`. See [Block the action when a hook fails](#block-the-action-when-a-hook-fails). Requires Claude Code v2.1.295 or later |

514 516 

515Claude Code sends the hook's [JSON input](#hook-input-and-output) as the POST request body with `Content-Type: application/json`. The response body uses the same [JSON output format](#json-output) as command hooks.517Claude Code sends the hook's [JSON input](#hook-input-and-output) as the POST request body with `Content-Type: application/json`. The response body uses the same [JSON output format](#json-output) as command hooks.

516 518 


775 777 

776### Exit code output778### Exit code output

777 779 

778The exit code from your hook command tells Claude Code whether the action should proceed, be blocked, or be ignored. The exit code doesn't act alone. Claude Code reads [JSON output fields](#json-output) from stdout on every exit code, not just 0, and for events that use the standard decision model, a parsed object that passes schema validation takes effect alongside the code. Exit 2's block is the one outcome JSON can't override.780Your hook's exit code tells Claude Code whether to continue with the action that triggered the hook, such as a tool call or a prompt. A run that finishes has one of three outcomes:

779 781 

780Two tables own the per-event exceptions: [Exit code 2 behavior per event](#exit-code-2-behavior-per-event) says what exit codes do for each event, and [Decision control](#decision-control) says which decision fields each event honors. Universal fields such as `systemMessage` work across most events and are listed in the [JSON output](#json-output) table.782* **Success**: your hook exits 0. Claude Code applies any [JSON output](#json-output) fields your hook printed, and the action goes ahead unless those fields block or deny it.

783* **Blocking error**: your hook exits 2. On [events that can block](#exit-code-2-behavior-per-event), Claude Code stops the action.

784* **Non-blocking error**: your hook exits with any other code, or fails in some other way, such as not starting or printing invalid JSON. The action goes ahead, and on events such as `PreToolUse` you see a `<hook name> hook error` notice in the transcript. If you want a failed hook to block the action, set [`onFailure: "block"`](#block-the-action-when-a-hook-fails).

785 

786What your hook prints to stdout can change the outcome. For example, if a `PreToolUse` hook exits 1 but prints JSON that passes validation, the run is a success and the JSON fields decide what happens. To find your hook's outcome on an event such as `PreToolUse`, match what it printed to stdout in the first column with its exit code along the top:

787 

788| Stdout | Exit 0 | Exit 2 | Any other exit code |

789| :- | :- | :- | :- |

790| JSON object that passes [schema validation](#json-output) | Success. The fields apply | Blocking error. Claude Code still reads the fields, but they can't override the block | Success. Claude Code ignores the exit code, and the fields alone decide. With [`onFailure: "block"`](#block-the-action-when-a-hook-fails), this counts as a failure |

791| JSON that [can't be parsed](#exit-code-0) or fails schema validation | Non-blocking error. The notice carries the parse or validation message | Blocking error. Your stderr is the reason | Non-blocking error. The notice carries the parse or validation message |

792| [Plain text](#exit-code-0), or nothing | Success | Blocking error. Your stderr is the reason | Non-blocking error. The notice carries the first line of your stderr |

793 

794Some events have their own rules:

795 

796* **`WorktreeCreate`**: any non-zero exit code makes worktree creation fail, whatever your JSON says.

797* **`WorktreeRemove`**: any non-zero exit code makes worktree removal fail if the directory still exists afterward.

798* **`Stop`, `SubagentStop`, `TaskCompleted`, and a plugin's `UserPromptSubmit` hook**: when your hook exits 2 with nothing on stdout and its stderr says a file is missing, such as `No such file or directory`, Claude Code treats the run as a non-blocking error.

799* **`Elicitation` and `ElicitationResult`**: Claude Code applies your `hookSpecificOutput` when your hook exits 0, and ignores it on any other exit code.

800* **Events that discard hook output, such as `StopFailure`**: Claude Code ignores your JSON on any exit code, apart from side-effect fields like `terminalSequence`, which still fire.

801 

802To check what exit code 2 does on your event, see [Exit code 2 behavior per event](#exit-code-2-behavior-per-event). To check which decision fields it honors, see [Decision control](#decision-control).

781 803 

782#### Exit code 0804#### Exit code 0

783 805 


787 809 

788Whether Claude Code reads your stdout as [JSON output](#json-output) or as plain text depends on how it starts and ends, ignoring surrounding whitespace:810Whether Claude Code reads your stdout as [JSON output](#json-output) or as plain text depends on how it starts and ends, ignoring surrounding whitespace:

789 811 

790* **Starts with `{` and ends with `}`**: Claude Code parses it as JSON. When the output is two or more lines that each parse as JSON on their own, and no line is a [JSON output](#json-output) object that sets a field, Claude Code treats the whole output as plain text. When one of those lines does set a field, the whole output is a parse failure, described below.812* **Starts with `{` and ends with `}`**: Claude Code parses it as JSON. When the output is two or more lines that each parse as JSON on their own, and no line is a [JSON output](#json-output) object that sets a field, Claude Code treats the whole output as plain text. When one of those lines does set a field, the whole output is a parse failure.

791* **Starts with `{` but doesn't end with `}`**: Claude Code treats it as plain text.813* **Starts with `{` but doesn't end with `}`**: Claude Code treats it as plain text.

792* **Starts with anything else**: Claude Code treats it as plain text, a JSON array or a quoted JSON string included.814* **Starts with anything else**: Claude Code treats it as plain text, a JSON array or a quoted JSON string included.

793 815 

794For events that use the standard decision model, exit 0 with a parsed object that fails schema validation is a non-blocking error: the action proceeds, and the transcript shows a `<hook name> hook error` notice with the validation message. The same happens on any exit code other than 2, while [exit 2 still blocks](#exit-code-2).816When Claude Code tries to parse your stdout as JSON and can't, or the parsed object fails [schema validation](#json-output), the run is a [non-blocking error](#exit-code-output). The `<hook name> hook error` notice carries the parse or validation message. On the events that add plain-text stdout as context, Claude Code doesn't add stdout it failed to parse.

795 817 

796For events that use the standard decision model, when Claude Code tries to parse your stdout as JSON and can't, it reports a non-blocking error on every exit code other than 2. The transcript shows a `<hook name> hook error` notice with the parse message. On the events that add plain-text stdout as context, Claude Code doesn't add the text. Before v2.1.248, Claude Code treated that stdout as plain text.818Claude never sees stderr from a hook that exits 0. To read it yourself on events such as `PreToolUse`, enable [debug logging](#debug-hooks). To surface a warning to Claude from a `PostToolUse` or `PostToolUseFailure` hook, exit 2 instead so [Claude sees the stderr](#exit-code-2-behavior-per-event) even though the tool already ran.

797 

798Stderr from a hook that exits 0 goes to the debug log only, never the transcript, and Claude never sees it. To read it yourself, enable [debug logging](#debug-hooks). To surface a warning to Claude from a `PostToolUse` or `PostToolUseFailure` hook, exit 2 instead so [Claude sees the stderr](#exit-code-2-behavior-per-event) even though the tool already ran.

799 819 

800#### Exit code 2820#### Exit code 2

801 821 

802Exit 2 means a blocking error. On [events that can block](#exit-code-2-behavior-per-event), exit 2 blocks whether or not you print JSON: even a JSON `permissionDecision` of `"allow"` can't override it. Claude Code still reads any valid [JSON output](#json-output) on stdout. On `Elicitation` and `ElicitationResult`, an exit-2 hook's `hookSpecificOutput` is ignored.822Exit with code 2 to block the action. On [events that can block](#exit-code-2-behavior-per-event), Claude Code stops the action: a `PreToolUse` hook blocks the tool call, for example, and a `UserPromptSubmit` hook rejects the prompt.

823 

824The message that comes with the block is your hook's stderr. If your hook also printed JSON that makes a blocking decision, Claude Code uses that decision's reason instead.

803 825 

804The blocking message is the reason from your JSON's blocking decision when it makes one, and your stderr text otherwise. What the block does varies by event: `PreToolUse` blocks the tool call, `UserPromptSubmit` rejects the prompt, and so on. [Exit code 2 behavior per event](#exit-code-2-behavior-per-event) lists the effect for every event, and each event's section says where the message goes.826Exit 2 blocks even when your hook prints JSON:

805 827 

806A hook that exits 2 while printing JSON that fails [JSON output](#json-output) schema validation still blocks: Claude Code uses stderr as the blocking reason and records the validation failure in the debug log. Before v2.1.214, Claude Code treated that combination as a non-blocking error and the action proceeded.828* **JSON that passes schema validation**: Claude Code still reads the [JSON output](#json-output) fields, but they can't override the block. Even a `permissionDecision` of `"allow"` doesn't let the action through. On `Elicitation` and `ElicitationResult`, an exit-2 hook's `hookSpecificOutput` is ignored.

829* **JSON that fails schema validation**: the hook still blocks. Claude Code uses your stderr as the blocking reason and records the validation failure in the debug log.

807 830 

808This script blocks `rm` commands by exiting 2 and leaves every other command to the normal permission flow:831This script blocks `rm` commands by exiting 2 and leaves every other command to the normal permission flow:

809 832 


821exit 0 # No decision: the normal permission flow applies844exit 0 # No decision: the normal permission flow applies

822```845```

823 846 

847With this script registered as a `PreToolUse` hook on `Bash`, a command that starts with `rm` is blocked, and Claude receives the hook's stderr as the tool's error, prefixed with the event name, the tool name, and the hook's command:

848 

849```text theme={null}

850PreToolUse:Bash hook error: [${CLAUDE_PROJECT_DIR}/.claude/hooks/no-rm.sh]: Blocked: rm commands are not allowed

851```

852 

824#### Other exit codes853#### Other exit codes

825 854 

826Any other exit code doesn't block on its own for most hook events. What happens depends on your stdout:855When your hook exits with a code other than 0 or 2 and prints plain text or nothing to stdout, the run is a [non-blocking error](#exit-code-output). You see a `<hook name> hook error` notice in the transcript with `Failed with non-blocking status code:` and the first line of your hook's stderr. For example, when a `PreToolUse` hook on `Bash` prints `something broke` to stderr and exits 1, the `PreToolUse:Bash hook error` notice carries this line:

827 856 

828* With a parsed object that passes schema validation, for events that use the standard decision model, Claude Code ignores the exit code and the JSON alone decides the outcome:857```text theme={null}

829 * Each field the event supports is honored, including `permissionDecision`, `additionalContext`, `updatedInput`, and `systemMessage`, and the hook isn't reported as an error.858Failed with non-blocking status code: something broke

830 * [Decision control](#decision-control) lists the decision fields per event; universal fields like `systemMessage` follow the [JSON output](#json-output) table.859```

831* With a parsed object that fails schema validation, for events that use the standard decision model, it's the same non-blocking error as [on exit 0](#exit-code-0): the action proceeds, and the `<hook name> hook error` notice carries the validation message.

832* With stdout that Claude Code [tries to parse as JSON](#exit-code-0) and can't, Claude Code reports the same non-blocking error as on exit 0 for events that use the standard decision model. The action proceeds, and the notice carries the parse message.

833* With stdout that Claude Code [treats as plain text](#exit-code-0), or with empty stdout, it's a non-blocking error for most hook events: the action proceeds, and the transcript shows a `<hook name> hook error` notice followed by the first line of stderr, prefixed with `Failed with non-blocking status code:`. To capture the full stderr, enable [debug logging](#debug-hooks).

834 860 

835Events outside the standard decision model keep their own rows in the [per-event table](#exit-code-2-behavior-per-event): `WorktreeCreate` fails creation on any nonzero exit no matter what your JSON says, and events that discard hook output entirely, like `StopFailure`, ignore your JSON on every exit code, apart from side-effect fields like `terminalSequence`, which still fire.861To capture the full stderr rather than its first line, enable [debug logging](#debug-hooks).

836 862 

837A hook that can't start lands in the same non-blocking bucket. When the script path doesn't exist or isn't executable, the shell exits with a code like 127 and you see the same notice with the interpreter's message, for example `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`. For most hook events, the action proceeds. When you set up a policy hook, watch for this notice on its first run: a mistyped path in `settings.json` leaves the gate silently disabled.863A hook that can't start is a non-blocking error too. In shell form, when the script path doesn't exist or isn't executable, the shell exits with a code like 127 and the notice carries the interpreter's message, for example `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`. When you set up a policy hook, watch for this notice on its first run, because a mistyped path in `settings.json` means the hook never runs. To block the action instead, set [`onFailure: "block"`](#block-the-action-when-a-hook-fails).

838 864 

839<Warning>865<Warning>

840 For most hook events, exit code 2 is the only exit code that blocks through the code alone. Without valid JSON on stdout, Claude Code treats exit code 1 as a non-blocking error and proceeds with the action, even though 1 is the conventional Unix failure code. If your hook is meant to enforce a policy, use `exit 2`. The worktree events differ: any non-zero exit code from `WorktreeCreate` aborts worktree creation, and any non-zero exit code from `WorktreeRemove` makes worktree removal fail if the directory still exists afterward.866 Without valid JSON on stdout, Claude Code treats exit code 1 as a non-blocking error, even though 1 is the conventional Unix failure code. If your hook is meant to enforce a policy, use `exit 2`.

841</Warning>867</Warning>

842 868 

843#### Timeouts869#### Timeouts


846 872 

847On [`PreModelSwitch`](#premodelswitch), a hook canceled at its timeout blocks the model switch. On `PreToolUse`, the two hook families differ:873On [`PreModelSwitch`](#premodelswitch), a hook canceled at its timeout blocks the model switch. On `PreToolUse`, the two hook families differ:

848 874 

849* A timed-out `command`, `http`, or `mcp_tool` hook doesn't block the tool call. The call continues through the normal [permission flow](/docs/en/permissions), so don't count on a stalled hook to act as a gate.875* A timed-out `command`, `http`, or `mcp_tool` hook doesn't block the tool call. The call continues through the normal [permission flow](/docs/en/permissions), so don't count on a stalled hook to act as a gate. To block the call when a `command` or `http` hook times out, set [`onFailure: "block"`](#block-the-action-when-a-hook-fails).

850* An [Agent SDK callback hook](/docs/en/agent-sdk/hooks) that exceeds its timeout [blocks the tool call](#pretooluse).876* An [Agent SDK callback hook](/docs/en/agent-sdk/hooks) that exceeds its timeout [blocks the tool call](#pretooluse).

851 877 

878#### Block the action when a hook fails

879 

880On most events, when a hook fails or times out, Claude Code still carries out the action, so a policy hook with a wrong path or a crashing script lets everything through. To block the action instead, set `"onFailure": "block"` on a `command` or `http` hook. The default value is `"continue"`. Requires Claude Code v2.1.295 or later.

881 

882This `PreToolUse` hook in `.claude/settings.json` runs a project script before each Bash command, and blocks the command if the script fails:

883 

884```json theme={null}

885{

886 "hooks": {

887 "PreToolUse": [

888 {

889 "matcher": "Bash",

890 "hooks": [

891 {

892 "type": "command",

893 "command": "node",

894 "args": ["${CLAUDE_PROJECT_DIR}/.claude/hooks/check-command.js"],

895 "onFailure": "block"

896 }

897 ]

898 }

899 ]

900 }

901}

902```

903 

904To test it, leave `check-command.js` missing and ask Claude to run a Bash command such as `ls`. Claude Code blocks the call, and the error includes `failed; blocking because onFailure is "block"` followed by node's own error output, trimmed here to one line:

905 

906```text theme={null}

907PreToolUse:Bash hook error: [node ${CLAUDE_PROJECT_DIR}/.claude/hooks/check-command.js]: failed; blocking because onFailure is "block"

908Error: Cannot find module '/path/to/project/.claude/hooks/check-command.js'

909```

910 

911After a timeout, the message says `timed out` instead of `failed`. Without `onFailure` set, the same missing script is a non-blocking error and `ls` runs.

912 

913Each of these counts as a failure:

914 

915* **Can't start**: a command hook fails to start, for example because the script or executable doesn't exist

916* **Exit code other than 0 or 2**: counts for a command hook even if it printed JSON that allows the action, such as `permissionDecision: "allow"`. To return a JSON decision, exit 0

917* **HTTP error**: an HTTP hook's connection fails, or the response status isn't 2xx

918* **Timeout**: the hook reaches its [`timeout`](#common-fields)

919* **Invalid output**: the JSON output [can't be parsed](#exit-code-0) or fails [schema validation](#json-output). For an HTTP hook, a 2xx body that is neither empty nor a JSON object also counts. Plain-text stdout from a command hook isn't a failure

920 

921With `"block"` set, a failure does what [exit code 2 does on that event](#exit-code-2-behavior-per-event), except on `PermissionRequest`, where it denies the request. For example, a `PreToolUse` failure blocks the tool call and a `UserPromptSubmit` failure blocks the prompt.

922 

923The field has no effect on these hooks:

924 

925* **`Stop`, `SubagentStop`, `TaskCompleted`, and `TeammateIdle` hooks**: exit code 2 on these events sends Claude back to keep working, and Claude can't repair a hook that won't run

926* **Background command hooks**: command hooks that set [`async` or `asyncRewake`](#run-hooks-in-the-background)

927 

852#### Exit code 2 behavior per event928#### Exit code 2 behavior per event

853 929 

854Exit code 2 is the way a hook signals "stop, don't do this." The effect depends on the event, because some events represent actions that can be blocked (like a tool call that hasn't happened yet) and others represent things that already happened or can't be prevented.930Exit code 2 is the way a hook signals "stop, don't do this." The effect depends on the event, because some events represent actions that can be blocked (like a tool call that hasn't happened yet) and others represent things that already happened or can't be prevented.


902* **Connection failure**: non-blocking error, execution continues978* **Connection failure**: non-blocking error, execution continues

903* **Timeout**: the hook is canceled, as described under [Timeouts](#timeouts)979* **Timeout**: the hook is canceled, as described under [Timeouts](#timeouts)

904 980 

905Unlike command hooks, HTTP hooks can't signal a blocking error through status codes alone. To block a tool call or deny a permission, return a 2xx response with a JSON body containing the appropriate decision fields.981HTTP hooks can't signal a blocking error through the status code alone: a non-2xx status or a failed connection is a [non-blocking error](#exit-code-output). To block a tool call or deny a permission, return a 2xx response with a JSON body containing the appropriate decision fields. To block the action when the request fails or returns a non-2xx status, set [`onFailure: "block"`](#block-the-action-when-a-hook-fails).

906 982 

907### JSON output983### JSON output

908 984 


1337 1413 

1338`UserPromptSubmit` hooks have a default timeout of 30 seconds for `command`, `http`, and `mcp_tool` types, shorter than the 600-second default for those types on most other events. Because this hook runs before every prompt and blocks model processing until it completes, a stuck hook stalls the session. If your hook needs more time, set the `timeout` field in the hook entry.1414`UserPromptSubmit` hooks have a default timeout of 30 seconds for `command`, `http`, and `mcp_tool` types, shorter than the 600-second default for those types on most other events. Because this hook runs before every prompt and blocks model processing until it completes, a stuck hook stalls the session. If your hook needs more time, set the `timeout` field in the hook entry.

1339 1415 

1340Apart from a command hook you run with [`async: true`](#run-hooks-in-the-background), a `UserPromptSubmit` command, HTTP, or MCP tool hook that reaches its timeout is canceled and its output, including any `additionalContext`, is discarded. The prompt still reaches Claude without that context. The transcript shows a notice naming the hook, the timeout that fired, and that the output was discarded.1416Apart from a command hook you run with [`async: true`](#run-hooks-in-the-background), a `UserPromptSubmit` command, HTTP, or MCP tool hook that reaches its timeout is canceled and its output, including any `additionalContext`, is discarded. The prompt still reaches Claude without that context. To block the prompt instead, set [`onFailure: "block"`](#block-the-action-when-a-hook-fails) on a command or HTTP hook. The transcript shows a notice naming the hook, the timeout that fired, and that the output was discarded.

1341 1417 

1342An [Agent SDK callback hook](/docs/en/agent-sdk/hooks) on `UserPromptSubmit` that reaches its timeout blocks the prompt with a message naming the hook and the timeout, because a callback there can be acting as a policy gate that must not fail open. The session continues. Before v2.1.208, a callback timeout on that event ended the turn with an execution error.1418An [Agent SDK callback hook](/docs/en/agent-sdk/hooks) on `UserPromptSubmit` that reaches its timeout blocks the prompt with a message naming the hook and the timeout, because a callback there can be acting as a policy gate that must not fail open. The session continues. Before v2.1.208, a callback timeout on that event ended the turn with an execution error.

1343 1419 


1740| :- | :- | :- | :- |1816| :- | :- | :- | :- |

1741| `url` | string | `"https://example.com/api"` | URL to fetch content from |1817| `url` | string | `"https://example.com/api"` | URL to fetch content from |

1742| `prompt` | string | `"Extract the API endpoints"` | Prompt to run on the fetched content |1818| `prompt` | string | `"Extract the API endpoints"` | Prompt to run on the fetched content |

1819| `offset` | number | `100000` | Optional number of characters to skip from the start of the page. Claude sets it to keep reading a long page. Requires Claude Code v2.1.290 or later |

1743 1820 

1744##### WebSearch1821##### WebSearch

1745 1822 


1974| `message` | For `"deny"` only: tells Claude why the permission was denied |2051| `message` | For `"deny"` only: tells Claude why the permission was denied |

1975| `interrupt` | For `"deny"` only: if `true`, stops Claude |2052| `interrupt` | For `"deny"` only: if `true`, stops Claude |

1976 2053 

1977A hook that exits 2 without a `decision` object leaves the permission flow unchanged, and its stderr is discarded. Only the `decision` object can grant or deny the request.2054A hook that exits 2 without a `decision` object leaves the permission flow unchanged, and its stderr is discarded. To grant or deny the request, return the `decision` object.

1978 2055 

1979```json theme={null}2056```json theme={null}

1980{2057{


2494 2571 

2495#### TaskCreated decision control2572#### TaskCreated decision control

2496 2573 

2497A TaskCreated hook can block the creation in two ways. Either way, Claude Code deletes the task and returns your message to Claude as the tool's error. Claude Code ignores `continue: false` from this event and Claude keeps working.2574A TaskCreated hook can block the creation with exit code 2 or with a JSON decision. Either way, Claude Code deletes the task and returns your message to Claude as the tool's error. Claude Code ignores `continue: false` from this event and Claude keeps working.

2498 2575 

2499* **Exit code 2**: Claude Code returns the stderr text as the message.2576* **Exit code 2**: Claude Code returns the stderr text as the message.

2500* **JSON `{"decision": "block", "reason": "..."}`**: Claude Code returns `reason` as the message.2577* **JSON `{"decision": "block", "reason": "..."}`**: Claude Code returns `reason` as the message.


3309 3386 

3310Claude Code shows the user any `systemMessage` your hook returns regardless of the decision, so a cost-report hook can return `{"systemMessage": "..."}` and exit 0.3387Claude Code shows the user any `systemMessage` your hook returns regardless of the decision, so a cost-report hook can return `{"systemMessage": "..."}` and exit 0.

3311 3388 

3312A PreModelSwitch hook that doesn't respond before its timeout blocks the switch. On [PreToolUse](#timeouts), by contrast, a timed-out command hook lets the tool call continue. The default timeout for this event is 30 seconds. `PreModelSwitch` runs `command`, `http`, and `mcp_tool` hooks only, so the `prompt` and `agent` defaults don't apply.3389A PreModelSwitch hook that doesn't respond before its timeout blocks the switch. For what a timeout does on other events, see [Timeouts](#timeouts). The default timeout for this event is 30 seconds. `PreModelSwitch` runs `command`, `http`, and `mcp_tool` hooks only, so the `prompt` and `agent` defaults don't apply.

3313 3390 

3314A hook that exits with a code other than 0 or 2 and prints no JSON decision doesn't block: Claude Code shows its stderr and applies the switch, as described under [Other exit codes](#other-exit-codes).3391A hook that exits with a code other than 0 or 2 and prints no JSON decision is a non-blocking error, as described under [Other exit codes](#other-exit-codes).

3315 3392 

3316### PostModelSwitch3393### PostModelSwitch

3317 3394 


3975Async hooks have additional constraints compared to synchronous hooks:4052Async hooks have additional constraints compared to synchronous hooks:

3976 4053 

3977* Hook output is delivered on the next conversation turn. If the session is idle, the response waits until the next user interaction. Exception: an `asyncRewake` hook that exits with code 2 wakes Claude immediately even when the session is idle.4054* Hook output is delivered on the next conversation turn. If the session is idle, the response waits until the next user interaction. Exception: an `asyncRewake` hook that exits with code 2 wakes Claude immediately even when the session is idle.

3978* Each execution creates a separate background process. There is no deduplication across multiple firings of the same async hook.4055* Each execution creates a separate background process.

3979 4056 

3980## Security considerations4057## Security considerations

3981 4058 

hooks-guide.md +13 −10

Details

234 234 

235To test the hook, ask Claude to add a line with single-quoted strings to a JavaScript file, then open the file: with Prettier's default settings, the hook rewrites them to double quotes.235To test the hook, ask Claude to add a line with single-quoted strings to a JavaScript file, then open the file: with Prettier's default settings, the hook rewrites them to double quotes.

236 236 

237When the hook succeeds, Claude Code shows nothing in the conversation. To confirm the hook ran, check that the edited file is reformatted, or see [Debug techniques](#debug-techniques).237When the hook succeeds, Claude Code shows nothing in the conversation. To confirm the hook ran, check that the edited file is reformatted, or see [Check what a hook did](#check-what-a-hook-did).

238 238 

239To reformat a specific file however it changes, including when a `Bash` command rewrites it, use a [FileChanged](/docs/en/hooks#filechanged) hook instead.239To reformat a specific file however it changes, including when a `Bash` command rewrites it, use a [FileChanged](/docs/en/hooks#filechanged) hook instead.

240 240 


937}937}

938```938```

939 939 

940The endpoint should return a JSON response body using the same [output format](/docs/en/hooks#json-output) as command hooks. To block a tool call, return a 2xx response with the appropriate `hookSpecificOutput` fields. HTTP status codes alone can't block actions.940Your endpoint responds with a JSON body in the same [output format](/docs/en/hooks#json-output) as command hooks, and Claude Code also checks the response status:

941 

942* **2xx status**: to block a tool call, return the appropriate `hookSpecificOutput` fields in the body.

943* **Any other status, or the request fails**: Claude Code reports a [non-blocking error](/docs/en/hooks#exit-code-output) and lets the action continue. To make a failed endpoint block the action, set [`onFailure: "block"`](/docs/en/hooks#block-the-action-when-a-hook-fails) on the hook.

941 944 

942Header values support environment variable interpolation using `$VAR_NAME` or `${VAR_NAME}` syntax. Only variables listed in the `allowedEnvVars` array are resolved; all other `$VAR` references remain empty.945Header values support environment variable interpolation using `$VAR_NAME` or `${VAR_NAME}` syntax. Only variables listed in the `allowedEnvVars` array are resolved; all other `$VAR` references remain empty.

943 946 


1045 1048 

1046When your hook returns `permissionDecision` or `additionalContext` at the top level instead of inside `hookSpecificOutput`, the JSON still parses, and Claude Code ignores the misplaced fields without reporting an error. To see which fields it ignored, start Claude Code with `claude --debug` and search the [debug log](/docs/en/hooks#debug-hooks) for `Hook JSON output had unrecognized keys`.1049When your hook returns `permissionDecision` or `additionalContext` at the top level instead of inside `hookSpecificOutput`, the JSON still parses, and Claude Code ignores the misplaced fields without reporting an error. To see which fields it ignored, start Claude Code with `claude --debug` and search the [debug log](/docs/en/hooks#debug-hooks) for `Hook JSON output had unrecognized keys`.

1047 1050 

1048### Debug techniques1051### Check what a hook did

1049 1052 

1050Press `Ctrl+O` to open the transcript view to check the outcome of a hook run:1053Press `Ctrl+O` to open the transcript view and look for the hook's outcome:

1051 1054 

1052* **Successful run**: you see nothing, unless the hook's JSON surfaces something, such as `systemMessage` or Stop hook feedback.1055* **Success**: you see nothing, unless the hook's JSON surfaces something, such as `systemMessage` or Stop hook feedback.

1053 * To confirm a hook ran, check for its effect, like a reformatted file, or turn on debug logging as described below and trigger the hook again1056 * To confirm the hook ran, check for its effect, like a reformatted file

1054* **Blocking error**: on most events you see the hook's feedback. When the hook's JSON made a blocking decision, the feedback is the reason from that decision; otherwise it is the hook's stderr. On a few events, such as `ConfigChange` and `Elicitation`, a block surfaces no message.1057* **Blocking error**: on most events you see the message that came with the block, for example `Blocked: rm commands are not allowed`. On a few events, such as `ConfigChange` and `Elicitation`, you see no message. [Exit code 2](/docs/en/hooks#exit-code-2) covers where the message comes from.

1055* **Non-blocking error**: the action proceeded, and you see a `<hook name> hook error` notice with a short explanation, such as the first line of stderr prefixed with `Failed with non-blocking status code:`, or a JSON validation or parse message.1058* **Non-blocking error**: you see a `<hook name> hook error` notice with a short explanation, such as the first line of stderr after `Failed with non-blocking status code:`, or a JSON validation or parse message. The action went ahead.

1056 1059 

1057Which exit-code and JSON combinations produce each outcome, including the per-event exceptions, is defined in the reference's [Exit code output](/docs/en/hooks#exit-code-output) section.1060To look up the outcome for a specific exit code and stdout, including the per-event exceptions, see [Exit code output](/docs/en/hooks#exit-code-output) in the reference.

1058 1061 

1059For full execution details including which hooks matched, their exit codes, stdout, and stderr, read the debug log. Start Claude Code with `claude --debug-file /tmp/claude.log` to write to a known path, then `tail -f /tmp/claude.log` in another terminal. If you started without that flag, run `/debug` mid-session to enable logging and find the log path.1062For full execution details including hook exit codes, stdout, and stderr, read the debug log. Start Claude Code with `claude --debug-file /tmp/claude.log` to write to a known path, then `tail -f /tmp/claude.log` in another terminal. If you started without that flag, run `/debug` mid-session to enable logging and find the log path.

1060 1063 

1061## Learn more1064## Learn more

1062 1065 

Details

188| `^` | First non-blank character |188| `^` | First non-blank character |

189| `gg` | Beginning of input |189| `gg` | Beginning of input |

190| `G` | Beginning of last line |190| `G` | Beginning of last line |

191| `f{char}` | Jump to next occurrence of character |191| `f{char}` | Jump to next occurrence of character on the current line |

192| `F{char}` | Jump to previous occurrence of character |192| `F{char}` | Jump to previous occurrence of character on the current line |

193| `t{char}` | Jump to just before next occurrence of character |193| `t{char}` | Jump to just before next occurrence of character on the current line |

194| `T{char}` | Jump to just after previous occurrence of character |194| `T{char}` | Jump to just after previous occurrence of character on the current line |

195| `;` | Repeat last f/F/t/T motion |195| `;` | Repeat last f/F/t/T motion |

196| `,` | Repeat last f/F/t/T motion in reverse |196| `,` | Repeat last f/F/t/T motion in reverse |

197| `/` | Open reverse history search, same as `Ctrl+R`. The empty search prompt shows a hint: press `Esc` then `i` then `/` to open the command menu instead |197| `/` | Open reverse history search, same as `Ctrl+R`. The empty search prompt shows a hint: press `Esc` then `i` then `/` to open the command menu instead |


209| `dd` | Delete line |209| `dd` | Delete line |

210| `D` | Delete to end of line |210| `D` | Delete to end of line |

211| `dw`/`de`/`db` | Delete word/to end/back |211| `dw`/`de`/`db` | Delete word/to end/back |

212| `df{char}`/`dt{char}` | Delete to and including, or up to, the next occurrence of a character |212| `df{char}`/`dt{char}` | Delete to and including, or up to, the next occurrence of a character on the current line |

213| `dj`/`dk` | Delete the current line and the line below or above |213| `dj`/`dk` | Delete the current line and the line below or above |

214| `dgg`/`dG` | Delete from the current line to the first or last line |214| `dgg`/`dG` | Delete from the current line to the first or last line |

215| `d0`/`c0`/`y0` | Delete, change, or yank from the cursor back to the beginning of the line. Requires Claude Code v2.1.281 or later |215| `d0`/`c0`/`y0` | Delete, change, or yank from the cursor back to the beginning of the line. Requires Claude Code v2.1.281 or later |


763* A bare `#123`763* A bare `#123`

764* A nested GitLab path such as `group/subgroup/project#123`764* A nested GitLab path such as `group/subgroup/project#123`

765* Any reference inside a code span or code block765* Any reference inside a code span or code block

766* Any reference in a reply longer than about 1,000 lines or 100,000 characters

766 767 

767Claude Code builds the link for the host of the repository it identifies from your git remote, not for the repository the reference names:768Claude Code builds the link for the host of the repository it identifies from your git remote, not for the repository the reference names:

768 769 

jetbrains.md +6 −2

Details

47 47 

48## Usage48## Usage

49 49 

50### From your IDE50<span id="from-your-ide" />

51 

52### Run Claude Code from your IDE

51 53 

52Run `claude` from your IDE's integrated terminal, and all integration features will be active.54Run `claude` from your IDE's integrated terminal, and all integration features will be active.

53 55 

54### From external terminals56<span id="from-external-terminals" />

57 

58### Connect from an external terminal

55 59 

56Use the `/ide` command in any external terminal to connect Claude Code to your JetBrains IDE and activate all features:60Use the `/ide` command in any external terminal to connect Claude Code to your JetBrains IDE and activate all features:

57 61 

mcp.md +13 −5

Details

165 165 

166Each is one of the inputs the four options in [Installing MCP servers](#installing-mcp-servers) take. Find the shape you have below to turn it into the command Claude Code accepts. Each command writes to [local scope](#local-scope) unless you add `--scope project` or `--scope user`.166Each is one of the inputs the four options in [Installing MCP servers](#installing-mcp-servers) take. Find the shape you have below to turn it into the command Claude Code accepts. Each command writes to [local scope](#local-scope) unless you add `--scope project` or `--scope user`.

167 167 

168#### From a URL168<span id="from-a-url" />

169 

170#### Add a server from a URL

169 171 

170A URL means the server is remote. For an `https://` endpoint, add it with `--transport http`, or follow [Option 2](#option-2-add-a-remote-sse-server) when the instructions say the endpoint uses SSE. For a `wss://` endpoint, use [Option 4](#option-4-add-a-remote-websocket-server) instead, since `--transport` doesn't accept `ws`:172A URL means the server is remote. For an `https://` endpoint, add it with `--transport http`, or follow [Option 2](#option-2-add-a-remote-sse-server) when the instructions say the endpoint uses SSE. For a `wss://` endpoint, use [Option 4](#option-4-add-a-remote-websocket-server) instead, since `--transport` doesn't accept `ws`:

171 173 


175 177 

176If the instructions also give an API key or token header, pass it with `--header` as shown in [Option 1](#option-1-add-a-remote-http-server).178If the instructions also give an API key or token header, pass it with `--header` as shown in [Option 1](#option-1-add-a-remote-http-server).

177 179 

178#### From an `npx`, `uvx`, or binary command180<span id="from-an-npx-uvx-or-binary-command" />

181 

182#### Add a server from an `npx`, `uvx`, or binary command

179 183 

180A launch command means the server runs as a local stdio process. Put the whole command after `--`, so Claude Code passes flags such as `-y` to the command that starts the server instead of reading them as its own options. Pass any environment variables the instructions ask for with `--env`, after the server name and before `--`:184A launch command means the server runs as a local stdio process. Put the whole command after `--`, so Claude Code passes flags such as `-y` to the command that starts the server instead of reading them as its own options. Pass any environment variables the instructions ask for with `--env`, after the server name and before `--`:

181 185 


185 189 

186[Option 3](#option-3-add-a-local-stdio-server) covers the `--` separator in full.190[Option 3](#option-3-add-a-local-stdio-server) covers the `--` separator in full.

187 191 

188#### From an `mcpServers` JSON block192<span id="from-an-mcpservers-json-block" />

193 

194#### Add a server from an `mcpServers` JSON block

189 195 

190An `mcpServers` block written for another MCP client, such as Claude Desktop, uses the wrapper key and entry shape Claude Code reads. Pass `claude mcp add-json` the object inside `mcpServers`, not the wrapper. Two entries need a repair first:196An `mcpServers` block written for another MCP client, such as Claude Desktop, uses the wrapper key and entry shape Claude Code reads. Pass `claude mcp add-json` the object inside `mcpServers`, not the wrapper. Two entries need a repair first:

191 197 


329 335 

330On v2, Claude Code also:336On v2, Claude Code also:

331 337 

332* Asks HTTP and stdio servers whether they support the newer revision, and uses it with those that do. In sessions where it fetches feature flags, it also asks claude.ai connector servers. It connects to every other server as v1 does.338* Asks HTTP, stdio, and claude.ai connector servers whether they support the newer revision, and uses it with those that do. It connects to every other server as v1 does.

333* Receives `list_changed` notifications from servers on the newer revision over a [stream it holds open](#notification-streams-on-the-v2-runtime).339* Receives `list_changed` notifications from servers on the newer revision over a [stream it holds open](#notification-streams-on-the-v2-runtime).

334* Doesn't register a [channel](#push-messages-with-channels) server that connects on the newer revision, because that revision can't carry channel messages.340* Doesn't register a [channel](#push-messages-with-channels) server that connects on the newer revision, because that revision can't carry channel messages.

335* Fails an [MCP OAuth sign-in](#authenticate-with-remote-mcp-servers) whose authorization response names an unexpected issuer.341* Fails an [MCP OAuth sign-in](#authenticate-with-remote-mcp-servers) whose authorization response names an unexpected issuer.


1437 Tool search isn't supported on Microsoft Foundry [deployments hosted on Azure](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry#hosting-options), which reject it server-side: Claude Code detects the rejection and loads MCP tools upfront for that deployment instead. [`ENABLE_TOOL_SEARCH`](#configure-tool-search) can't override this, since the rejection comes from the deployment itself.1443 Tool search isn't supported on Microsoft Foundry [deployments hosted on Azure](https://platform.claude.com/docs/en/build-with-claude/claude-in-microsoft-foundry#hosting-options), which reject it server-side: Claude Code detects the rejection and loads MCP tools upfront for that deployment instead. [`ENABLE_TOOL_SEARCH`](#configure-tool-search) can't override this, since the rejection comes from the deployment itself.

1438</Note>1444</Note>

1439 1445 

1440### For MCP server authors1446<span id="for-mcp-server-authors" />

1447 

1448### Tool search for MCP server authors

1441 1449 

1442If you're building an MCP server, the server instructions field becomes more useful with tool search enabled. Server instructions help Claude understand when to search for your tools, similar to how [skills](/docs/en/skills) work.1450If you're building an MCP server, the server instructions field becomes more useful with tool search enabled. Server instructions help Claude understand when to search for your tools, similar to how [skills](/docs/en/skills) work.

1443 1451 

Details

559 559 

560In sessions signed in to a [Claude apps gateway](/docs/en/claude-apps-gateway) through `/login`, the CLI stamps exports with the authenticated identity: `user.id` is the IdP subject, `user.email` is the signed-in email, and `user.groups` carries IdP group membership as a comma-separated string. Each export also carries `identity.source: gateway-oidc`. The gateway identity is applied last, so `user.*` and `identity.*` keys set through `OTEL_RESOURCE_ATTRIBUTES` are ignored on those sessions.560In sessions signed in to a [Claude apps gateway](/docs/en/claude-apps-gateway) through `/login`, the CLI stamps exports with the authenticated identity: `user.id` is the IdP subject, `user.email` is the signed-in email, and `user.groups` carries IdP group membership as a comma-separated string. Each export also carries `identity.source: gateway-oidc`. The gateway identity is applied last, so `user.*` and `identity.*` keys set through `OTEL_RESOURCE_ATTRIBUTES` are ignored on those sessions.

561 561 

562<Note>

563 Events that Claude Code logs before a developer signs in don't carry the gateway identity. When Claude Code opens a session signed out of the gateway, for example after [the gateway ends the sign-in](/docs/en/errors#cloud-gateway-session-expired), the startup events logged before sign-in carry the anonymous `user.id` and no `identity.source`. These include [`managed_settings_resolved`](#managed-settings-resolved-event), [`plugin_loaded`](#plugin-loaded-event), and [`mcp_server_connection`](#mcp-server-connection-event).

564</Note>

565 

562For the identity attributes on Claude Desktop and Cowork sessions that connect through a gateway, see the [gateway `telemetry` reference](/docs/en/claude-apps-gateway-config#telemetry).566For the identity attributes on Claude Desktop and Cowork sessions that connect through a gateway, see the [gateway `telemetry` reference](/docs/en/claude-apps-gateway-config#telemetry).

563 567 

564Events additionally include the following attributes. These are never attached to metrics because they would cause unbounded cardinality:568Events additionally include the following attributes. These are never attached to metrics because they would cause unbounded cardinality:


841* `error`: Error message845* `error`: Error message

842* `status_code`: HTTP status code as a number. Absent for non-HTTP errors such as connection failures.846* `status_code`: HTTP status code as a number. Absent for non-HTTP errors such as connection failures.

843* `duration_ms`: Request duration in milliseconds847* `duration_ms`: Request duration in milliseconds

844* `attempt`: Total number of attempts made, including the initial request (`1` means no retries occurred)848* `attempt`: Number of attempts made, including the initial request. [Detect retry exhaustion](#detect-retry-exhaustion) says when the count starts again

845* `request_id`: API request ID, such as `"req_011..."`, described under [Event correlation attributes](#event-correlation-attributes).849* `request_id`: API request ID, such as `"req_011..."`, described under [Event correlation attributes](#event-correlation-attributes).

846* `client_request_id`: Client-generated UUID sent as the `x-client-request-id` request header. Available even when a failure such as a timeout or connection error never produced a server `request_id`; see the [event correlation attributes](#event-correlation-attributes) table for when it's present. Requires Claude Code v2.1.214 or later850* `client_request_id`: Client-generated UUID sent as the `x-client-request-id` request header. Available even when a failure such as a timeout or connection error never produced a server `request_id`; see the [event correlation attributes](#event-correlation-attributes) table for when it's present. Requires Claude Code v2.1.214 or later

847* `speed`: `"fast"` or `"normal"`, indicating whether fast mode was active851* `speed`: `"fast"` or `"normal"`, indicating whether fast mode was active


1090 1094 

1091Logged when Claude Code resolves an `@`-mention in a prompt. Not every mention emits an event: early-exit paths such as permission denials, oversized files, PDF reference attachments, and directory listing failures return without logging.1095Logged when Claude Code resolves an `@`-mention in a prompt. Not every mention emits an event: early-exit paths such as permission denials, oversized files, PDF reference attachments, and directory listing failures return without logging.

1092 1096 

1097Each time Claude Code reads a prompt, it logs at most 100 events with a `mention_type` of `"agent"` and 100 with `"mcp_resource"`. Mentions past either limit still resolve but emit no event.

1098 

1093**Event Name**: `claude_code.at_mention`1099**Event Name**: `claude_code.at_mention`

1094 1100 

1095**Attributes**:1101**Attributes**:


1398 1404 

1399Claude Code retries failed API requests internally and emits a single `claude_code.api_error` event only after it gives up, so the event itself is the terminal signal for that request. Intermediate retry attempts are not logged as separate events.1405Claude Code retries failed API requests internally and emits a single `claude_code.api_error` event only after it gives up, so the event itself is the terminal signal for that request. Intermediate retry attempts are not logged as separate events.

1400 1406 

1401The `attempt` attribute on the event records the total number of attempts. `CLAUDE_CODE_MAX_RETRIES` defaults to 10 and is capped at 15. On v2.1.199 or later, you can set `CLAUDE_CODE_RETRY_WATCHDOG` to raise the default and remove the cap.1407The `attempt` attribute on the event records the number of attempts. `CLAUDE_CODE_MAX_RETRIES` defaults to 10 and is capped at 15. On v2.1.199 or later, you can set `CLAUDE_CODE_RETRY_WATCHDOG` to raise the default and remove the cap.

1402 1408 

1403When the request exhausts all retries on a transient error, `attempt` equals one more than that effective limit: 11 by default, and never more than 16 unless the watchdog is set. A lower value indicates a non-retryable error such as a `400` response, or a cause with its own smaller retry budget. For example, Claude Code retries a failure to load AWS or Google Cloud credentials at most twice.1409When the request exhausts all retries on a transient error, `attempt` is at most one more than that effective limit: 11 by default.

1410 

1411A lower value can still mean the retries ran out: `attempt` starts again from `1` each time Claude Code re-issues the request after a streaming failure.

1404 1412 

1405To distinguish a session that recovered from one that stalled, group events by `session.id` and check whether a later `api_request` event exists after the error.1413To distinguish a session that recovered from one that stalled, group events by `session.id` and check whether a later `api_request` event exists after the error.

1406 1414 


1549 1557 

1550Your choice of metrics, logs, and traces backends determines the types of analyses you can perform:1558Your choice of metrics, logs, and traces backends determines the types of analyses you can perform:

1551 1559 

1552### For metrics1560<span id="for-metrics" />

1561 

1562### Backends for metrics

1553 1563 

1554* **Time series databases**: Rate calculations, aggregated metrics1564* **Time series databases**: Rate calculations, aggregated metrics

1555* **Columnar stores**: Complex queries, unique user analysis1565* **Columnar stores**: Complex queries, unique user analysis

1556* **Full-featured observability platforms**: Advanced querying, visualization, alerting1566* **Full-featured observability platforms**: Advanced querying, visualization, alerting

1557 1567 

1558### For events/logs1568<span id="for-events/logs" />

1569 

1570### Backends for events and logs

1559 1571 

1560* **Log aggregation systems**: Full-text search, log analysis1572* **Log aggregation systems**: Full-text search, log analysis

1561* **Columnar stores**: Structured event analysis1573* **Columnar stores**: Structured event analysis

1562* **Full-featured observability platforms**: Correlation between metrics and events1574* **Full-featured observability platforms**: Correlation between metrics and events

1563 1575 

1564### For traces1576<span id="for-traces" />

1577 

1578### Backends for traces

1565 1579 

1566Choose a backend that supports distributed trace storage and span correlation:1580Choose a backend that supports distributed trace storage and span correlation:

1567 1581 

Details

177 177 

178You can load a plugin for a single session in three ways: from a directory or `.zip` archive on disk with `--plugin-dir`, from a URL with `--plugin-url`, or from an environment variable when you can't add a flag. Each plugin loads for that session only, and nothing is written to your settings for it. When you edit the plugin's files during the session, run `/reload-plugins` to load the changes.178You can load a plugin for a single session in three ways: from a directory or `.zip` archive on disk with `--plugin-dir`, from a URL with `--plugin-url`, or from an environment variable when you can't add a flag. Each plugin loads for that session only, and nothing is written to your settings for it. When you edit the plugin's files during the session, run `/reload-plugins` to load the changes.

179 179 

180#### From a directory or `.zip`180<span id="from-a-directory-or-zip" />

181 

182#### Load a plugin from a directory or `.zip`

181 183 

182When you start `claude` from your shell, pass `--plugin-dir` with the plugin's root directory or a `.zip` archive of it. Repeat the flag to load several plugins:184When you start `claude` from your shell, pass `--plugin-dir` with the plugin's root directory or a `.zip` archive of it. Repeat the flag to load several plugins:

183 185 


185claude --plugin-dir ./my-first-plugin --plugin-dir ./other-plugin.zip187claude --plugin-dir ./my-first-plugin --plugin-dir ./other-plugin.zip

186```188```

187 189 

188<h4 id="load-a-folder-of-plugins">190#### Load a folder of plugins

189 From a folder of plugins

190</h4>

191 191 

192To load several plugins from one place, pass a folder that holds them, such as `--plugin-dir ./plugins`. Loading a folder of plugins requires Claude Code v2.1.265 or later.192To load several plugins from one place, pass a folder that holds them, such as `--plugin-dir ./plugins`. Loading a folder of plugins requires Claude Code v2.1.265 or later.

193 193 


202 202 

203A message appears in the session for each of these changes. If loading or unloading a plugin mid-conversation would [invalidate the prompt cache](/docs/en/prompt-caching#enabling-or-disabling-a-plugin), the change is held instead, and the message tells you to run `/reload-plugins` to apply it.203A message appears in the session for each of these changes. If loading or unloading a plugin mid-conversation would [invalidate the prompt cache](/docs/en/prompt-caching#enabling-or-disabling-a-plugin), the change is held instead, and the message tells you to run `/reload-plugins` to apply it.

204 204 

205<h4 id="fetch-an-archive-from-a-url-for-one-session">205<span id="fetch-an-archive-from-a-url-for-one-session" />

206 From a URL206 

207</h4>207#### Load a plugin from a URL

208 208 

209When you start `claude` from your shell, pass `--plugin-url` with the address of a `.zip` archive, such as a build artifact your CI publishes:209When you start `claude` from your shell, pass `--plugin-url` with the address of a `.zip` archive, such as a build artifact your CI publishes:

210 210 


218 218 

219If Claude Code can't fetch the archive, or the archive is invalid, it starts without the plugin and records a plugin load error that you can review in the `/plugin` manager's **Errors** tab.219If Claude Code can't fetch the archive, or the archive is invalid, it starts without the plugin and records a plugin load error that you can review in the `/plugin` manager's **Errors** tab.

220 220 

221#### From an environment variable221<span id="from-an-environment-variable" />

222 

223#### Load plugins from an environment variable

222 224 

223To load plugins in a session where you can't add the `--plugin-dir` flag, list their absolute paths in the [`CLAUDE_CODE_PLUGIN_DIRS`](/docs/en/env-vars#variables) environment variable instead. Claude Code loads each path as it loads a `--plugin-dir` path. These plugins load in addition to any you pass with `--plugin-dir`. [Project and local settings can't set this variable](/docs/en/settings-reference#variables-claude-code-ignores-in-env). `CLAUDE_CODE_PLUGIN_DIRS` requires Claude Code v2.1.280 or later.225To load plugins in a session where you can't add the `--plugin-dir` flag, list their absolute paths in the [`CLAUDE_CODE_PLUGIN_DIRS`](/docs/en/env-vars#variables) environment variable instead. Claude Code loads each path as it loads a `--plugin-dir` path. These plugins load in addition to any you pass with `--plugin-dir`. [Project and local settings can't set this variable](/docs/en/settings-reference#variables-claude-code-ignores-in-env). `CLAUDE_CODE_PLUGIN_DIRS` requires Claude Code v2.1.280 or later.

224 226 

Details

361 361 

362### How users accept a headersHelper command362### How users accept a headersHelper command

363 363 

364A user accepts a plugin entry's command each time they install or update that one plugin by itself. They do that from the plugin's own view in `/plugin`, or with `claude plugin install` or `claude plugin update`. Claude Code shows the command and the archive URL, and runs the command only after the user accepts.364A user accepts a plugin entry's command each time they install or update that one plugin by itself. Claude Code shows the command and the archive URL, and runs the command only after the user accepts.

365 

366Users can install or update the plugin inside a Claude Code session in a terminal, in their shell with no session running, or in the VS Code extension:

367 

368* **Terminal session**: from the plugin's own view in `/plugin`.

369* **Shell**: with `claude plugin install` or `claude plugin update`.

370* **VS Code extension**: from the [**Manage plugins** dialog](/docs/en/vs-code#manage-plugins), with version 2.1.290 or later of the extension.

365 371 

366In a non-interactive shell, pass [`--yes`](/docs/en/plugins/cli-reference#plugin-install) to accept the command. To accept only the command that a previous `--json` run displayed, pass [`--accept-command`](/docs/en/plugins/cli-reference#plugin-install) with the `sha256` the run reported.372In a non-interactive shell, pass [`--yes`](/docs/en/plugins/cli-reference#plugin-install) to accept the command. To accept only the command that a previous `--json` run displayed, pass [`--accept-command`](/docs/en/plugins/cli-reference#plugin-install) with the `sha256` the run reported.

367 373 

368Claude Code runs only the command it showed, for the archive URL it showed. If the entry's command or archive URL changed in between, Claude Code refuses the install or update. A change in the query string alone doesn't count.374Claude Code runs only the command it showed, for the archive URL it showed. If the entry's command or archive URL changed in between, Claude Code refuses the install or update. A change in the query string alone doesn't count, except in the VS Code extension or with `--accept-command`.

369 375 

370<h3 id="installs-and-updates-that-refuse-the-command-instead-of-asking">376<h3 id="installs-and-updates-that-refuse-the-command-instead-of-asking">

371 Installs and updates that refuse a command instead of asking377 Installs and updates that refuse a command instead of asking

Details

244 244 

245The shell command adds the marketplace without a confirmation step. A marketplace you've already added from that source is reused. A new one is added under the same [organization policy checks](/docs/en/plugins/org#restrict-what-users-can-install) as `claude plugin marketplace add`, and is declared in your user settings even when you pass `--scope project`.245The shell command adds the marketplace without a confirmation step. A marketplace you've already added from that source is reused. A new one is added under the same [organization policy checks](/docs/en/plugins/org#restrict-what-users-can-install) as `claude plugin marketplace add`, and is declared in your user settings even when you pass `--scope project`.

246 246 

247If you haven't added that marketplace yet, the command prints `Successfully added marketplace: <name> (declared in user settings)` and then [installs the plugin](#install-from-your-shell).

248 

247### Add a private marketplace249### Add a private marketplace

248 250 

249A private marketplace is one in a repository you need credentials to clone, on GitHub or any other git host. You add it with the same `/plugin marketplace add` or `claude plugin marketplace add` command as a public one. Claude Code clones it with the git credentials already on your machine and never prompts, so each way of connecting has a requirement:251A private marketplace is one in a repository you need credentials to clone, on GitHub or any other git host. You add it with the same `/plugin marketplace add` or `claude plugin marketplace add` command as a public one. Claude Code clones it with the git credentials already on your machine and never prompts, so each way of connecting has a requirement:

Details

175| Puts `official` beside `claude` or `anthropic`, such as `official-claude-tools` | Error |175| Puts `official` beside `claude` or `anthropic`, such as `official-claude-tools` | Error |

176| Has `claude`, `anthropic`, or `anthropics` as a whole word anywhere else, such as `mcp-for-claude` | Warning |176| Has `claude`, `anthropic`, or `anthropics` as a whole word anywhere else, such as `mcp-for-claude` | Warning |

177 177 

178The error reads `Plugin name "<name>" is reserved: it passes as one of Anthropic's own`, and the warning reads `Plugin name "<name>" reads as one of Anthropic's own`. `claude plugin init` and `claude plugin tag` refuse a name that draws the error. Only these commands check the name. Claude Code still installs and loads a plugin whose name they refuse.178The error reads `Plugin name "<name>" is reserved: it passes as one of Anthropic's own`, and the warning reads `Plugin name "<name>" reads as one of Anthropic's own`. `claude plugin init` and `claude plugin tag` refuse a name that draws the error. Claude Code still installs and loads a plugin whose name they refuse.

179 179 

180### `displayName`180### `displayName`

181 181 

Details

58 58 

59| Field | Type | Description |59| Field | Type | Description |

60| :- | :- | :- |60| :- | :- | :- |

61| `name` | string | Marketplace identifier: letters, digits, `.`, `_`, and `-`, starting with a letter or digit, and no `..`. `claude plugin validate` fails any other name, because Claude Code can't install plugins from a marketplace that uses one. Users type the name after `@` in a [plugin id](/docs/en/plugins/loading#find-where-a-plugin-came-from) such as `my-plugin@my-marketplace` when they install a plugin. See [Reserved names](#reserved-names) |61| `name` | string | Marketplace identifier: letters, digits, `.`, `_`, and `-`, starting with a letter or digit, and no `..`. `claude plugin validate` fails any other name, because Claude Code [can't install plugins from a marketplace that uses one](/docs/en/plugins/troubleshooting#cannot-install-plugins-from-a-marketplace-with-this-name). Users type the name after `@` in a [plugin id](/docs/en/plugins/loading#find-where-a-plugin-came-from) such as `my-plugin@my-marketplace` when they install a plugin. See [Reserved names](#reserved-names) |

62| `owner` | object | Maintainer information. `name` is required; `email` and `url` are optional |62| `owner` | object | Maintainer information. `name` is required; `email` and `url` are optional |

63| `plugins` | array | [Plugin entries](#plugin-entries). Each entry is validated on its own, so one invalid entry doesn't fail the marketplace |63| `plugins` | array | [Plugin entries](#plugin-entries). Each entry is validated on its own, so one invalid entry doesn't fail the marketplace |

64| `$schema` | string | JSON Schema URL for editor autocomplete. Ignored at load time |64| `$schema` | string | JSON Schema URL for editor autocomplete. Ignored at load time |

Details

128| `$.mcp.call` | Calls a tool on a connected MCP server, under the session's permission rules |128| `$.mcp.call` | Calls a tool on a connected MCP server, under the session's permission rules |

129| `$.model.complete` | Uses the user's plan or API key for model calls |129| `$.model.complete` | Uses the user's plan or API key for model calls |

130| `$.prompt.submit` | Submits a prompt, and can send it as the user's own words |130| `$.prompt.submit` | Submits a prompt, and can send it as the user's own words |

131| `$.session.send` | Sends a message that another session's or subagent's Claude reads |131| `$.session.send` | Sends a message that another session's, subagent's, or [teammate's](/docs/en/agent-teams) Claude reads |

132 132 

133In the `hooks:` line, [`tool.call`](/docs/en/plugins/mods/reference#tools) and [`prompt.submit`](/docs/en/plugins/mods/reference#prompts-and-what-claude-reads) mean the mod sees every tool call and every prompt, and can change them. [`session.append`](/docs/en/plugins/mods/reference#session) means the mod can rewrite each row of the conversation before it's stored. [`ui.render{component=AskUserQuestion}`](/docs/en/plugins/mods/interface#change-what-claude-code-already-draws) means the mod can redraw the dialog Claude uses to ask the user a question. `tool.check` means the mod can approve or deny a tool call before a permission prompt appears. [Know what happens by default](#know-what-happens-by-default) lists which of your rules and hooks take precedence over its answer.133In the `hooks:` line, [`tool.call`](/docs/en/plugins/mods/reference#tools) and [`prompt.submit`](/docs/en/plugins/mods/reference#prompts-and-what-claude-reads) mean the mod sees every tool call and every prompt, and can change them. [`session.append`](/docs/en/plugins/mods/reference#session) means the mod can rewrite each row of the conversation before it's stored. [`ui.render{component=AskUserQuestion}`](/docs/en/plugins/mods/interface#change-what-claude-code-already-draws) means the mod can redraw the dialog Claude uses to ask the user a question. `tool.check` means the mod can approve or deny a tool call before a permission prompt appears. [Know what happens by default](#know-what-happens-by-default) lists which of your rules and hooks take precedence over its answer.

134 134 

Details

71 71 

72## Call a model72## Call a model

73 73 

74A mod can ask a model a question of its own, outside the conversation, for a small job such as sorting or summarizing a piece of text. `$.model.complete` sends one prompt to a model with your session's credentials and resolves to the reply. It has no conversation history.74A mod can send its own requests to a model for a small job such as classifying or summarizing text. `$.model.complete` sends your prompt on its own, and `$.model.fork({ prompt })` sends the current conversation with your prompt at the end.

75 

76This table compares what each request contains:

77 

78| In the request | `$.model.complete` | `$.model.fork` |

79| :- | :- | :- |

80| Model | The `model` you pass | The session's model |

81| System prompt | A short [attribution block](/docs/en/llm-gateway-protocol#system-prompt-attribution-block), then your `system` if you pass one | The session's system prompt |

82| Messages | One user message, your `prompt` | The conversation so far, then your `prompt` as a user message |

83| CLAUDE.md and other project context | Not included | Included, as in the conversation's last request |

84| Tools | None | Claude's tools, which the model can't call |

85 

86A fork repeats the conversation's last request, so the Claude API serves most of it from the [prompt cache](/docs/en/prompt-caching) while the conversation is still cached.

87 

88Both calls use the session's credentials, so they bill to the user's plan, API key, or cloud provider. [The types for your build](/docs/en/plugins/mods/create#get-the-types-for-your-build) document every `$.model` method.

89 

90### Send one prompt

91 

92Pass `model` and `prompt` to `$.model.complete`. `prompt` becomes the user message. To give the model instructions, such as a role or an output format, also pass `system`, which becomes the system prompt.

75 93 

76This hook answers a `/triage` command, [registered as a command](#add-a-command), by asking a small model to label the text typed after it:94This hook answers a `/triage` command, [registered as a command](#add-a-command), by asking a small model to label the text typed after it:

77 95 


92})110})

93```111```

94 112 

95When you run `/triage the export button does nothing`, the mod sends that text to the model and prints its answer, such as `Label: bug`. Claude's conversation isn't part of the request. When the model doesn't answer, the label is `unknown`.113When you run `/triage the export button does nothing`, the mod sends that text to the model and prints its answer, such as `Label: bug`. When the model doesn't answer, the label is `unknown`.

114 

115A Claude API failure doesn't reject the call, so check `r.isAnswered`, and read `r.reason` when it's `false`. The call rejects for a request Claude Code won't send, such as a model your organization blocks.

116 

117[The types for your build](/docs/en/plugins/mods/create#get-the-types-for-your-build) list the other options, such as `effort`, and the [limits](/docs/en/plugins/mods/reference#limits) give the `maxTokens` default.

118 

119### Use prompt caching

96 120 

97A Claude API failure doesn't reject the call, so check `r.isAnswered`, and read `r.reason` when it's `false`. The call rejects for a request Claude Code won't send, such as a model your organization blocks. [The types for your build](/docs/en/plugins/mods/create#get-the-types-for-your-build) list the other options, such as `effort`, and the [limits](/docs/en/plugins/mods/reference#limits) give the `maxTokens` default.121`$.model.complete` supports the Claude API's [prompt caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching). The API caches the start of a request, called the prefix, up to a [cache breakpoint](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#explicit-cache-breakpoints) that you set. When every call starts with the same long static content, such as instructions or reference material, set a breakpoint at the end of that content. Later calls then read it from the cache instead of paying the full input price for it.

98 122 

99`$.model.fork({ prompt })` asks one question over the current conversation instead, with the same model and system prompt, so the Claude API serves most of it from the prompt cache.123To set a breakpoint, pass `prompt` as an array of `{ text }` blocks instead of a string, and add `cache: true` to the last block of the static content. Claude Code sends that block with the API's `cache_control` field. `system` takes the same array form. To decide between them, see [Choose between `prompt` and `system`](#choose-between-prompt-and-system).

100 124 

101These calls use the user's plan or API key.125<Note>

126 Arrays of blocks require Claude Code v2.1.292 or later. Earlier versions reject an array in `prompt` with an error that ends with `takes { model, prompt } (host check)`, and they leave an array in `system` out of the request.

127</Note>

128 

129This version of the [`/triage` hook](#send-one-prompt) sends a long set of labeling rules before the text to label, with a breakpoint after the rules. `RULES` is a string of your own:

130 

131```javascript theme={null}

132on('command.run', { command: 'triage' }, async ($, e) => {

133 const r = await $.model.complete({

134 model: 'haiku',

135 prompt: [

136 // Identical on every call, so it forms the cached prefix

137 { text: RULES, cache: true },

138 // Changes on every call, so it goes after the breakpoint

139 { text: e.args },

140 ],

141 })

142 return { text: 'Label: ' + (r.isAnswered ? r.text.trim() : 'unknown') }

143})

144```

145 

146The TTL and the number of breakpoints have these limits:

147 

148* **TTL**: a cache entry lasts five minutes after its last use. The TTL comes from the user's Claude Code settings, not from the call. For one hour, set [`subagentPromptCacheTtl`](/docs/en/prompt-caching#choose-the-ttl-yourself) to `1h`.

149* **Breakpoints per request**: the API accepts [up to four](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#when-to-use-multiple-breakpoints), and one more comes back as an `api-error` in `r.reason`

150 

151#### Choose between `prompt` and `system`

152 

153Put the static content that your calls share at the start of `prompt` unless you know that your requests go directly to the Claude API:

154 

155* **Directly to the Claude API, with an API key or a Claude subscription**: either field works

156* **Through [Amazon Bedrock](/docs/en/amazon-bedrock), [Claude Platform on AWS](/docs/en/claude-platform-on-aws), [Google Cloud's Agent Platform](/docs/en/google-vertex-ai), [Microsoft Foundry](/docs/en/microsoft-foundry), or an [LLM gateway](/docs/en/llm-gateway)**: use `prompt`. Claude Code begins the system prompt with an [attribution block](/docs/en/llm-gateway-protocol#system-prompt-attribution-block) whose fingerprint comes from the start of the user message. The `api.anthropic.com` endpoint strips that block before caching. Other endpoints receive it as part of the prompt, so a breakpoint in `system` can miss when `prompt` starts differently.

157* **In a mod that other people run**: use `prompt`, because you don't choose their provider

158 

159`system` comes before `prompt` in the prefix, so a breakpoint in `prompt` covers `system` too, and a call with a different `system` misses the cache.

160 

161#### Check for cache hits

162 

163The result of `$.model.complete` has a `usage` object with the API's [cache fields](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#tracking-cache-performance). `usage.cache_creation_input_tokens` counts the tokens the call wrote to the cache, and `usage.cache_read_input_tokens` counts the tokens it read from the cache. Expect a write on the first call and reads on later calls within the TTL.

164 

165If every call writes and none reads, the prefix differs between calls or the calls are further apart than the TTL. For a prefix that differs, see [Choose between `prompt` and `system`](#choose-between-prompt-and-system).

166 

167If both fields stay at zero on calls the model answered, nothing was cached. Check for each of these causes:

168 

169* **The prefix is too short**: the API doesn't cache a prefix under the model's [minimum length](https://platform.claude.com/docs/en/build-with-claude/prompt-caching#cache-limitations), and it returns no error

170* **Prompt caching is disabled**: when a [`DISABLE_PROMPT_CACHING` variable](/docs/en/prompt-caching#disable-prompt-caching) applies to the model, Claude Code removes the breakpoints and sends the text uncached

171* **Your gateway strips `cache_control`**: a gateway can [remove the field and still return success](/docs/en/prompt-caching#where-the-cache-lives)

172* **Another mod rewrites the start of the text**: Claude Code then [sends it without breakpoints](#what-a-model-complete-hook-receives)

173 

174### What a `model.complete` hook receives

175 

176If you hook the [`model.complete`](/docs/en/plugins/mods/reference#mods-api-calls) event to inspect or change other mods' requests, read the text from these fields:

177 

178* **`e.prompt`**: always a string. When the caller passed an array, it's the blocks' text concatenated in order.

179* **`e.system`**: a string built the same way, or absent when the caller passed no `system`

180* **`e.promptBlocks` and `e.systemBlocks`**: the caller's arrays, each present when the caller passed an array for that field

181 

182Claude Code sends the strings your hook passes to `next` and uses the arrays you pass with them to place [cache breakpoints](#use-prompt-caching). It keeps the leading blocks that still match the start of the string, with their breakpoints, and sends the rest of the string with no breakpoint. For example, `next({ ...e, prompt: e.prompt + NOTE })` keeps the caller's breakpoints, and a hook that changes the start of `prompt` removes them.

102 183 

103## Run work in the background184## Run work in the background

104 185 


128| Call | What the user sees |209| Call | What the user sees |

129| :- | :- |210| :- | :- |

130| `$.ui.status(text)` | One line under the prompt that stays until you change it. It starts with `⚠` and the mod's name, as in `⚠ my-mod: checks: 3 passing`. |211| `$.ui.status(text)` | One line under the prompt that stays until you change it. It starts with `⚠` and the mod's name, as in `⚠ my-mod: checks: 3 passing`. |

131| `$.ui.toast(text)` | A toast notification at the top right, with the mod's name above the text, that disappears after a few seconds |212| `$.ui.toast(text)` | A toast notification with the mod's name that disappears after a few seconds. It's a box at the top right in [fullscreen rendering](/docs/en/fullscreen), and one line at the right under the prompt in the classic renderer. |

132| `$.ui.log(text)` | A dim line in the transcript that Claude doesn't read. It starts with `●` and the mod's name, as in `● my-mod: build finished`. |213| `$.ui.log(text)` | A dim line in the transcript that Claude doesn't read. It starts with `●` and the mod's name, as in `● my-mod: build finished`. |

133 214 

134### Start a turn from a background job215### Start a turn from a background job


141 222 

142## Send and receive messages between sessions223## Send and receive messages between sessions

143 224 

144A mod can send a plain-text message to another of your sessions or to one of this session's subagents, and observe the messages that arrive and leave. `$.session.send({ to, text })` sends one, the same delivery the SendMessage tool makes. `to` is `{ sessionId }` for a session, `{ agentId }` for a subagent from `$.agent.list()`, or the string address a received message came from. The call resolves once the message is queued, with `{ isDelivered: true }`. When nothing was delivered it resolves with `{ isDelivered: false, reason }`, and `reason` says why.225A mod can send a plain-text message to another of your sessions, to one of this session's subagents, or to a teammate in its [agent team](/docs/en/agent-teams). It can also observe the messages that arrive and leave.

226 

227To send one, call `$.session.send({ to, text })`, which makes the same delivery the SendMessage tool makes. Set `to` by who receives the message:

228 

229* **Another of your sessions**: `{ sessionId }`

230* **A subagent or teammate**: `{ agentId }`, with an id from `$.agent.list()`

231* **The sender of a message you received**: the string address that message came from

232 

233The call resolves once the message is queued, with `{ isDelivered: true }`. When nothing was delivered, it resolves with `{ isDelivered: false, reason }`, and `reason` says why.

145 234 

146This hook answers a `/ping` command, [registered as a command](#add-a-command), by asking the session whose id you type after it for a status:235This hook answers a `/ping` command, [registered as a command](#add-a-command), by asking the session whose id you type after it for a status:

147 236 

Details

269 Get type definitions for your version269 Get type definitions for your version

270</h3>270</h3>

271 271 

272Each time Claude Code loads or reloads a mod from a directory you pass to `--plugin-dir`, or a mod [Claude wrote for you](#ask-claude-for-a-mod), it writes TypeScript declaration files, ending in `.d.ts`, into `.claude-plugin/types/` inside the mod's directory. They describe the exact events, mods API methods, and elements in the Claude Code version you're running, so your editor can autocomplete and type-check your hooks. To browse the declarations online, read [`mods/types/claude-code.d.ts`](https://github.com/anthropics/claude-code/blob/main/mods/types/claude-code.d.ts) in the Claude Code repository, whose first line names the version that wrote it. The directory holds these files:272When Claude Code loads a mod from `--plugin-dir` in an interactive session, or a mod [Claude wrote for you](#ask-claude-for-a-mod), it writes TypeScript declaration files into the mod's `.claude-plugin/types/` directory. They describe the exact events, mods API methods, and elements in the Claude Code version you're running, so your editor can autocomplete and type-check your hooks. The directory holds these files:

273 273 

274| Path | What it declares |274| Path | What it declares |

275| :- | :- |275| :- | :- |

Details

131 131 

132After Claude edits or writes an `.mdx` file, a dim line in the transcript names the file. Nothing is logged for another kind of file, or for a call that was refused or failed. Claude's view of the call doesn't change, because the hook returns the result it received.132After Claude edits or writes an `.mdx` file, a dim line in the transcript names the file. Nothing is logged for another kind of file, or for a call that was refused or failed. Claude's view of the call doesn't change, because the hook returns the result it received.

133 133 

134To change a call, pass changed arguments to `next`. To retry a call, call `next(e)` again: a hook that sees `isError` on the first result can run the tool a second time and return that result. To answer a call yourself, return an object with a `result` field, such as `{ result: 'Skipped by my-mod' }`, without calling `next`. When you do that, no permission prompt appears and the tool doesn't run, so the result you return is all Claude learns about what happened.134Your hook can also change a call, retry it, answer it itself, or withhold its result:

135 

136* **Change the call**: pass changed arguments to `next`.

137* **Retry the call**: call `next(e)` again. A hook that sees `isError` on the first result can run the tool a second time and return that result.

138* **Answer the call yourself**: return an object with a `result` field, without calling `next`, and for a built-in tool, give `result` the shape that tool's own result has in [the types for your build](/docs/en/plugins/mods/create#get-the-types-for-your-build). No permission prompt appears and the tool doesn't run, so the result you return is all Claude learns about what happened.

139* **Withhold the result from Claude**: return `{ deny: reason }` after `await next(e)`. Claude reads your reason in place of what `next` returned. When the tool ran, the deny keeps its result from Claude and undoes nothing the tool did. When the tool ran and succeeded, the reason follows a note such as `Bash ran, and a plugin withheld its result:`.

135 140 

136Hooks in your organization's [managed settings](/docs/en/server-managed-settings) run before any mod's `tool.call` hook, and a block from one of them is final.141Hooks in your organization's [managed settings](/docs/en/server-managed-settings) run before any mod's `tool.call` hook, and a block from one of them is final.

137 142 


205 210 

206| To do this | Return this |211| To do this | Return this |

207| :- | :- |212| :- | :- |

208| Rewrite the prompt. The message in the transcript shows the new text. | `next({ ...e, text: newText })` |213| Rewrite the prompt. The transcript and your [prompt history](/docs/en/interactive-mode#command-history) show the new text. | `next({ ...e, text: newText })` |

209| Add text only Claude reads, after the prompt | `next({ ...e, context: [...(e.context ?? []), extraText] })` |214| Add text only Claude reads, after the prompt | `next({ ...e, context: [...(e.context ?? []), extraText] })` |

210| Stop the prompt from being sent | `{ drop: 'the reason' }` |215| Stop the prompt from being sent | `{ drop: 'the reason' }` |

211 216 


225 230 

226When you send a prompt such as `open a PR for this change`, your message looks the same in the transcript, and Claude also reads a line such as `Current branch: feature/auth` after it. A prompt that doesn't mention a pull request goes through unchanged, and `git` doesn't run.231When you send a prompt such as `open a PR for this change`, your message looks the same in the transcript, and Claude also reads a line such as `Current branch: feature/auth` after it. A prompt that doesn't mention a pull request goes through unchanged, and `git` doesn't run.

227 232 

228To stop a prompt, return `{ drop: 'the reason' }` without calling `next`. If your hook returns a `drop` after its `next(e)` call let the prompt through, the turn still runs, and the hook [fails](#handle-a-hook-that-fails) with a message that includes `a drop after its next() was answered`.233To stop a prompt, return `{ drop: 'the reason' }` without calling `next`. The text goes back into the user's prompt input, and they see `Prompt dropped by a hook:` followed by your reason, so address the reason to them. If your hook returns a `drop` after its `next(e)` call let the prompt through, the turn still runs, and the hook [fails](#handle-a-hook-that-fails) with a message that includes `a drop after its next() was answered`.

229 234 

230[Other events](/docs/en/plugins/mods/reference#prompts-and-what-claude-reads) cover the rest of what Claude reads: `prompt.section` for each section of the system prompt, `prompt.context` for the context sent with the first message, and `skill.prompt` for a skill's text. Text from these hooks that changes between requests [invalidates the prompt cache](/docs/en/prompt-caching).235[Other events](/docs/en/plugins/mods/reference#prompts-and-what-claude-reads) cover the rest of what Claude reads: `prompt.section` for each section of the system prompt, `prompt.context` for the context sent with the first message, and `skill.prompt` for a skill's text. Text from these hooks that changes between requests [invalidates the prompt cache](/docs/en/prompt-caching).

231 236 


259 264 

260`result.usage` holds the token counts the Claude API reports for a request, plus the `model` that answered: `input_tokens`, `output_tokens`, `cache_read_input_tokens`, and `cache_creation_input_tokens`. The hook runs for subagents' requests too, so check `e.agentId` when you want only the main conversation.265`result.usage` holds the token counts the Claude API reports for a request, plus the `model` that answered: `input_tokens`, `output_tokens`, `cache_read_input_tokens`, and `cache_creation_input_tokens`. The hook runs for subagents' requests too, so check `e.agentId` when you want only the main conversation.

261 266 

267To see the tool calls that the API ran itself during the request, such as calls to the [advisor tool](/docs/en/advisor), read `result.serverToolUses`. Claude Code doesn't run these calls, so no `tool.call` or `tool.check` hook fires for them. The field is absent when the response has no such calls, and it requires Claude Code v2.1.290 or later.

268 

262<h3 id="hook-the-settings-hook-events">269<h3 id="hook-the-settings-hook-events">

263 Handle the settings hook events270 Handle the settings hook events

264</h3>271</h3>


339* **`tool.check`**: return `{ decision: 'deny', reason: 'the reason' }`346* **`tool.check`**: return `{ decision: 'deny', reason: 'the reason' }`

340* **`plugin.register`**: return `{ refuse: 'the reason' }`, as [Refuse mods when your check fails](/docs/en/plugins/mods/admin#refuse-mods-when-your-check-fails) shows347* **`plugin.register`**: return `{ refuse: 'the reason' }`, as [Refuse mods when your check fails](/docs/en/plugins/mods/admin#refuse-mods-when-your-check-fails) shows

341 348 

349At `tool.call`, a `deny` returned after `next` resolved [withholds the result from Claude](#guard-or-change-a-tool-call).

350 

342## Next steps351## Next steps

343 352 

344* [Use the mods API](/docs/en/plugins/mods/api): add commands and tools, call a model, and run work on a timer353* [Use the mods API](/docs/en/plugins/mods/api): add commands and tools, call a model, and run work on a timer

Details

10 10 

11This map shows where a mod can draw in a terminal session:11This map shows where a mod can draw in a terminal session:

12 12 

13<img src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-screen-map.svg?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=5fda26b6609c62b68c6f9e528c1590ea" className="dark:hidden" alt="Map of a Claude Code terminal session. A mod can add a pane as a sidebar on the right, a toast at the top right of the transcript, a log line in the transcript, a band above the prompt, and a status line under the prompt. A mod can redraw messages, tool call rows, and the spinner. The prompt is Claude Code's own." width="600" height="336" data-path="images/mods-screen-map.svg" />13<img src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-screen-map.svg?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=5fda26b6609c62b68c6f9e528c1590ea" className="dark:hidden" alt="Map of a Claude Code terminal session in fullscreen rendering. A mod can add a pane as a sidebar on the right, a toast at the top right of the transcript, a log line in the transcript, a band above the prompt, and a status line under the prompt. A mod can redraw messages, tool call rows, and the spinner. The prompt is Claude Code's own." width="600" height="336" data-path="images/mods-screen-map.svg" />

14 14 

15<img src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-screen-map-dark.svg?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=5b4161581a1bd2c0450b0c8b57bc1225" className="hidden dark:block" alt="Map of a Claude Code terminal session. A mod can add a pane as a sidebar on the right, a toast at the top right of the transcript, a log line in the transcript, a band above the prompt, and a status line under the prompt. A mod can redraw messages, tool call rows, and the spinner. The prompt is Claude Code's own." width="600" height="336" data-path="images/mods-screen-map-dark.svg" />15<img src="https://mintcdn.com/claude-code/dgiVO_Od1X1faduV/images/mods-screen-map-dark.svg?fit=max&auto=format&n=dgiVO_Od1X1faduV&q=85&s=5b4161581a1bd2c0450b0c8b57bc1225" className="hidden dark:block" alt="Map of a Claude Code terminal session in fullscreen rendering. A mod can add a pane as a sidebar on the right, a toast at the top right of the transcript, a log line in the transcript, a band above the prompt, and a status line under the prompt. A mod can redraw messages, tool call rows, and the spinner. The prompt is Claude Code's own." width="600" height="336" data-path="images/mods-screen-map-dark.svg" />

16 16 

17In a narrower terminal, the pane sits above the prompt instead of beside the transcript.17In a narrower terminal, the pane sits above the prompt instead of beside the transcript.

18 18 


316| `title` | The pane's tab label when more than one pane is open |316| `title` | The pane's tab label when more than one pane is open |

317| `focus` | Requests [keyboard focus](#know-which-keys-your-mod-can-receive) |317| `focus` | Requests [keyboard focus](#know-which-keys-your-mod-can-receive) |

318| `closeOnEscape` | Makes Esc close the pane |318| `closeOnEscape` | Makes Esc close the pane |

319| `holdToasts` | Holds toasts, the small notices from [`$.ui.toast`](/docs/en/plugins/mods/api#show-something-without-starting-a-turn), until the pane closes |319| `holdToasts` | In the terminal, holds toasts while this pane is the one showing. See [Hold toasts behind a dialog](#hold-toasts-behind-a-dialog). |

320| `rows` | The height to ask for when the pane sits above the prompt. The default is a third of the space. |320| `rows` | The height to ask for when the pane sits above the prompt. The default is a third of the space. |

321| `columns` | The width to ask for when the pane sits beside the transcript |321| `columns` | The width to ask for when the pane sits beside the transcript |

322 322 


329 329 

330To let a command open the pane while Claude is working, add `immediate: true` when you [register the command](/docs/en/plugins/mods/api#add-a-command). Without it, a command typed during a turn waits for the turn to end.330To let a command open the pane while Claude is working, add `immediate: true` when you [register the command](/docs/en/plugins/mods/api#add-a-command). Without it, a command typed during a turn waits for the turn to end.

331 331 

332#### Hold toasts behind a dialog

333 

334Pass `holdToasts: true` to `$.ui.open` when the pane is a dialog the user answers and leaves, so toasts don't appear while they decide. In the terminal, the hold lasts while that pane is the one showing, and a toast raised in that time waits until the hold ends.

335 

336Claude Code holds other mods' toasts and its own short-lived notifications as well as the ones your mod raises with [`$.ui.toast`](/docs/en/plugins/mods/api#show-something-without-starting-a-turn). Leave the field off a pane that stays open, so the user keeps seeing them.

337 

332#### When a pane waits for a wider terminal338#### When a pane waits for a wider terminal

333 339 

334A pane your mod opens without being asked doesn't appear in a narrow terminal, so it can't take over a small screen. Whether it appears depends on what opened it:340A pane your mod opens without being asked doesn't appear in a narrow terminal, so it can't take over a small screen. Whether it appears depends on what opened it:

Details

56| :- | :- | :- |56| :- | :- | :- |

57| [`tool.call`](/docs/en/plugins/mods/events#guard-or-change-a-tool-call) | A tool is about to run | `next(e)`, `{ deny: reason }`, or `{ result }` |57| [`tool.call`](/docs/en/plugins/mods/events#guard-or-change-a-tool-call) | A tool is about to run | `next(e)`, `{ deny: reason }`, or `{ result }` |

58| [`tool.check`](/docs/en/plugins/mods/events#where-settings-hooks-run-in-the-order) | Claude Code decides whether a tool call may run, after the `tool.call` and `PreToolUse` hooks. `next(e)` resolves to the decision the rules, the permission mode, and those hooks reached. | `{ decision }`, which is `allow`, `ask`, or `deny` |58| [`tool.check`](/docs/en/plugins/mods/events#where-settings-hooks-run-in-the-order) | Claude Code decides whether a tool call may run, after the `tool.call` and `PreToolUse` hooks. `next(e)` resolves to the decision the rules, the permission mode, and those hooks reached. | `{ decision }`, which is `allow`, `ask`, or `deny` |

59| `tool.describe` | Once for each tool, when its description is first sent to Claude | `{ description }`, optionally with `isDeferred` set to `true` to put the tool behind [tool search](/docs/en/mcp#scale-with-mcp-tool-search) or `false` to load it upfront |59| `tool.describe` | Once for each tool, when its description is first sent to Claude. A second time for an MCP tool when Claude loads it through [tool search](/docs/en/mcp#scale-with-mcp-tool-search), with `e.description` set to the text Claude reads for the loaded tool. | `{ description }`, optionally with `isDeferred` set to `true` to put the tool behind tool search or `false` to load it upfront |

60 60 

61#### Agent and organization fields on `tool.check`61#### Agent and organization fields on `tool.check`

62 62 


117| `session.end` | The session ends, or `/clear`, `/resume`, or `/branch` runs. `e.reason` is `clear`, `resume`, `logout`, `prompt_input_exit`, or `other`. `/branch` reports `resume`. | `next(e)` |117| `session.end` | The session ends, or `/clear`, `/resume`, or `/branch` runs. `e.reason` is `clear`, `resume`, `logout`, `prompt_input_exit`, or `other`. `/branch` reports `resume`. | `next(e)` |

118| `session.compact` | The conversation is about to be compacted | `{ skip: reason }` |118| `session.compact` | The conversation is about to be compacted | `{ skip: reason }` |

119| [`session.receive`](/docs/en/plugins/mods/api#send-and-receive-messages-between-sessions), [`session.send`](/docs/en/plugins/mods/api#send-and-receive-messages-between-sessions) | A message arrives from, or is about to go to, another agent or session. See [Send and receive messages between sessions](/docs/en/plugins/mods/api#send-and-receive-messages-between-sessions). | `{ consumed: reason }` for `receive`, `{ isDelivered: false, reason }` for `send` |119| [`session.receive`](/docs/en/plugins/mods/api#send-and-receive-messages-between-sessions), [`session.send`](/docs/en/plugins/mods/api#send-and-receive-messages-between-sessions) | A message arrives from, or is about to go to, another agent or session. See [Send and receive messages between sessions](/docs/en/plugins/mods/api#send-and-receive-messages-between-sessions). | `{ consumed: reason }` for `receive`, `{ isDelivered: false, reason }` for `send` |

120| `session.append` | Once for each row the conversation keeps, such as a prompt, a response block, a tool result, or a notice, before it's stored | `next({ ...e, message })` to rewrite the row's `content` |120| `session.append` | Once for each row the conversation keeps, such as a prompt, a response block, a tool result, or a notice, before it's stored | `next({ ...e, message })` with a changed `message.content`, to rewrite the row's text blocks or the `content` of a `tool_result` block in it |

121| `session.attach`, `session.detach` | Another app connects to or disconnects from the session | `next(e)` |121| `session.attach`, `session.detach` | Another app connects to or disconnects from the session | `next(e)` |

122| `session.measure` | After each turn, and when a plan limit's percent used changes | `next(e)` |122| `session.measure` | After each turn, and when a plan limit's percent used changes | `next(e)` |

123 123 


179| [`$.ui`](/docs/en/plugins/mods/interface#pick-where-to-draw) | `resolve`, `invalidate`, `open`, `close`, `panes`, `focus`, `scroll`, `toast`, `status`, `log`, `notice`, `ask`, `copy`, `selection`, `blit` |179| [`$.ui`](/docs/en/plugins/mods/interface#pick-where-to-draw) | `resolve`, `invalidate`, `open`, `close`, `panes`, `focus`, `scroll`, `toast`, `status`, `log`, `notice`, `ask`, `copy`, `selection`, `blit` |

180| [`$.command`](/docs/en/plugins/mods/api#add-a-command) | `register`, `run`, `list` |180| [`$.command`](/docs/en/plugins/mods/api#add-a-command) | `register`, `run`, `list` |

181| [`$.tool`](/docs/en/plugins/mods/api#add-a-tool) | `register`, `call`, `check`, `list` |181| [`$.tool`](/docs/en/plugins/mods/api#add-a-tool) | `register`, `call`, `check`, `list` |

182| `$.agent` | `register`, `spawn`, `list` |182| `$.agent` | `register`, `spawn`, `list`. `list()` returns this session's subagents and teammates, each with a `status` of `pending`, `running`, `waiting`, `idle`, `completed`, `failed`, or `killed`, where `idle` and `waiting` require Claude Code v2.1.289 or later. |

183| [`$.model`](/docs/en/plugins/mods/api#call-a-model) | `complete`, `fork`, `classify` |183| [`$.model`](/docs/en/plugins/mods/api#call-a-model) | `complete`, `fork`, `classify` |

184| [`$.prompt`](/docs/en/plugins/mods/api#start-a-turn-from-a-background-job) | `submit`, `read`, `fill`, `suggest`, `compose`. Claude reads text from `submit({ text })` after a sentence that names your mod as the sender. `submit({ text, asUser: true })` sends the text as the user's own words, without that sentence. |184| [`$.prompt`](/docs/en/plugins/mods/api#start-a-turn-from-a-background-job) | `submit`, `read`, `fill`, `suggest`, `compose`. Claude reads text from `submit({ text })` after a sentence that names your mod as the sender. `submit({ text, asUser: true })` sends the text as the user's own words, without that sentence. |

185| `$.turn` | `abort` |185| `$.turn` | `abort` |


290| `$.ui.invalidate('ui.render')` redraws | Throttled to 10 a second, or 30 in the terminal for the visible pane, the expanded band, and the hint line under the prompt. Calls that come sooner are coalesced. |290| `$.ui.invalidate('ui.render')` redraws | Throttled to 10 a second, or 30 in the terminal for the visible pane, the expanded band, and the hint line under the prompt. Calls that come sooner are coalesced. |

291| `$.ui.toast` | Shown for 4 seconds unless you pass `{ timeoutMs }` |291| `$.ui.toast` | Shown for 4 seconds unless you pass `{ timeoutMs }` |

292| A pane opened without the user asking | Placed from 144 terminal columns, 110 after they've opened it once |292| A pane opened without the user asking | Placed from 144 terminal columns, 110 after they've opened it once |

293| Scopes, such as functions, blocks, and loops, nested inside one another in one file of a hooks module | 2,000 |

293| Command, tool, subagent type, and pane names | Letters, digits, `_`, and `-`, up to 64 characters |294| Command, tool, subagent type, and pane names | Letters, digits, `_`, and `-`, up to 64 characters |

294| One `claude plugin test` test | 5 seconds unless the test sets `timeoutMs` |295| One `claude plugin test` test | 5 seconds unless the test sets `timeoutMs` |

295 296 

Details

94 94 

95Set or change the value. The end of the line names its `pluginConfigs` entry in `settings.json`.95Set or change the value. The end of the line names its `pluginConfigs` entry in `settings.json`.

96 96 

97### `code nested too deep to scan: more than 2000 scopes`

98 

99The line starts with the mod's name, then `hooks module did not load:`, the file, and `code nested too deep to scan: more than 2000 scopes`. A file in a hooks module can't nest scopes, such as functions, blocks, and loops, more than [2,000 deep](/docs/en/plugins/mods/reference#limits). [`claude plugin validate`](/docs/en/plugins/mods/create#check-what-claude-code-reads-from-your-mod) reports the same reason.

100 

101Rewrite the code so its scopes nest less deeply.

102 

97### No mod loads in a directory you opened for the first time103### No mod loads in a directory you opened for the first time

98 104 

99You haven't answered the trust prompt for the directory.105You haven't answered the trust prompt for the directory.


106 112 

107Start without the flag.113Start without the flag.

108 114 

115### Claude Code stops asking to enable hot reloading

116 

117Claude writes a mod in an interactive session, nothing loads, and Claude Code doesn't ask again [whether to enable hot reloading](/docs/en/plugins/mods/create#ask-claude-for-a-mod). If the question ends three times without an answer picked, hot reloading stays off. For example, the question ends that way when you set [`askUserQuestionTimeout`](/docs/en/settings-reference#askuserquestiontimeout) and the time passes before you answer. That setting applies here because Claude Code asks in the same [question dialog that `AskUserQuestion` uses](/docs/en/tools-reference#question-auto-continue-timeout). A question you dismiss yourself doesn't count toward the three.

118 

119To run the mod, [copy its directory out of the mods folder](/docs/en/plugins/mods/create#use-the-mod-in-other-sessions), then in your shell start a new session with `--plugin-dir`, as in `claude --plugin-dir ~/mods/git-branch`.

120 

109## A hook is skipped or a mod is unloaded121## A hook is skipped or a mod is unloaded

110 122 

111The mod loaded, and then Claude Code skipped one of its hooks or unloaded it.123The mod loaded, and then Claude Code skipped one of its hooks or unloaded it.


163 175 

164## A drawing doesn't appear or respond176## A drawing doesn't appear or respond

165 177 

166The mod loaded, and its pane, band, or controls don't behave as you expect.178The mod loaded, and its pane, band, toast, or controls don't behave as you expect.

167 179 

168### A pane or band is empty or shows Claude Code's usual content180### A pane or band is empty or shows Claude Code's usual content

169 181 


193 205 

194Open the pane from a command or a button, or check the call's `isPlaced` result. See [Open a pane at the right time](/docs/en/plugins/mods/interface#open-a-pane-at-the-right-time).206Open the pane from a command or a button, or check the call's `isPlaced` result. See [Open a pane at the right time](/docs/en/plugins/mods/interface#open-a-pane-at-the-right-time).

195 207 

208### A toast doesn't appear

209 

210Your mod calls [`$.ui.toast`](/docs/en/plugins/mods/api#show-something-without-starting-a-turn) in an interactive terminal session and you don't see the toast. To confirm that the call ran, look in the [debug log](#read-the-debug-log) for a line with your mod's name and the toast's text, as in `$.ui.toast (first-mod): build finished`. Then check for causes such as these:

211 

212* **The line for the call is missing**: look for one that says why Claude Code refused the call, as in `first-mod: $.ui.toast dropped: timeoutMs is a whole number of ms, 1 to 60000`.

213* **A pane is holding toasts**: your mod or another one passed [`holdToasts`](/docs/en/plugins/mods/interface#hold-toasts-behind-a-dialog) when it opened the pane that's showing. Close the pane to end the hold. If the pane is yours and is meant to stay open, remove `holdToasts` from its `$.ui.open` call and open the pane again.

214* **The toast is under the prompt**: in the [classic renderer](/docs/en/fullscreen#enable-fullscreen-rendering), look at the right under the prompt. A toast there is one line that starts with the mod's name, rather than a box at the top right.

215* **Your mod raised a newer toast**: in the classic renderer, a newer toast from your mod can take the place of one that's showing or waiting to show. The debug log has another line for the older toast, which ends with `gave way, cut short` when it was showing, or `gave way, unseen` when it never appeared. To show both messages, put them in one toast.

216* **The toast ran out of time undrawn**: in fullscreen rendering, Claude Code draws at most three toasts at a time, so a toast can run out of time before it's drawn. The debug log has another line for that toast, which ends with `left the stack, never drawn`. When your mod raises several at once, put the messages in one toast.

217 

218Before v2.1.290, Claude Code dropped a toast raised within two seconds of the last one it showed for your mod, and the debug log line for the dropped toast said `within 2000ms of the last; dropped`.

219 

196### Hotkeys do nothing220### Hotkeys do nothing

197 221 

198Your pane doesn't have keyboard focus.222Your pane doesn't have keyboard focus.

Details

98}98}

99```99```

100 100 

101In your shell, run `claude plugin validate .` in the repository to check the file before you push.101In your shell, run `claude plugin validate .` in the repository before you push. For what the run checks, see [Validate a directory](/docs/en/plugins/cli-reference#validate-a-directory).

102 102 

103[Create a marketplace](/docs/en/plugins/create-marketplace) covers the layout with several plugins in one repository.103[Create a marketplace](/docs/en/plugins/create-marketplace) covers the layout with several plugins in one repository.

104 104 

Details

233* **You own the marketplace**: put the file at that location and re-add the marketplace233* **You own the marketplace**: put the file at that location and re-add the marketplace

234* **Someone else hosts it**: ask the owner for the exact source they publish234* **Someone else hosts it**: ask the owner for the exact source they publish

235 235 

236<h3 id="cannot-install-plugins-from-a-marketplace-with-this-name">

237 `Cannot add marketplace "<name>": Claude Code cannot install plugins from a marketplace with this name`

238</h3>

239 

240You added a marketplace, and the [`name`](/docs/en/plugins/marketplace-reference#top-level-fields) in its `marketplace.json` isn't valid as the part after `@` in a [plugin id](/docs/en/plugins/loading#find-where-a-plugin-came-from) such as `my-plugin@my-marketplace`. Claude Code refuses the add and registers nothing.

241 

242The rest of the message states the rule for the name. In this example, `_internal` breaks the rule by starting with `_`:

243 

244```text theme={null}

245Cannot add marketplace "_internal": Claude Code cannot install plugins from a marketplace with this name. Each part of a plugin id (plugin@marketplace) may use only the letters a-z and A-Z, digits, ".", "_" and "-", and must start with a letter or digit. The name is set by "name" in the marketplace's marketplace.json; ask its maintainer to change it.

246```

247 

248Give the marketplace a name that fits that rule, then add it again:

249 

250* **You own the marketplace**: change `name` in `marketplace.json`, for example to `internal-tools`

251* **Someone else hosts it**: ask the owner to change the name

252 

253Before v2.1.295, Claude Code reported the add in this example as successful.

254 

236<h3 id="ssh-authentication-failed-or-https-authentication-failed">255<h3 id="ssh-authentication-failed-or-https-authentication-failed">

237 `SSH authentication failed` or `HTTPS authentication failed`256 `SSH authentication failed` or `HTTPS authentication failed`

238</h3>257</h3>


778 797 

779Claude Code copies the unusable records into the `.set-aside` file and drops them from the list. Claude Code never reads the copies back, and the copies age out on the [`cleanupPeriodDays`](/docs/en/settings-reference#cleanupperioddays) schedule.798Claude Code copies the unusable records into the `.set-aside` file and drops them from the list. Claude Code never reads the copies back, and the copies age out on the [`cleanupPeriodDays`](/docs/en/settings-reference#cleanupperioddays) schedule.

780 799 

800<h3 id="does-not-load-so-claude-code-ignores-the-whole-file">

801 `does not load (...), so Claude Code ignores the whole file`

802</h3>

803 

804The command worked. The settings file the warning names has an error, so Claude Code ignores the whole file, including anything the command wrote there, until you fix it.

805 

806Fix the error the warning names. For a value Claude Code doesn't accept, [Fix a broken settings file](/docs/en/settings#fix-a-broken-settings-file) says how. Then run the command again if its change is no longer in the file.

807 

808The warning follows the success line of `claude plugin install`, `enable`, `disable`, or `claude plugin marketplace add` in your shell:

809 

810```text theme={null}

811⚠ /home/user/.claude/settings.json does not load (its "permissions" is not valid), so Claude Code ignores the whole file, including anything this command wrote there. Fix the file, then run this command again if its change is missing. If a newer Claude Code wrote the file, update Claude Code instead.

812```

813 

814The text in parentheses names the error:

815 

816* **`its "<key>" is not valid`**: the quoted setting holds a value Claude Code doesn't accept. Look up the setting in the [settings reference](/docs/en/settings-reference) for the values it takes. When more than one value fails, the text names the first setting and counts the others, as in `its "permissions" and 1 other value are not valid`.

817* **`it is not a JSON object`**: the file's top level isn't a JSON object, such as a file whose top level is an array.

818 

781<h3 id="a-plugin-you-disabled-still-loads">819<h3 id="a-plugin-you-disabled-still-loads">

782 `Disabled in ~/.claude/settings.json but still loads`820 `Disabled in ~/.claude/settings.json but still loads`

783</h3>821</h3>


804 842 

805If your organization pre-installs plugins for you, it does so through managed settings instead. See [Pre-install and require plugins](/docs/en/plugins/org#pre-install-and-require-plugins).843If your organization pre-installs plugins for you, it does so through managed settings instead. See [Pre-install and require plugins](/docs/en/plugins/org#pre-install-and-require-plugins).

806 844 

845<h3 id="a-plugin-stays-installed-after-plugin-uninstall-on-windows">

846 A plugin stays installed after `plugin uninstall` on Windows

847</h3>

848 

849On Windows, you run `claude plugin uninstall` at project or local scope and it reports success, but `claude plugin list` or `/plugin` still lists the plugin.

850 

851`installed_plugins.json` held two install records of the plugin for the project folder, each spelling the folder's path differently, and one uninstall removes one of them. To check, run `claude plugin list --json` in your shell. The plugin's remaining row has a `projectPath` that spells the folder differently from where you ran the uninstall, such as `c:\work\app` for `C:\work\app`.

852 

853Run the same uninstall command again, with the same `--scope`, from the same folder. The second run finds no record under its own spelling of the path, so it removes the one under the other spelling. For a project-scope install:

854 

855```shell theme={null}

856claude plugin uninstall <name>@<marketplace> --scope project

857```

858 

859Then run `claude plugin list --json` again to confirm that the row is gone.

860 

861Before v2.1.295, the second run fails with `Plugin "<name>" is not installed in project scope`. Run `claude update`, then run the uninstall again.

862 

807<h3 id="failed-to-load-hooks-from-and-hooks-that-dont-fire">863<h3 id="failed-to-load-hooks-from-and-hooks-that-dont-fire">

808 `Failed to load hooks from <path>` and hooks that don't fire864 `Failed to load hooks from <path>` and hooks that don't fire

809</h3>865</h3>


823 879 

824If the stderr shows the plugin's path cut off at a space, the hook's shell-form command uses `${CLAUDE_PLUGIN_ROOT}` outside quotes and the install path contains a space. Wrap the variable in double quotes or use [exec form](/docs/en/hooks#exec-form-and-shell-form). To find the unquoted variable, run `claude plugin validate` on the plugin's directory and look for its [quoting warning](/docs/en/plugins/manifest-reference#quoting-and-path-separators).880If the stderr shows the plugin's path cut off at a space, the hook's shell-form command uses `${CLAUDE_PLUGIN_ROOT}` outside quotes and the install path contains a space. Wrap the variable in double quotes or use [exec form](/docs/en/hooks#exec-form-and-shell-form). To find the unquoted variable, run `claude plugin validate` on the plugin's directory and look for its [quoting warning](/docs/en/plugins/manifest-reference#quoting-and-path-separators).

825 881 

882If the notice reads `Failed to run: Plugin directory does not exist: <path>`, see [`Plugin directory does not exist`](#plugin-directory-does-not-exist).

883 

826For any other error, run the hook's command yourself from the plugin directory to see the full output, or capture the full stderr with [debug logging](/docs/en/hooks#debug-hooks).884For any other error, run the hook's command yourself from the plugin directory to see the full output, or capture the full stderr with [debug logging](/docs/en/hooks#debug-hooks).

827 885 

828#### A plugin hook blocks a tool call or prompt886#### A plugin hook blocks a tool call or prompt


853 </Step>911 </Step>

854</Steps>912</Steps>

855 913 

914<h3 id="plugin-directory-does-not-exist">

915 `Plugin directory does not exist: <path>`

916</h3>

917 

918Run `/reload-plugins` at the Claude Code prompt first, even though the message says to reinstall. A plugin's hook fails with `Failed to run: Plugin directory does not exist: <path> (<plugin> — run /plugin to reinstall)`, and the hook doesn't run, when the directory your session loaded the plugin's hooks from is gone from disk. [`Plugin directory not found at path: <path>`](#plugin-directory-not-found-at-path) is a different message, about a marketplace entry.

919 

920The reload loads the plugin's hooks from its current directory. The failure is shown once per session for each hook event and command, so the hook going quiet doesn't confirm the fix. Read the reload's output instead:

921 

922* **`Reloaded:` with no errors line**: the plugin's hooks no longer point at the missing directory

923* **`N errors during load. Run /plugin for details.`**: open the **Errors** tab in `/plugin` and follow this page's entry for the message it shows

924* **A line that ends `Run /reload-plugins --force to apply.`**: nothing reloaded, and the hooks keep failing. Run `/reload-plugins --force` at the Claude Code prompt

925 

856<h3 id="invalid-mcp-server-config-for-and-mcp-servers-that-dont-start">926<h3 id="invalid-mcp-server-config-for-and-mcp-servers-that-dont-start">

857 `Invalid MCP server config for "<server>"` and MCP servers that don't start927 `Invalid MCP server config for "<server>"` and MCP servers that don't start

858</h3>928</h3>


1031 1101 

1032You ran `claude plugin validate <path>`, or `/plugin validate <path>` in a session, and it printed `Found N errors` and `Validation failed`, then exited with code 1.1102You ran `claude plugin validate <path>`, or `/plugin validate <path>` in a session, and it printed `Found N errors` and `Validation failed`, then exited with code 1.

1033 1103 

1034The validator reads the manifest at the path you give it: `.claude-plugin/plugin.json` for a plugin directory, or `.claude-plugin/marketplace.json` for a marketplace directory. For a marketplace, it prefixes problems in an entry's own manifest with the entry index, as `plugins[1] plugin.json → json: ...`.1104The validator reads the manifest at the path you give it: `.claude-plugin/plugin.json` for a plugin directory, `.claude-plugin/marketplace.json` for a marketplace directory, or both for a directory that holds both. For a marketplace, it prefixes problems in an entry's own manifest with the entry index, as `plugins[1] plugin.json → json: ...`. Before v2.1.289, Claude Code validated a directory that holds both as a marketplace alone.

1035 1105 

1036The table covers the messages that stop validation and two warnings, `No frontmatter block found` and `Unknown field '<key>'`, which stop it only when you pass `--strict`. Other warnings, such as a missing description, aren't listed.1106The table covers the messages that stop validation and two warnings, `No frontmatter block found` and `Unknown field '<key>'`, which stop it only when you pass `--strict`. Other warnings, such as a missing description, aren't listed.

1037 1107 

Details

169 169 

170### Jitter170### Jitter

171 171 

172To avoid every session hitting the API at the same wall-clock moment, the scheduler adds a deterministic offset to fire times:172A scheduled task can run at a different time than its schedule says. If every session's tasks ran exactly on schedule, many of them would call the API at the same moment, so Claude Code shifts each task's run time. Recurring tasks run late, and one-shot tasks scheduled on the hour or half hour run a little early.

173 173 

174* Recurring tasks fire up to 30 minutes after the scheduled time (or up to half the interval, for tasks that run more often than hourly). An hourly job scheduled for `:00` may fire anywhere up to `:30`.174#### How late a recurring task runs

175* One-shot tasks scheduled for the top or bottom of the hour fire up to 90 seconds early.

176 175 

177The offset is derived from the task ID, so the same task always gets the same offset. If exact timing matters, pick a minute that is not `:00` or `:30`, for example `3 9 * * *` instead of `0 9 * * *`, and the one-shot jitter will not apply.176When you create a recurring task, Claude Code gives it a fixed delay and adds that delay to every run. The delay is worked out from the task's ID, so the same task runs the same number of minutes late each time, including when the session is idle and nothing else is running.

177 

178Tasks that run more often get shorter delays, and 30 minutes is the longest delay a task can get. These are the delay ranges for some common schedules:

179 

180| Task runs | Delay is between |

181| :- | :- |

182| Every 10 minutes | 0 and 5 minutes |

183| Every 30 minutes | 0 and 15 minutes |

184| Every hour, or less often such as daily | 0 and 30 minutes |

185 

186For example, `7,37 * * * *` schedules a task for `:07` and `:37`, which are 30 minutes apart, so its delay is somewhere between 0 and 15 minutes. If this task's delay is 14 minutes, it runs at `:21` and `:51` every hour. Changing the schedule to a different minute moves the run time, and a delay is still added on top.

187 

188#### When a one-shot task runs early

189 

190A one-shot task scheduled for `:00` or `:30` runs up to 90 seconds early. Claude Code doesn't shift a one-shot task scheduled for any other minute, so when the timing matters, schedule it off the hour and half hour: `3 9 * * *` instead of `0 9 * * *`.

178 191 

179### Seven-day expiry192### Seven-day expiry

180 193 

Details

66 66 

67You can extend each layer by [adding your own rules](#add-your-own-rules). Built-in checks cannot be removed individually, but you can [disable each layer](#disable-or-uninstall) independently.67You can extend each layer by [adding your own rules](#add-your-own-rules). Built-in checks cannot be removed individually, but you can [disable each layer](#disable-or-uninstall) independently.

68 68 

69### On each file edit69<span id="on-each-file-edit" />

70 

71### Checks on each file edit

70 72 

71When Claude writes to a file, the plugin scans the new content for known risky patterns. This is a pattern match with no model call, so it adds no usage cost.73When Claude writes to a file, the plugin scans the new content for known risky patterns. This is a pattern match with no model call, so it adds no usage cost.

72 74 


81 83 

82You can [add your own patterns](#add-custom-per-edit-patterns) to this layer with a `security-patterns.yaml` file.84You can [add your own patterns](#add-custom-per-edit-patterns) to this layer with a `security-patterns.yaml` file.

83 85 

84### At the end of each turn86<span id="at-the-end-of-each-turn" />

87 

88### Checks at the end of each turn

85 89 

86A turn is one round of Claude responding: you send a message, Claude works and replies, and the turn ends. After each turn, the plugin computes a git diff of everything that changed in the working tree during the turn, including changes from Claude's edit tools, Bash commands, and subagents, and sends it to a separate Claude review focused on security. The review runs in the background, so Claude's reply is not delayed. If the review finds issues, Claude is re-prompted with the findings and addresses them as a follow-up.90A turn is one round of Claude responding: you send a message, Claude works and replies, and the turn ends. After each turn, the plugin computes a git diff of everything that changed in the working tree during the turn, including changes from Claude's edit tools, Bash commands, and subagents, and sends it to a separate Claude review focused on security. The review runs in the background, so Claude's reply is not delayed. If the review finds issues, Claude is re-prompted with the findings and addresses them as a follow-up.

87 91 


95 99 

96You see both the finding and Claude's resolution directly in your session. The review covers up to 30 changed files per turn and fires at most three times in a row before yielding back to you.100You see both the finding and Claude's resolution directly in your session. The review covers up to 30 changed files per turn and fires at most three times in a row before yielding back to you.

97 101 

98### On each commit or push Claude makes102<span id="on-each-commit-or-push-claude-makes" />

103 

104### Checks on each commit or push Claude makes

99 105 

100When Claude runs `git commit` or `git push` through its Bash tool, the plugin runs a deeper agentic review of the change in the background. This review reads surrounding code, including callers, sanitizers, and related files, to decide whether a finding is real before reporting it. The extra context keeps false positives low on patterns that look dangerous in isolation but are safe in your codebase.106When Claude runs `git commit` or `git push` through its Bash tool, the plugin runs a deeper agentic review of the change in the background. This review reads surrounding code, including callers, sanitizers, and related files, to decide whether a finding is real before reporting it. The extra context keeps false positives low on patterns that look dangerous in isolation but are safe in your codebase.

101 107 

Details

373 373 

374* The enterprise-scope [managed MCP file](/docs/en/managed-mcp) at its standard system path: `/etc/claude-code/managed-mcp.json` on Linux runner hosts, `/Library/Application Support/ClaudeCode/managed-mcp.json` on macOS hosts. Use it for locked-down fleets where only administrator-listed servers may load. See [exclusive control with managed-mcp.json](/docs/en/managed-mcp#exclusive-control-with-managed-mcp-json) for the precedence rules. When this file is on the runner host, Claude Code skips the MCP servers Anthropic's control plane delivers to a session, including claude.ai connectors, and names them in a warning on the session child's stderr, which the runner records at the `debug` log level. Before v2.1.229, those sessions exited at startup with `You cannot dynamically configure MCP servers when an enterprise MCP config is present`.374* The enterprise-scope [managed MCP file](/docs/en/managed-mcp) at its standard system path: `/etc/claude-code/managed-mcp.json` on Linux runner hosts, `/Library/Application Support/ClaudeCode/managed-mcp.json` on macOS hosts. Use it for locked-down fleets where only administrator-listed servers may load. See [exclusive control with managed-mcp.json](/docs/en/managed-mcp#exclusive-control-with-managed-mcp-json) for the precedence rules. When this file is on the runner host, Claude Code skips the MCP servers Anthropic's control plane delivers to a session, including claude.ai connectors, and names them in a warning on the session child's stderr, which the runner records at the `debug` log level. Before v2.1.229, those sessions exited at startup with `You cannot dynamically configure MCP servers when an enterprise MCP config is present`.

375* The [`managedMcpServers`](/docs/en/settings-reference#managedmcpservers) key in [managed settings](/docs/en/managed-settings) on the runner host: provides HTTP and SSE servers without taking exclusive control, so servers from the other sources still load. Requires Claude Code v2.1.259 or later.375* The [`managedMcpServers`](/docs/en/settings-reference#managedmcpservers) key in [managed settings](/docs/en/managed-settings) on the runner host: provides HTTP and SSE servers without taking exclusive control, so servers from the other sources still load. Requires Claude Code v2.1.259 or later.

376* `<repo>/.mcp.json`: project scope. Commit the file to the repository; its servers are auto-approved in cloud sessions.376* `<repo>/.mcp.json`: project scope. Commit the file to the repository; its servers are auto-approved in cloud sessions. In a session with several repositories, [at most one repository's file loads](#repository-settings-in-sessions-with-several-repositories).

377 377 

378When connector delivery is enabled for your organization, Anthropic's control plane delivers the connectors you've configured on claude.ai to interactively-created sessions through server-provided MCP configuration, routed through `api.anthropic.com`. Sessions created programmatically, such as [CLI dispatches](/docs/en/self-hosted-environments-testing#run-the-test-loop), don't receive connector delivery; give them MCP servers through any of the other sources this section lists instead. The child's OAuth token doesn't carry a scope for fetching connectors directly, so the child doesn't attempt that fetch itself; delivery is server-driven.378When connector delivery is enabled for your organization, Anthropic's control plane delivers the connectors you've configured on claude.ai to interactively-created sessions through server-provided MCP configuration, routed through `api.anthropic.com`. Sessions created programmatically, such as [CLI dispatches](/docs/en/self-hosted-environments-testing#run-the-test-loop), don't receive connector delivery; give them MCP servers through any of the other sources this section lists instead. The child's OAuth token doesn't carry a scope for fetching connectors directly, so the child doesn't attempt that fetch itself; delivery is server-driven.

379 379 


508exit 0508exit 0

509```509```

510 510 

511The hook prompts Claude to commit and push before the session ends, and stays silent when the directory isn't a git repository or has no remote.511The hook prompts Claude to commit and push before the session ends, and stays silent when the directory isn't a git repository or has no remote. For a session with several repositories, see [what `$CLAUDE_PROJECT_DIR` names](#repository-settings-in-sessions-with-several-repositories).

512 512 

513## Permissions and tool approval513## Permissions and tool approval

514 514 


533 533 

534Set `SELF_HOSTED_RUNNER_HOST_CONFIG_DIR` to seed from a different path, or point it at an empty directory to disable seeding.534Set `SELF_HOSTED_RUNNER_HOST_CONFIG_DIR` to seed from a different path, or point it at an empty directory to disable seeding.

535 535 

536Repository-committed `.claude/settings.json` layers on top as project settings. Sessions also read [`managed-settings.json`](/docs/en/settings#where-settings-live) from the standard system path in your runner image. Whether its keys apply alongside [server-managed settings](/docs/en/server-managed-settings) follows [how Claude Code combines managed sources](/docs/en/managed-settings#how-claude-code-combines-managed-sources): by default, when your organization delivers any server-managed keys, sessions ignore the runner image's file apart from the [keys Claude Code reads from every admin source](/docs/en/managed-settings#keys-read-from-every-admin-source), such as the `env` block, the sandbox locks, the sandbox binary paths, and `forceRemoteSettingsRefresh`. See [settings precedence](/docs/en/settings#settings-precedence).536Repository-committed `.claude/settings.json` layers on top as project settings. In a session with several repositories, [at most one repository's file takes effect](#repository-settings-in-sessions-with-several-repositories). Sessions also read [`managed-settings.json`](/docs/en/settings#where-settings-live) from the standard system path in your runner image. Whether its keys apply alongside [server-managed settings](/docs/en/server-managed-settings) follows [how Claude Code combines managed sources](/docs/en/managed-settings#how-claude-code-combines-managed-sources): by default, when your organization delivers any server-managed keys, sessions ignore the runner image's file apart from the [keys Claude Code reads from every admin source](/docs/en/managed-settings#keys-read-from-every-admin-source), such as the `env` block, the sandbox locks, the sandbox binary paths, and `forceRemoteSettingsRefresh`. See [settings precedence](/docs/en/settings#settings-precedence).

537 537 

538When Anthropic's control plane supplies a session with [Claude Code hooks](/docs/en/hooks), the runner installs them alongside, not over, your own configuration. Requires Claude Code v2.1.229 or later.538When Anthropic's control plane supplies a session with [Claude Code hooks](/docs/en/hooks), the runner installs them alongside, not over, your own configuration. Requires Claude Code v2.1.229 or later.

539 539 


545 545 

546The runner's snapshot of the host's `~/.claude/` leaves out the `projects/` directory. Auto memory's default storage location is under that directory. If you put memory files there, the runner doesn't seed them into sessions, and they don't turn auto memory on.546The runner's snapshot of the host's `~/.claude/` leaves out the `projects/` directory. Auto memory's default storage location is under that directory. If you put memory files there, the runner doesn't seed them into sessions, and they don't turn auto memory on.

547 547 

548### Repository settings in sessions with several repositories

549 

550In a session with several repositories, Claude Code reads project settings from the directory the session starts in, so at most one repository's `.claude/settings.json` takes effect as project settings. A hook defined in another repository's file doesn't run, a deny rule in it doesn't apply, and its `env` isn't set.

551 

552* **`--capacity 1`, the default, with the built-in checkout**: the session starts in the first repository in its list of repositories. That repository's `.claude/settings.json` takes effect as project settings and its `.mcp.json` loads, and the other repositories' don't.

553* **A `--capacity` above one, or a [`checkout` hook](#checkout)**: the session starts in a per-session directory that contains the checkouts. No repository's `.claude/settings.json` takes effect as project settings, no repository's `.mcp.json` loads, and [`$CLAUDE_PROJECT_DIR`](/docs/en/hooks#reference-scripts-by-path) in a hook command is that directory, not a checkout.

554 

555Each repository's `CLAUDE.md` and skills load wherever the session starts. The runner passes every repository to Claude Code as an [additional directory](/docs/en/permissions#additional-directories-grant-file-access-not-configuration), so Claude Code also reads the `enabledPlugins` and `extraKnownMarketplaces` keys from each repository's `.claude/settings.json`.

556 

557To run a hook or apply a permission rule in every session, put it in `~/.claude/settings.json` on the runner host. The runner [seeds the host file into every session](#how-each-session’s-config-is-assembled), wherever the session starts. Write a path in a `Read` or `Edit` rule as a `//` absolute or `~/` home-relative [pattern](/docs/en/permissions#read-and-edit), because other patterns anchor at the settings source or the current directory.

558 

548### Repository-committed permission rules559### Repository-committed permission rules

549 560 

550Don't put a bare `"Edit"`, `"Write"`, or `"NotebookEdit"` entry in a repository-committed `permissions.allow`. A bare file-tool rule matches the tool regardless of path, granting writes anywhere on the host rather than only the workspace, so the runner's write-scope confine guard flags the session; with [`--confine-repo-settings enforce`](/docs/en/self-hosted-environments-reference#runner-cli-flags) it refuses to spawn the session instead of logging and continuing. See the [hardening section](/docs/en/self-hosted-environments-deploy#harden-your-deployment).561Don't put a bare `"Edit"`, `"Write"`, or `"NotebookEdit"` entry in a repository-committed `permissions.allow`. A bare file-tool rule matches the tool regardless of path, granting writes anywhere on the host rather than only the workspace, so the runner's write-scope confine guard flags the session; with [`--confine-repo-settings enforce`](/docs/en/self-hosted-environments-reference#runner-cli-flags) it refuses to spawn the session instead of logging and continuing. See the [hardening section](/docs/en/self-hosted-environments-deploy#harden-your-deployment).

Details

86 86 

87 <Step title="Save and deploy">87 <Step title="Save and deploy">

88 Save your changes. Claude Code clients receive the updated settings on their next startup or hourly polling cycle.88 Save your changes. Claude Code clients receive the updated settings on their next startup or hourly polling cycle.

89 

90 The editor checks your JSON against the published JSON schema for Claude Code settings. If it finds a problem in JSON that parses, it shows a warning and relabels the save button. The label is **Update with errors** when settings are already saved, and **Add with errors** when no settings are saved yet. That button still saves, because a schema warning doesn't block the save.

91 

92 The schema [can lag behind the newest releases](/docs/en/settings#edit-a-settings-file), so the editor can flag a key or value that the [settings reference](/docs/en/settings-reference#all-settings) documents. Claude Code receives the keys and values you saved and runs [its own validation](#invalid-entries-in-delivered-settings) when it loads them.

89 </Step>93 </Step>

90</Steps>94</Steps>

91 95 

settings.md +2 −2

Details

507 507 

508In a [Cowork](https://claude.com/docs/cowork/overview) session that runs on your machine in the Claude Desktop app, Claude Code doesn't fetch server-managed settings from the claude.ai admin console, and it reads policy deployed to your device unless your organization's Claude Desktop configuration sets `requireCoworkFullVmSandbox`. [Where and when a policy applies](/docs/en/managed-settings#where-and-when-a-policy-applies) covers Cowork and cloud sessions.508In a [Cowork](https://claude.com/docs/cowork/overview) session that runs on your machine in the Claude Desktop app, Claude Code doesn't fetch server-managed settings from the claude.ai admin console, and it reads policy deployed to your device unless your organization's Claude Desktop configuration sets `requireCoworkFullVmSandbox`. [Where and when a policy applies](/docs/en/managed-settings#where-and-when-a-policy-applies) covers Cowork and cloud sessions.

509 509 

510If you're the administrator, [Set up Claude Code for your organization](/docs/en/admin-setup) walks through choosing what to enforce, and [Deploy managed settings](/docs/en/managed-settings) covers delivery and how to confirm a policy is in force.510If you're the administrator, [Set up Claude Code for your organization](/docs/en/admin-setup) walks through choosing what to enforce, and [Deploy managed settings](/docs/en/managed-settings) covers delivery and how to confirm a policy is in force. For the warning the managed settings editor in the claude.ai admin console can show, see [Configure server-managed settings](/docs/en/server-managed-settings#configure-server-managed-settings).

511 511 

512## Change a setting512## Change a setting

513 513 


751 751 

752A [cloud session](/docs/en/claude-code-on-the-web) runs in a [cloud environment](/docs/en/cloud-environments) on a fresh clone of your repository, not on your machine. That changes which settings reach it:752A [cloud session](/docs/en/claude-code-on-the-web) runs in a [cloud environment](/docs/en/cloud-environments) on a fresh clone of your repository, not on your machine. That changes which settings reach it:

753 753 

754* **Shared project settings** (`.claude/settings.json`): read in a session with one repository, because the file is part of the clone and the session starts inside it. Commit a setting there to apply it in those sessions. A session with several repositories starts above the clones and reads only the `enabledPlugins` and `extraKnownMarketplaces` keys from each repository's `.claude/settings.json`, not permission rules, hooks, `env`, or other keys. The marketplaces and plugins those two keys declare still [don't load in a cloud session](/docs/en/cloud-environments#what-carries-over-from-your-setup).754* **Shared project settings** (`.claude/settings.json`): read in a session with one repository, because the file is part of the clone and the session starts inside it. Commit a setting there to apply it in those sessions. In an Anthropic-hosted environment, a session with several repositories starts above the clones and reads only the `enabledPlugins` and `extraKnownMarketplaces` keys from each repository's `.claude/settings.json`, not permission rules, hooks, `env`, or other keys. The marketplaces and plugins those two keys declare still [don't load in a cloud session](/docs/en/cloud-environments#what-carries-over-from-your-setup). For a self-hosted environment, see [which repository's settings apply](/docs/en/self-hosted-environments-configuration#repository-settings-in-sessions-with-several-repositories).

755* **User and project local settings** (`~/.claude/settings.json` and `.claude/settings.local.json`): not read. Both stay on your machine, and the local file isn't in the clone.755* **User and project local settings** (`~/.claude/settings.json` and `.claude/settings.local.json`): not read. Both stay on your machine, and the local file isn't in the clone.

756* **Managed settings**: a `managed-settings.json` file or MDM profile on your device doesn't reach a cloud session. Your organization's [server-managed settings](/docs/en/server-managed-settings) do; [surface coverage](/docs/en/model-config#surface-coverage) lists which cloud sessions receive them. A [self-hosted environment](/docs/en/self-hosted-environments) also reads the managed settings file in its runner image. [How Claude Code combines managed sources](/docs/en/managed-settings#how-claude-code-combines-managed-sources) says when that file applies.756* **Managed settings**: a `managed-settings.json` file or MDM profile on your device doesn't reach a cloud session. Your organization's [server-managed settings](/docs/en/server-managed-settings) do; [surface coverage](/docs/en/model-config#surface-coverage) lists which cloud sessions receive them. A [self-hosted environment](/docs/en/self-hosted-environments) also reads the managed settings file in its runner image. [How Claude Code combines managed sources](/docs/en/managed-settings#how-claude-code-combines-managed-sources) says when that file applies.

757* **`/config`**: in your browser at claude.ai/code, opens the Claude Code section of your claude.ai settings instead of changing a value. To change a setting for a cloud session, set an [environment variable](/docs/en/cloud-environments#set-environment-variables) on the environment, or in a session with one repository, commit the key to that repository's `.claude/settings.json`.757* **`/config`**: in your browser at claude.ai/code, opens the Claude Code section of your claude.ai settings instead of changing a value. To change a setting for a cloud session, set an [environment variable](/docs/en/cloud-environments#set-environment-variables) on the environment, or in a session with one repository, commit the key to that repository's `.claude/settings.json`.

setup.md +20 −10

Details

39 <Tab title="Native Install (Recommended)">39 <Tab title="Native Install (Recommended)">

40 **macOS, Linux, WSL:**40 **macOS, Linux, WSL:**

41 41 

42 ```bash theme={null}42 ```bash theme={null} theme={null}

43 curl -fsSL https://claude.ai/install.sh | bash43 curl -fsSL https://claude.ai/install.sh | bash

44 ```44 ```

45 45 


47 47 

48 **Windows PowerShell:**48 **Windows PowerShell:**

49 49 

50 ```powershell theme={null}50 ```powershell theme={null} theme={null}

51 irm https://claude.ai/install.ps1 | iex51 irm https://claude.ai/install.ps1 | iex

52 ```52 ```

53 53 

54 **Windows CMD:**54 **Windows CMD:**

55 55 

56 ```batch theme={null}56 ```batch theme={null} theme={null}

57 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd57 curl -fsSL https://claude.ai/install.cmd -o install.cmd && install.cmd && del install.cmd

58 ```58 ```

59 59 


71 </Tab>71 </Tab>

72 72 

73 <Tab title="Homebrew">73 <Tab title="Homebrew">

74 ```bash theme={null}74 ```bash theme={null} theme={null}

75 brew install --cask claude-code75 brew install --cask claude-code

76 ```76 ```

77 77 


83 </Tab>83 </Tab>

84 84 

85 <Tab title="WinGet">85 <Tab title="WinGet">

86 ```powershell theme={null}86 ```powershell theme={null} theme={null}

87 winget install Anthropic.ClaudeCode87 winget install Anthropic.ClaudeCode

88 ```88 ```

89 89 


590 590 

591To remove Claude Code, follow the instructions for your installation method. If `claude` still runs afterward, you likely have a second installation or a leftover shell alias from an older installer. See [Check for conflicting installations](/docs/en/troubleshoot-install#check-for-conflicting-installations) to find and remove it.591To remove Claude Code, follow the instructions for your installation method. If `claude` still runs afterward, you likely have a second installation or a leftover shell alias from an older installer. See [Check for conflicting installations](/docs/en/troubleshoot-install#check-for-conflicting-installations) to find and remove it.

592 592 

593### Native installation593<span id="native-installation" />

594 

595### Uninstall a native installation

594 596 

595Remove the Claude Code binary and version files:597Remove the Claude Code binary and version files:

596 598 


610 </Tab>612 </Tab>

611</Tabs>613</Tabs>

612 614 

613### Homebrew installation615<span id="homebrew-installation" />

616 

617### Uninstall with Homebrew

614 618 

615Remove the Homebrew cask you installed. If you installed the stable cask:619Remove the Homebrew cask you installed. If you installed the stable cask:

616 620 


624brew uninstall --cask claude-code@latest628brew uninstall --cask claude-code@latest

625```629```

626 630 

627### WinGet installation631<span id="winget-installation" />

632 

633### Uninstall with WinGet

628 634 

629Remove the WinGet package:635Remove the WinGet package:

630 636 


632winget uninstall Anthropic.ClaudeCode638winget uninstall Anthropic.ClaudeCode

633```639```

634 640 

635### apt / dnf / apk641<span id="apt-/-dnf-/-apk" />

642 

643### Uninstall with apt, dnf, or apk

636 644 

637Remove the package and the repository configuration:645Remove the package and the repository configuration:

638 646 


660 </Tab>668 </Tab>

661</Tabs>669</Tabs>

662 670 

663### npm671<span id="npm" />

672 

673### Uninstall with npm

664 674 

665Remove the global npm package:675Remove the global npm package:

666 676 

skills.md +2 −0

Details

84| `migrate` | Update your existing Claude API code to a newer model | Earlier than v2.1.221 |84| `migrate` | Update your existing Claude API code to a newer model | Earlier than v2.1.221 |

85| `upgrade` | Move your project's Anthropic SDK dependency across a major version, currently the Python `anthropic` package from 0.x to 1.x | v2.1.236 or later |85| `upgrade` | Move your project's Anthropic SDK dependency across a major version, currently the Python `anthropic` package from 0.x to 1.x | v2.1.236 or later |

86| `managed-agents-onboard` | Walk through creating a new Managed Agent | Earlier than v2.1.221 |86| `managed-agents-onboard` | Walk through creating a new Managed Agent | Earlier than v2.1.221 |

87| `managed-agents-onboard <url>` | Build the Managed Agent that the page at the URL describes, such as a page in the [Managed Agents docs](https://platform.claude.com/docs/en/managed-agents/overview) | v2.1.290 or later |

88| `managed-agents-onboard <quickstart-name>` | Build one of the Console's quickstart templates, such as `deep-researcher`. If you give one word that isn't a template name, Claude lists the valid names | v2.1.290 or later |

87| `prompt-audit` | Flag instructions written for older models in your prompts, skills, and tool descriptions and propose fixes as a diff | v2.1.221 or later |89| `prompt-audit` | Flag instructions written for older models in your prompts, skills, and tool descriptions and propose fixes as a diff | v2.1.221 or later |

88| `cost-optimize` | Profile where your project's Claude API spend goes and propose savings from options such as prompt caching, trimming unneeded input and output tokens, batch processing, effort, and model choice, one change at a time | v2.1.247 or later |90| `cost-optimize` | Profile where your project's Claude API spend goes and propose savings from options such as prompt caching, trimming unneeded input and output tokens, batch processing, effort, and model choice, one change at a time | v2.1.247 or later |

89| `build-eval` | Build an eval set for your Claude-powered app | v2.1.259 or later |91| `build-eval` | Build an eval set for your Claude-powered app | v2.1.259 or later |

sub-agents.md +4 −2

Details

579The main conversation's permission mode decides whether Claude Code uses the value you set:579The main conversation's permission mode decides whether Claude Code uses the value you set:

580 580 

581* When the main conversation is in `bypassPermissions`, `acceptEdits`, or [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode), the subagent runs in that same mode and Claude Code ignores the `permissionMode` you set. Under auto mode, the classifier evaluates the subagent's tool calls with the main conversation's block and allow rules. When the subagent finishes, the classifier also reviews its work and its final report before the report is delivered, as [How auto mode handles subagents](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) describes.581* When the main conversation is in `bypassPermissions`, `acceptEdits`, or [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode), the subagent runs in that same mode and Claude Code ignores the `permissionMode` you set. Under auto mode, the classifier evaluates the subagent's tool calls with the main conversation's block and allow rules. When the subagent finishes, the classifier also reviews its work and its final report before the report is delivered, as [How auto mode handles subagents](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) describes.

582* When the main conversation is in `default`, `dontAsk`, or `plan` mode, the subagent runs in the permission mode you set, except `bypassPermissions`. A subagent that declares `bypassPermissions` keeps the main conversation's mode instead. The `bypassPermissions` exception requires Claude Code v2.1.267 or later.582* When the main conversation is in `default`, `dontAsk`, or `plan` mode, the subagent runs in the permission mode you set. It keeps the main conversation's permission mode instead in these cases:

583 * You set `bypassPermissions`. The `bypassPermissions` exception requires Claude Code v2.1.267 or later.

584 * You set `auto` and [auto mode isn't available](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) to the subagent, such as when a settings file sets [`disableAutoMode`](/docs/en/settings-reference#disableautomode) or the subagent's model doesn't support auto mode.

583 585 

584`permissionMode` accepts these values, and `manual` as an alias for `default`:586`permissionMode` accepts these values, and `manual` as an alias for `default`:

585 587 


608Implement API endpoints. Follow the conventions and patterns from the preloaded skills.610Implement API endpoints. Follow the conventions and patterns from the preloaded skills.

609```611```

610 612 

611The full content of each listed skill is injected into the subagent's context at startup. This field controls which skills are preloaded, not which skills the subagent can access: without it, the subagent can still discover and invoke project, user, and plugin skills through the Skill tool during execution. To prevent a subagent from invoking skills entirely, omit `Skill` from the [`tools`](#available-tools) list or add it to `disallowedTools`.613The full content of each listed skill is injected into the subagent's context at startup, up to the first 32 distinct names in the list. This field controls which skills are preloaded, not which skills the subagent can access: without it, the subagent can still discover and invoke project, user, and plugin skills through the Skill tool during execution. To prevent a subagent from invoking skills entirely, omit `Skill` from the [`tools`](#available-tools) list or add it to `disallowedTools`.

612 614 

613You can't preload skills that set [`disable-model-invocation: true`](/docs/en/skills#control-who-invokes-a-skill), since preloading draws from the same set of skills Claude can invoke. This includes the bundled `/verify` skill, which Claude can't run on its own.615You can't preload skills that set [`disable-model-invocation: true`](/docs/en/skills#control-who-invokes-a-skill), since preloading draws from the same set of skills Claude can invoke. This includes the bundled `/verify` skill, which Claude can't run on its own.

614 616 

Details

590 590 

591* WebFetch refuses `localhost` and any other hostname without a dot, such as a bare intranet name, before making a request. The [error it returns](/docs/en/errors#webfetch-cannot-fetch-localhost) tells Claude to reach local servers with `curl` through Bash instead.591* WebFetch refuses `localhost` and any other hostname without a dot, such as a bare intranet name, before making a request. The [error it returns](/docs/en/errors#webfetch-cannot-fetch-localhost) tells Claude to reach local servers with `curl` through Bash instead.

592* HTTP URLs are automatically upgraded to HTTPS.592* HTTP URLs are automatically upgraded to HTTPS.

593* Large pages are truncated to a fixed character limit before processing.593* WebFetch reads up to 100,000 characters of a page's content per call. On Claude Code v2.1.290 or later, the result for a longer page tells Claude how much went unread, so Claude can fetch the next part.

594* WebFetch caches each response for 15 minutes by default, so repeated fetches of the same URL return quickly. On Claude Code v2.1.233 or later, set [`CLAUDE_CODE_WEBFETCH_CACHE_TTL_MS`](/docs/en/env-vars#variables) to change how long WebFetch keeps each response.594* WebFetch caches each response for 15 minutes by default, so repeated fetches of the same URL return quickly. On Claude Code v2.1.233 or later, set [`CLAUDE_CODE_WEBFETCH_CACHE_TTL_MS`](/docs/en/env-vars#variables) to change how long WebFetch keeps each response.

595* A page that hasn't finished downloading within five minutes, including any redirects WebFetch follows, fails with a deadline error. On Claude Code v2.1.268 or later, set [`CLAUDE_CODE_WEBFETCH_DEADLINE_MS`](/docs/en/env-vars#variables) to change the limit, or to `0` to remove it.595* A page that hasn't finished downloading within five minutes, including any redirects WebFetch follows, fails with a deadline error. On Claude Code v2.1.268 or later, set [`CLAUDE_CODE_WEBFETCH_DEADLINE_MS`](/docs/en/env-vars#variables) to change the limit, or to `0` to remove it.

596* When a URL redirects to a different host, WebFetch returns a text result that names the original URL and the redirect target instead of following it. Claude then fetches the new URL with a second WebFetch call.596* When a URL redirects to a different host, WebFetch returns a text result that names the original URL and the redirect target instead of following it. Claude then fetches the new URL with a second WebFetch call.

Details

15| What you see | Solution |15| What you see | Solution |

16| :- | :- |16| :- | :- |

17| `command not found: claude` or `'claude' is not recognized` | [Fix your PATH](#command-not-found-claude-after-installation) |17| `command not found: claude` or `'claude' is not recognized` | [Fix your PATH](#command-not-found-claude-after-installation) |

18| `Native installation exists but ... is not in your PATH` | [Add the install directory to your PATH](#verify-your-path) |

19| `INFO: Could not find files for the given pattern(s).` from `where.exe claude` | [Check whether Claude Code is installed](#check-for-conflicting-installations) |

20| `zsh: permission denied: /Users/you/.zshrc` or `bash: /home/you/.bashrc: Permission denied` | [Make your shell config file writable](#permission-denied-when-adding-to-your-path) |

18| `syntax error near unexpected token '<'` | [Install script returns HTML](#install-script-returns-html-instead-of-a-shell-script) |21| `syntax error near unexpected token '<'` | [Install script returns HTML](#install-script-returns-html-instead-of-a-shell-script) |

22| `< was unexpected at this time` in CMD | [Install script returns HTML](#install-script-returns-html-instead-of-a-shell-script) |

23| `The term 'System.Xml.XmlDocument' is not recognized` | [Install script returns HTML](#install-script-returns-html-instead-of-a-shell-script) |

19| `curl: (22) The requested URL returned error: 403` | [Install script returned 403](#install-script-returns-html-instead-of-a-shell-script) |24| `curl: (22) The requested URL returned error: 403` | [Install script returned 403](#install-script-returns-html-instead-of-a-shell-script) |

20| `curl: (23)` or `curl: (56) Failure writing output to destination` | [Check connectivity or use an alternative installer](#curl-56-failure-writing-output-to-destination) |25| `curl: (23)` or `curl: (56) Failure writing output to destination` | [Check connectivity or use an alternative installer](#curl-56-failure-writing-output-to-destination) |

21| `Killed` during install on Linux, or `Installation was killed before it could finish (exit code 137)` | [Free memory or add swap space](#install-killed-on-low-memory-linux-servers) |26| `Killed` during install on Linux | [Free memory or add swap space](#install-killed-on-low-memory-linux-servers) |

27| `Installation was killed before it could finish` | [Free memory, then rerun the installer](#installation-was-killed-before-it-could-finish) |

22| `Raw mode is not supported` during install | [Rerun the installer](#raw-mode-is-not-supported-during-install) |28| `Raw mode is not supported` during install | [Rerun the installer](#raw-mode-is-not-supported-during-install) |

23| `EACCES: permission denied` during install | [Fix the install directory's permissions](#permission-errors-during-installation) |29| `EACCES: permission denied` during install | [Fix the install directory's permissions](#permission-errors-during-installation) |

24| `TLS connect error` or `SSL/TLS secure channel` | [Update CA certificates](#tls-or-ssl-connection-errors) |30| `TLS connect error` or `SSL/TLS secure channel` | [Update CA certificates](#tls-or-ssl-connection-errors) |

31| `CRYPT_E_NO_REVOCATION_CHECK` or `CRYPT_E_REVOCATION_OFFLINE` | [Work around blocked revocation checks](#tls-or-ssl-connection-errors) |

25| `Failed to fetch version` or can't reach download server | [Check network and proxy settings](#check-network-connectivity) |32| `Failed to fetch version` or can't reach download server | [Check network and proxy settings](#check-network-connectivity) |

33| `The connection dropped while downloading the update` or `Download timed out: exceeded the total deadline` | [Run the update again or set your proxy](#the-connection-dropped-while-downloading-the-update) |

26| `irm is not recognized` or `The token '&&' is not a valid statement separator` | [Use the right command for your shell](#wrong-install-command-on-windows) |34| `irm is not recognized` or `The token '&&' is not a valid statement separator` | [Use the right command for your shell](#wrong-install-command-on-windows) |

27| `Cask 'claude-code' is unavailable: No Cask with this name exists` | [Update Homebrew](#homebrew-cask-unavailable-or-outdated) |35| `Cask 'claude-code' is unavailable: No Cask with this name exists` | [Update Homebrew](#homebrew-cask-unavailable-or-outdated) |

36| `Cask 'claude-code@latest' is not installed` | [Upgrade the cask you installed](#cask-is-not-installed) |

28| `'bash' is not recognized as the name of a cmdlet` | [Use the Windows installer command](#wrong-install-command-on-windows) |37| `'bash' is not recognized as the name of a cmdlet` | [Use the Windows installer command](#wrong-install-command-on-windows) |

29| `A parameter cannot be found that matches parameter name 'fsSL'` | [Use the Windows installer command](#wrong-install-command-on-windows) |38| `A parameter cannot be found that matches parameter name 'fsSL'` | [Use the Windows installer command](#wrong-install-command-on-windows) |

30| `Claude Code on Windows requires either Git for Windows (for bash) or PowerShell` | [Install a shell](#claude-code-on-windows-requires-either-git-for-windows-for-bash-or-powershell) |39| `Claude Code on Windows requires either Git for Windows (for bash) or PowerShell` | [Install a shell](#claude-code-on-windows-requires-either-git-for-windows-for-bash-or-powershell) |


117 126 

118If installation succeeded but you get a `command not found` or `not recognized` error when running `claude`, the install directory isn't in your PATH. Your shell searches for programs in directories listed in PATH, and the installer places `claude` at `~/.local/bin/claude` on macOS/Linux or `%USERPROFILE%\.local\bin\claude.exe` on Windows.127If installation succeeded but you get a `command not found` or `not recognized` error when running `claude`, the install directory isn't in your PATH. Your shell searches for programs in directories listed in PATH, and the installer places `claude` at `~/.local/bin/claude` on macOS/Linux or `%USERPROFILE%\.local\bin\claude.exe` on Windows.

119 128 

129The installer detects this case and reports it under `Setup notes:` in its output: `Native installation exists but ~/.local/bin is not in your PATH.` on macOS and Linux, or `Native installation exists but C:\Users\you\.local\bin is not in your PATH.` on Windows. It prints the fix with that note but doesn't change PATH itself.

130 

120<Note>131<Note>

121 The [VS Code extension](/docs/en/vs-code) does not place `claude` at this location. It bundles a private copy of the CLI inside the extension directory for its own chat panel and does not add it to PATH. If you have only installed the extension, `~/.local/bin/claude` will not exist. Run the [standalone install](/docs/en/setup) to use `claude` from a terminal, then continue below.132 The [VS Code extension](/docs/en/vs-code) does not place `claude` at this location. It bundles a private copy of the CLI inside the extension directory for its own chat panel and does not add it to PATH. If you have only installed the extension, `~/.local/bin/claude` will not exist. Run the [standalone install](/docs/en/setup) to use `claude` from a terminal, then continue below.

122</Note>133</Note>

123 134 

124Check if the install directory is in your PATH by listing your PATH entries and filtering for `local/bin`:135First check that the program is there at all, then check whether its folder is in your PATH. The PATH fix is permanent, so you apply it once. Pick your platform's tab and run its commands there: in your terminal on macOS and Linux, or in PowerShell or Command Prompt on Windows.

125 136 

126<Tabs>137<Tabs>

127 <Tab title="macOS/Linux">138 <Tab title="macOS/Linux">

139 Check that the installer put the program in place:

140 

141 ```bash theme={null}

142 ls -la ~/.local/bin/claude

143 ```

144 

145 * **`No such file or directory`**: there's no native install. If you haven't installed Claude Code another way, such as with npm, Homebrew, or a Linux package manager, [install Claude Code](/docs/en/setup#install-claude-code). If you installed it another way, see [Check for conflicting installations](#check-for-conflicting-installations).

146 * **A listing for the file**: the program is there. Check your PATH next.

147 

148 List your PATH entries and filter for the install folder:

149 

128 ```bash theme={null}150 ```bash theme={null}

129 echo $PATH | tr ':' '\n' | grep -Fx "$HOME/.local/bin"151 echo $PATH | tr ':' '\n' | grep -Fx "$HOME/.local/bin"

130 ```152 ```

131 153 

132 If this prints `/Users/you/.local/bin` or `/home/you/.local/bin`, the directory is in your PATH and you can skip to [Check for conflicting installations](#check-for-conflicting-installations). If there's no output, add it to your shell configuration.154 If this prints `/Users/you/.local/bin` or `/home/you/.local/bin`, the directory is in your PATH and you can skip to [Check for conflicting installations](#check-for-conflicting-installations). If there's no output, add it to your shell configuration with the two commands for your shell. The `echo` command saves the setting for every new terminal, and `source` applies it to the window you're in. The `echo` command prints nothing when it succeeds.

133 155 

134 For Zsh, the default on macOS:156 For Zsh, the default on macOS:

135 157 


154 176 

155 Alternatively, close and reopen your terminal.177 Alternatively, close and reopen your terminal.

156 178 

179 If the `echo` command prints `permission denied`, see [`permission denied` when adding to your PATH](#permission-denied-when-adding-to-your-path).

180 

157 For other shells such as fish or Nushell, add `~/.local/bin` to your PATH using your shell's own configuration syntax, then restart your terminal.181 For other shells such as fish or Nushell, add `~/.local/bin` to your PATH using your shell's own configuration syntax, then restart your terminal.

158 182 

159 Verify the fix worked:183 Verify the fix worked:


161 ```bash theme={null}185 ```bash theme={null}

162 claude --version186 claude --version

163 ```187 ```

188 

189 If `claude` is still not found, check these causes:

190 

191 * **The terminal predates the change**: a window that was already open keeps its old PATH, and a terminal inside an editor takes its PATH from the editor. Open a new window, or quit and reopen the editor.

192 * **The line wasn't saved**: run `grep -n '.local/bin' ~/.zshrc`, using your shell's file name. It prints the line with its line number when the line is there. If it prints nothing, run the two PATH commands again.

193 * **The line went to another shell's file**: run `echo $0` to see your shell, then run the two PATH commands for that shell.

164 </Tab>194 </Tab>

165 195 

166 <Tab title="Windows PowerShell">196 <Tab title="Windows PowerShell">

197 Check that the installer put the program in place:

198 

199 ```powershell theme={null}

200 Test-Path "$env:USERPROFILE\.local\bin\claude.exe"

201 ```

202 

203 * **`False`**: there's no native install. If you haven't installed Claude Code another way, such as with npm or WinGet, [install Claude Code](/docs/en/setup#install-claude-code). If you installed it another way, see [Check for conflicting installations](#check-for-conflicting-installations).

204 * **`True`**: the program is there. Check your PATH next.

205 

206 List your PATH entries and filter for the install folder:

207 

167 ```powershell theme={null}208 ```powershell theme={null}

168 $env:PATH -split ';' | Select-String '\.local\\bin'209 $env:PATH -split ';' | Select-String '\.local\\bin'

169 ```210 ```

170 211 

171 If there's no output, add the install directory to your User PATH:212 If this prints `C:\Users\you\.local\bin`, the directory is in your PATH and you can skip to [Check for conflicting installations](#check-for-conflicting-installations). If there's no output, add the install directory to your User PATH:

172 213 

173 ```powershell theme={null}214 ```powershell theme={null}

174 $currentPath = [Environment]::GetEnvironmentVariable('PATH', 'User')215 $currentPath = [Environment]::GetEnvironmentVariable('PATH', 'User')


182 ```powershell theme={null}223 ```powershell theme={null}

183 claude --version224 claude --version

184 ```225 ```

226 

227 If `claude` is still not found in a new terminal, check these causes:

228 

229 * **The terminal runs inside an editor**: it takes its PATH from the editor, so quit and reopen the editor.

230 * **The change wasn't saved**: run `[Environment]::GetEnvironmentVariable('PATH', 'User')` and look for `.local\bin` in the PATH it prints. If it's missing, run the two commands again.

185 </Tab>231 </Tab>

186 232 

187 <Tab title="Windows CMD">233 <Tab title="Windows CMD">

234 Check that the installer put the program in place:

235 

236 ```batch theme={null}

237 dir "%USERPROFILE%\.local\bin\claude.exe"

238 ```

239 

240 * **`File Not Found` or `The system cannot find the path specified.`**: there's no native install. If you haven't installed Claude Code another way, such as with npm or WinGet, [install Claude Code](/docs/en/setup#install-claude-code). If you installed it another way, see [Check for conflicting installations](#check-for-conflicting-installations).

241 * **A listing for `claude.exe`**: the program is there. Check your PATH next.

242 

243 List your PATH entries and filter for the install folder:

244 

188 ```batch theme={null}245 ```batch theme={null}

189 echo %PATH% | findstr /i "local\bin"246 echo %PATH% | findstr /i "local\bin"

190 ```247 ```


196 ```batch theme={null}253 ```batch theme={null}

197 claude --version254 claude --version

198 ```255 ```

256 

257 If `claude` is still not found in a new terminal, a terminal inside an editor takes its PATH from the editor, so quit and reopen the editor too.

199 </Tab>258 </Tab>

200</Tabs>259</Tabs>

201 260 


211 which -a claude270 which -a claude

212 ```271 ```

213 272 

214 If this prints nothing, no `claude` is on your PATH yet. Go back to [Verify your PATH](#verify-your-path).273 If this prints `claude not found`, a `no claude in` line, or nothing, no `claude` is on your PATH. The next checks show whether one is installed at all.

215 274 

216 Check the three locations a `claude` binary can come from. `~/.local/bin/claude` is the native installer, `~/.claude/local/` is a legacy local npm install created by older versions of Claude Code, and the npm global list shows a `-g` install:275 Check the three locations a `claude` binary can come from. `~/.local/bin/claude` is the native installer, `~/.claude/local/` is a legacy local npm install created by older versions of Claude Code, and the npm global list shows a `-g` install:

217 276 


230 ```bash theme={null}289 ```bash theme={null}

231 npm -g ls @anthropic-ai/claude-code 2>/dev/null290 npm -g ls @anthropic-ai/claude-code 2>/dev/null

232 ```291 ```

292 

293 If `ls -la ~/.local/bin/claude` printed `No such file or directory`, there's no native install. If you haven't installed Claude Code another way, such as with npm, Homebrew, or a Linux package manager, [install Claude Code](/docs/en/setup#install-claude-code). If `~/.local/bin/claude` exists but `which -a claude` didn't list it, the folder isn't in your PATH: see [Verify your PATH](#verify-your-path).

233 </Tab>294 </Tab>

234 295 

235 <Tab title="Windows PowerShell">296 <Tab title="Windows PowerShell">


239 where.exe claude300 where.exe claude

240 ```301 ```

241 302 

303 If this prints `INFO: Could not find files for the given pattern(s).`, no `claude` is on your PATH.

304 

242 Check whether the native installer placed a binary:305 Check whether the native installer placed a binary:

243 306 

244 ```powershell theme={null}307 ```powershell theme={null}

245 Test-Path "$env:USERPROFILE\.local\bin\claude.exe"308 Test-Path "$env:USERPROFILE\.local\bin\claude.exe"

246 ```309 ```

310 

311 * **`True`**: the native install is there. If `where.exe` found nothing, its folder isn't in your PATH: see [Verify your PATH](#verify-your-path).

312 * **`False`**: there's no native install. If you haven't installed Claude Code another way, such as with npm or WinGet, [install Claude Code](/docs/en/setup#install-claude-code).

247 </Tab>313 </Tab>

248</Tabs>314</Tabs>

249 315 


350 416 

351### Install script returns HTML instead of a shell script417### Install script returns HTML instead of a shell script

352 418 

353When running the install command, you may see one of these errors:419The install command fails with one of these errors when what it downloaded isn't the install script.

420 

421**Bash or Zsh**: the error quotes the first line of the returned page.

354 422 

355```text theme={null}423```text theme={null}

356bash: line 1: syntax error near unexpected token `<'424bash: line 1: syntax error near unexpected token `<'

357bash: line 1: `<!DOCTYPE html>'425bash: line 1: `<!DOCTYPE html>'

358```426```

359 427 

360On PowerShell, the same problem appears as parse errors pointing into the returned page, with `iex` trying to run HTML and CSS as PowerShell:428**PowerShell, parse errors**: the errors point into the returned page, with `iex` trying to run HTML and CSS as PowerShell.

361 429 

362```text theme={null}430```text theme={null}

363iex : At line:1 char:2310431iex : At line:1 char:2310


368 436 

369The wording varies with the PowerShell version and system language: you may see `Missing expression after unary operator '--'` or a `ParserError` with `ParseException` instead. HTML tags or CSS in the quoted text identify this failure. If you download with `-OutFile install.ps1` instead, the saved file is the same web page, so that doesn't help either.437The wording varies with the PowerShell version and system language: you may see `Missing expression after unary operator '--'` or a `ParserError` with `ParseException` instead. HTML tags or CSS in the quoted text identify this failure. If you download with `-OutFile install.ps1` instead, the saved file is the same web page, so that doesn't help either.

370 438 

371Depending on how the request was routed, you may instead see a 403 with no HTML body:439**PowerShell, `System.Xml.XmlDocument`**: the error names this type instead of quoting the page.

440 

441```text theme={null}

442System.Xml.XmlDocument : The term 'System.Xml.XmlDocument' is not recognized as the name of a cmdlet, function, script

443file, or operable program.

444```

445 

446When `irm` can parse the response as XML, it returns an XML object instead of text, and `iex` then tries to run that object's type name as a command. The install script is PowerShell code and doesn't parse as XML, so this error also means the response was something other than the script. The wording around the type name varies with the PowerShell version and system language, but `System.Xml.XmlDocument` itself stays the same, so match on the type name.

447 

448**CMD**: you see this error, followed by the HTML of the returned page.

449 

450```text theme={null}

451< was unexpected at this time.

452 

453C:\Users\you><!DOCTYPE html>...

454```

455 

456The first line appears in your system language, so look for the HTML that follows it.

457 

458**A 403 with no page**: depending on how the request was routed, curl reports a 403 status with no HTML body.

372 459 

373```text theme={null}460```text theme={null}

374curl: (22) The requested URL returned error: 403461curl: (22) The requested URL returned error: 403

375```462```

376 463 

377These all mean the install URL returned an HTML page or an error status instead of the install script. If the HTML page says "App unavailable in region," Claude Code is not available in your country. See [supported countries](https://www.anthropic.com/supported-countries).464These all mean the install URL returned a web page, an XML document, or an error status instead of the install script. If the error output quotes "App unavailable in region," Claude Code isn't available in your country. See [supported countries](https://www.anthropic.com/supported-countries).

378 465 

379A bare 403 with no body often has the same cause, but it can also come from a corporate proxy or firewall blocking the download. If you are in a supported country and still see the 403, work through [Check network connectivity](#check-network-connectivity) before trying the alternative installers below, since those reach the same hosts.466A bare 403 with no body often has the same cause, but it can also come from a corporate proxy or firewall blocking the download. If you are in a supported country and still see the 403, work through [Check network connectivity](#check-network-connectivity) before trying the alternative installers below, since those reach the same hosts.

380 467 


382 469 

383**Solutions:**470**Solutions:**

384 471 

3851. **Use an alternative install method**:4721. **Retry after a few minutes**: the issue is often temporary. Wait and try the original command again.

473 

4742. **Use an alternative install method**: unlike a native install, a Homebrew or WinGet install [doesn't update itself by default](/docs/en/setup#auto-updates).

386 475 

387 On macOS, install via Homebrew:476 On macOS, install via Homebrew:

388 477 


398 487 

399 Then run `claude --version` to confirm: the command prints a version number such as `2.1.211 (Claude Code)`. If the shell reports `claude` isn't found, open a new terminal window and retry: the session you installed from keeps its old `PATH`.488 Then run `claude --version` to confirm: the command prints a version number such as `2.1.211 (Claude Code)`. If the shell reports `claude` isn't found, open a new terminal window and retry: the session you installed from keeps its old `PATH`.

400 489 

4012. **Retry after a few minutes**: the issue is often temporary. Wait and try the original command again.

402 

403### `command not found: claude` after installation490### `command not found: claude` after installation

404 491 

405The install finished but `claude` doesn't work. The exact error varies by platform:492The install finished but `claude` doesn't work. The exact error varies by platform:


415 502 

416Otherwise, see [Verify your PATH](#verify-your-path) for the fix on each platform.503Otherwise, see [Verify your PATH](#verify-your-path) for the fix on each platform.

417 504 

505### `permission denied` when adding to your PATH

506 

507If the `echo` command that adds `~/.local/bin` to your PATH prints `zsh: permission denied: /Users/you/.zshrc` or `bash: /home/you/.bashrc: Permission denied`, your user can't write to that file and nothing was saved. In your terminal, check who owns the file, using your shell's file name in place of `~/.zshrc`:

508 

509```bash theme={null}

510ls -l ~/.zshrc

511```

512 

513The third field of the output is the owner.

514 

515* **The owner is another user, such as `root`**: take ownership with `sudo chown $(whoami) ~/.zshrc`, which requires administrator rights.

516* **The owner is you**: the file is read-only. Make it writable with `chmod u+w ~/.zshrc`.

517 

518Then run the two PATH commands for your shell in [Verify your PATH](#verify-your-path) again.

519 

418### `curl: (56) Failure writing output to destination`520### `curl: (56) Failure writing output to destination`

419 521 

420The `curl ... | bash` command downloads the script and pipes it to Bash for execution. This error, and the related `curl: (23) Failure writing output to destination`, means Bash did not receive the complete script. Exit code 56 indicates the download itself was interrupted, and exit code 23 indicates curl could not write what it received to the pipe, usually because Bash exited early.522The `curl ... | bash` command downloads the script and pipes it to Bash for execution. This error, and the related `curl: (23) Failure writing output to destination`, means Bash did not receive the complete script. Exit code 56 indicates the download itself was interrupted, and exit code 23 indicates curl could not write what it received to the pipe, usually because Bash exited early.


432 534 

433If Homebrew installs an older Claude Code version than you expect, the same stale index is usually the cause. The `claude-code` cask tracks the stable channel and is typically about one week behind the latest release; for the newest version run `brew install --cask claude-code@latest` instead. See [Configure release channel](/docs/en/setup#configure-release-channel) for the difference between the two casks.535If Homebrew installs an older Claude Code version than you expect, the same stale index is usually the cause. The `claude-code` cask tracks the stable channel and is typically about one week behind the latest release; for the newest version run `brew install --cask claude-code@latest` instead. See [Configure release channel](/docs/en/setup#configure-release-channel) for the difference between the two casks.

434 536 

537<h3 id="cask-is-not-installed">

538 `Cask 'claude-code@latest' is not installed`

539</h3>

540 

541Homebrew offers two casks, `claude-code` and `claude-code@latest`. Running `brew upgrade --cask claude-code@latest` when that cask isn't the one installed prints `Error: Cask 'claude-code@latest' is not installed.` To see which cask you have, run this in your terminal:

542 

543```bash theme={null}

544brew list --cask | grep claude-code

545```

546 

547Upgrade the cask it prints. If it prints nothing, neither cask is installed.

548 

435### TLS or SSL connection errors549### TLS or SSL connection errors

436 550 

437Errors such as these mean the TLS handshake failed:551Errors such as these mean the TLS handshake failed:


441* PowerShell's `Could not create SSL/TLS secure channel`555* PowerShell's `Could not create SSL/TLS secure channel`

442* PowerShell's `Could not establish trust relationship for the SSL/TLS secure channel`556* PowerShell's `Could not establish trust relationship for the SSL/TLS secure channel`

443 557 

558For `CRYPT_E_NO_REVOCATION_CHECK` or `CRYPT_E_REVOCATION_OFFLINE`, go to step 4.

559 

444**Solutions:**560**Solutions:**

445 561 

4461. **Update your system CA certificates**:5621. **Update your system CA certificates**:


453 569 

454 On macOS, the system curl uses the Keychain trust store; updating macOS itself updates the root certificates.570 On macOS, the system curl uses the Keychain trust store; updating macOS itself updates the root certificates.

455 571 

4562. **On Windows, enable TLS 1.2** in PowerShell before running the installer:5722. **In Windows PowerShell 5.1, enable TLS 1.2**:

457 ```powershell theme={null}573 ```powershell theme={null}

458 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12574 [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

575 ```

576 Then run the installer in the same window:

577 ```powershell theme={null}

459 irm https://claude.ai/install.ps1 | iex578 irm https://claude.ai/install.ps1 | iex

460 ```579 ```

461 580 


509 628 

510The installer couldn't reach the download server. This typically means `downloads.claude.ai` is blocked on your network. See [Check network connectivity](#check-network-connectivity).629The installer couldn't reach the download server. This typically means `downloads.claude.ai` is blocked on your network. See [Check network connectivity](#check-network-connectivity).

511 630 

631### The connection dropped while downloading the update

632 

633The connection to the download server closed while `claude install` or `claude update` was fetching the Claude Code binary, and the retries didn't recover. Claude Code retries the download when the connection drops, the transfer stalls, or the downloaded file fails its checksum, up to three attempts in total. A completed HTTP error, such as a 404, isn't retried because the server already answered. Before v2.1.202, a single dropped connection failed the download immediately with the bare error `aborted` instead of retrying.

634 

635```text theme={null}

636The connection dropped while downloading the update (attempt 3/3: aborted). Check your network — proxies sometimes cut off large downloads.

637```

638 

639The text in parentheses names which attempt failed and the underlying network error. `claude update` precedes the message with `Error: Failed to install native update` on stderr.

640 

641A download that stays connected but doesn't finish within 10 minutes fails with `Download timed out: exceeded the total deadline` instead. Claude Code doesn't retry a timed-out download, because a connection too slow to finish inside the deadline won't finish on an immediate retry either. The steps below apply to both messages.

642 

643A proxy or gateway can close a long transfer before it finishes, and the Claude Code binary is a large download.

644 

645**What to do:**

646 

647* Run `claude update` again. On an otherwise healthy network, the download usually succeeds on the next run. For the timed-out message, run it again from a faster or less throttled network.

648* If your network requires a proxy, set `HTTPS_PROXY` before running the installer or `claude update`. See [Check network connectivity](#check-network-connectivity).

649* If a corporate proxy keeps closing the transfer, ask your network team to allow the full download from `downloads.claude.ai`. See [Network access requirements](/docs/en/network-config#network-access-requirements).

650* Run `claude doctor` from your shell for installation diagnostics

651 

512### Wrong install command on Windows652### Wrong install command on Windows

513 653 

514If you see `'irm' is not recognized`, `The token '&&' is not a valid statement separator`, `A parameter cannot be found that matches parameter name 'fsSL'`, or `'bash' is not recognized as the name of a cmdlet`, you copied the install command for a different shell or operating system. If the command prints the script's text instead of installing anything, you ran only part of it.654If you see `'irm' is not recognized`, `The token '&&' is not a valid statement separator`, `A parameter cannot be found that matches parameter name 'fsSL'`, or `'bash' is not recognized as the name of a cmdlet`, you copied the install command for a different shell or operating system. If the command prints the script's text instead of installing anything, you ran only part of it.


648 788 

6493. **Use a larger instance** if possible. Claude Code requires at least 4 GB of RAM.7893. **Use a larger instance** if possible. Claude Code requires at least 4 GB of RAM.

650 790 

791### Installation was killed before it could finish

792 

793The install script reports when the `claude install` step is terminated by a signal. On Linux, exit code 137 means the process received SIGKILL, and on a low-memory host that's usually the kernel out-of-memory (OOM) killer. The script prints this explanation and exits with code 137:

794 

795```text theme={null}

796Installation was killed before it could finish (exit code 137). This usually means the system ran out of memory.

797Claude Code needs roughly 512MB of free memory to install. Free up memory, then run this script again.

798```

799 

800For any other fatal signal, and for exit code 137 on macOS, the script prints `Installation was killed before it could finish (exit code <N>)` with the actual exit code and omits the out-of-memory explanation. The message comes from the install script macOS and Linux use, which also covers installs inside WSL; the native Windows install scripts never print it. Before v2.1.200, the script exited with only the shell's bare `Killed` line.

801 

802**What to do:**

803 

804* Stop other processes to free memory, then rerun the installer

805* Add swap space or move to a larger instance. See [Install killed on low-memory Linux servers](#install-killed-on-low-memory-linux-servers) for the swap-file commands.

806 

651### Install hangs in Docker807### Install hangs in Docker

652 808 

653When installing Claude Code in a Docker container, installing as root into `/` can cause hangs.809When installing Claude Code in a Docker container, installing as root into `/` can cause hangs.

Details

11| Symptom | Go to |11| Symptom | Go to |

12| :- | :- |12| :- | :- |

13| `command not found`, install fails, PATH issues, `EACCES`, TLS errors | [Troubleshoot installation and login](/docs/en/troubleshoot-install) |13| `command not found`, install fails, PATH issues, `EACCES`, TLS errors | [Troubleshoot installation and login](/docs/en/troubleshoot-install) |

14| Update or install download fails with `The connection dropped while downloading the update` or `aborted` | [Error reference](/docs/en/errors#the-connection-dropped-while-downloading-the-update) |14| Update or install download fails with `The connection dropped while downloading the update` or `aborted` | [Troubleshoot installation and login](/docs/en/troubleshoot-install#the-connection-dropped-while-downloading-the-update) |

15| Login loops, OAuth errors, `403 Forbidden`, "organization disabled", Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry credentials | [Troubleshoot installation and login](/docs/en/troubleshoot-install#login-and-authentication) |15| Login loops, OAuth errors, `403 Forbidden`, "organization disabled", Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry credentials | [Troubleshoot installation and login](/docs/en/troubleshoot-install#login-and-authentication) |

16| Settings not applying, hooks not firing, MCP servers not loading | [Debug your configuration](/docs/en/debug-your-config) |16| Settings not applying, hooks not firing, MCP servers not loading | [Debug your configuration](/docs/en/debug-your-config) |

17| Session started in auto mode, or Claude edits files and runs commands without asking | [Which mode a session starts in](/docs/en/permission-modes#which-mode-a-session-starts-in) |17| Session started in auto mode, or Claude edits files and runs commands without asking | [Which mode a session starts in](/docs/en/permission-modes#which-mode-a-session-starts-in) |

ultrareview.md +6 −6

Details

50 50 

51### Review a pull request51### Review a pull request

52 52 

53To review a GitHub pull request instead of a local branch, pass the PR number:53To review a pull request on `github.com` instead of a local branch, pass the PR number:

54 54 

55```text theme={null}55```text theme={null}

56/code-review ultra 123456/code-review ultra 1234


58 58 

59The command also accepts `#1234`, `PR 1234`, and pasted PR URLs; a pasted URL must point to the repository in your current directory.59The command also accepts `#1234`, `PR 1234`, and pasted PR URLs; a pasted URL must point to the repository in your current directory.

60 60 

61In PR mode, the cloud sandbox clones the pull request directly from the host rather than bundling your local working tree. PR mode works with repositories on `github.com` and on [GitHub Enterprise Server](/docs/en/github-enterprise-server) instances that an Owner has connected to Claude Code.61PR mode needs a repository on `github.com`. For a repository on a [GitHub Enterprise Server](/docs/en/github-enterprise-server) instance, run `/code-review ultra` without a PR number to review your local branch instead.

62 62 

63For repositories on `github.com`, the sandbox clones with the GitHub account connected to your Claude account, so the account must be able to read the PR's repository.63In PR mode, the cloud sandbox clones the pull request from `github.com` instead of uploading your working tree. It uses the GitHub account connected to your Claude account, so that account needs read access to the repository.

64 64 

65Run [`/web-setup`](/docs/en/web-quickstart#connect-from-your-terminal) to connect your GitHub CLI login to your Claude account.65Run [`/web-setup`](/docs/en/web-quickstart#connect-from-your-terminal) to connect your GitHub CLI login to your Claude account.

66 66 

67### Post findings to the pull request67### Post findings to the pull request

68 68 

69On Claude Code v2.1.227 or later, when you review a pull request on `github.com`, you can have Claude post the finished findings to the PR as a single plain comment from your own GitHub account. The comment isn't a review or an approval, and it ends with a "Generated by Claude Code" note. When you review a branch or a GitHub Enterprise Server pull request, Claude Code shows the findings in your session only.69On Claude Code v2.1.227 or later, when you review a pull request on `github.com`, you can have Claude post the finished findings to the PR as a single plain comment from your own GitHub account. The comment isn't a review or an approval, and it ends with a "Generated by Claude Code" note. When you review a branch, Claude Code shows the findings in your session only.

70 70 

71Claude Code never posts unless you choose to on that run, and `--no-post` is the default. Posting is a choice you make for each run:71Claude Code never posts unless you choose to on that run, and `--no-post` is the default. Posting is a choice you make for each run:

72 72 


96Claude Code treats your text as a note only when it has more than one word and isn't a branch name or PR reference. It reads a single word as a branch name or PR reference, so a mistyped branch name gets the closest-branch error from [Review against a different base](#review-against-a-different-base) instead of launching with a note. If your text combines a PR reference with other words, such as `check PR 123 again`, Claude Code doesn't launch either; it asks you to rerun with the PR number alone to review that PR, or without the reference to review your current branch.96Claude Code treats your text as a note only when it has more than one word and isn't a branch name or PR reference. It reads a single word as a branch name or PR reference, so a mistyped branch name gets the closest-branch error from [Review against a different base](#review-against-a-different-base) instead of launching with a note. If your text combines a PR reference with other words, such as `check PR 123 again`, Claude Code doesn't launch either; it asks you to rerun with the PR number alone to review that PR, or without the reference to review your current branch.

97 97 

98<Tip>98<Tip>

99 If your repository is too large to bundle, Claude Code prompts you to use PR mode instead. Push your branch and open a draft PR, then run `/code-review ultra <PR-number>`.99 If your repository is too large to bundle, Claude Code prompts you to use PR mode instead. For a repository on `github.com`, push your branch and open a draft PR, then run `/code-review ultra <PR-number>`.

100</Tip>100</Tip>

101 101 

102### Diff limits and fallbacks102### Diff limits and fallbacks


155claude ultrareview origin/main155claude ultrareview origin/main

156```156```

157 157 

158Without arguments, the subcommand reviews the diff between your current branch and the default branch, with the same [whole-repository fallback](#diff-limits-and-fallbacks) as `/code-review ultra` when no merge base exists. Pass a PR number to review a pull request, or a base branch to review against it; [base-branch handling](#review-against-a-different-base) matches the interactive command.158Without arguments, the subcommand reviews the diff between your current branch and the default branch, with the same [whole-repository fallback](#diff-limits-and-fallbacks) as `/code-review ultra` when no merge base exists. Pass a PR number to [review a pull request on `github.com`](#review-a-pull-request), or a base branch to review against it; [base-branch handling](#review-against-a-different-base) matches the interactive command.

159 159 

160You consent to the whole-repository fallback and to the billing and terms prompt when you run the subcommand, so the run starts without waiting for input. Running it yourself is what counts as consent. When Claude runs the subcommand for you instead, for example through the Bash tool, Claude Code refuses the whole-repository review.160You consent to the whole-repository fallback and to the billing and terms prompt when you run the subcommand, so the run starts without waiting for input. Running it yourself is what counts as consent. When Claude runs the subcommand for you instead, for example through the Bash tool, Claude Code refuses the whole-repository review.

161 161 

vs-code.md +2 −0

Details

158* **Bookmarks**: hover over a response and click **Bookmark response** to save it, or click **Remove bookmark** on a saved response to remove it.158* **Bookmarks**: hover over a response and click **Bookmark response** to save it, or click **Remove bookmark** on a saved response to remove it.

159 159 

160 To review saved responses, open the Bookmarks panel: click the bookmark icon at the top of the Claude Code panel, select **Bookmarks** in the Context section of the command menu, or type `/bookmarks`. Requires Claude Code v2.1.286 or later.160 To review saved responses, open the Bookmarks panel: click the bookmark icon at the top of the Claude Code panel, select **Bookmarks** in the Context section of the command menu, or type `/bookmarks`. Requires Claude Code v2.1.286 or later.

161* **Files Claude sends you**: when the session is connected to [Remote Control](/docs/en/remote-control#start-a-remote-control-session) and Claude sends you files with the [`SendUserFile` tool](/docs/en/tools-reference), the conversation shows a row such as **Sent report.md, chart.png**. Click a file's name to open it in the editor.

161* **Context indicator**: the prompt box shows how much of Claude's context window you're using. Claude automatically compacts when needed, or you can run `/compact` manually.162* **Context indicator**: the prompt box shows how much of Claude's context window you're using. Claude automatically compacts when needed, or you can run `/compact` manually.

162* **Prompt cache clock**: a clock icon next to the context indicator estimates how much time the conversation's [prompt cache](/docs/en/prompt-caching) has left before it expires. It counts down from the cache's five-minute or one-hour [lifetime](/docs/en/prompt-caching#cache-lifetime), and each response that uses the cache restarts the countdown. Apart from compaction, the [actions that invalidate the cache](/docs/en/prompt-caching#actions-that-invalidate-the-cache) don't reset the clock, so it can still show minutes left after you switch models.163* **Prompt cache clock**: a clock icon next to the context indicator estimates how much time the conversation's [prompt cache](/docs/en/prompt-caching) has left before it expires. It counts down from the cache's five-minute or one-hour [lifetime](/docs/en/prompt-caching#cache-lifetime), and each response that uses the cache restarts the countdown. Apart from compaction, the [actions that invalidate the cache](/docs/en/prompt-caching#actions-that-invalidate-the-cache) don't reset the clock, so it can still show minutes left after you switch models.

163 * Until the countdown runs out, the icon shows the minutes left, such as **12m**.164 * Until the countdown runs out, the icon shows the minutes left, such as **12m**.


545| `useCtrlEnterToSend` | `false` | Use Ctrl/Cmd+Enter instead of Enter to send prompts |546| `useCtrlEnterToSend` | `false` | Use Ctrl/Cmd+Enter instead of Enter to send prompts |

546| `scrollToBottomOnSend` | `true` | Scroll the conversation to the bottom when you send a message. When off, the conversation stays where you left it. Requires Claude Code v2.1.275 or later |547| `scrollToBottomOnSend` | `true` | Scroll the conversation to the bottom when you send a message. When off, the conversation stays where you left it. Requires Claude Code v2.1.275 or later |

547| `showMessageTimestamps` | `true` | Show when each message was sent. A date line marks where the day changes. Requires Claude Code v2.1.284 or later. Before v2.1.290, the default was `false` |548| `showMessageTimestamps` | `true` | Show when each message was sent. A date line marks where the day changes. Requires Claude Code v2.1.284 or later. Before v2.1.290, the default was `false` |

549| `spinnerVerbs` | `{"mode": "append", "verbs": []}` | Set the verbs the conversation spinner rotates through while a turn runs, with the same `mode` and `verbs` fields as the CLI's [`spinnerVerbs`](/docs/en/settings-reference#spinnerverbs). |

548| `enableNewConversationShortcut` | `false` | Enable Cmd/Ctrl+N to start a new conversation |550| `enableNewConversationShortcut` | `false` | Enable Cmd/Ctrl+N to start a new conversation |

549| `enableReopenClosedSessionShortcut` | `true` | Use Cmd/Ctrl+Shift+T to reopen the most recently closed Claude session tab. When the last closed tab wasn't a Claude session, the shortcut runs VS Code's normal reopen-closed-editor command instead. |551| `enableReopenClosedSessionShortcut` | `true` | Use Cmd/Ctrl+Shift+T to reopen the most recently closed Claude session tab. When the last closed tab wasn't a Claude session, the shortcut runs VS Code's normal reopen-closed-editor command instead. |

550| `archiveInactiveSessions` | `14` | [Archive a session automatically](#resume-past-conversations) after this many days without activity: `1`, `2`, `7`, or `14`. Set `0` to turn it off. Requires Claude Code v2.1.265 or later |552| `archiveInactiveSessions` | `14` | [Archive a session automatically](#resume-past-conversations) after this many days without activity: `1`, `2`, `7`, or `14`. Set `0` to turn it off. Requires Claude Code v2.1.265 or later |

workflows.md +25 −1

Details

312 312 

313The body is plain JavaScript with top-level `await`. `agent()` spawns one subagent, `pipeline()` runs one per item in a list, and `parallel()` runs a set of agent tasks at the same time and waits for all of them.313The body is plain JavaScript with top-level `await`. `agent()` spawns one subagent, `pipeline()` runs one per item in a list, and `parallel()` runs a set of agent tasks at the same time and waits for all of them.

314 314 

315An `agent()` call resolves to `null` if you stop it mid-run or it hits an unrecoverable API error. `pipeline()` keeps each `null` in the results array, which is why the example ends with `.filter(Boolean)` to drop those entries.315An `agent()` call resolves to `null` if you stop it mid-run or it hits an unrecoverable API error. `pipeline()` keeps each `null` in the results array, which is why the example ends with `.filter(Boolean)` to drop those entries, including the slot of [an agent that stalled on every attempt](#when-an-agent-stalls-and-restarts).

316 316 

317In [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode), the prompt your script passes to `agent()` doesn't count as a request from you when the classifier reviews that subagent's actions, because Claude Code marks it as text the script computed.317In [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode), the prompt your script passes to `agent()` doesn't count as a request from you when the classifier reviews that subagent's actions, because Claude Code marks it as text the script computed.

318 318 


407* The limit resets within 24 hours. A weekly limit can reset further out.407* The limit resets within 24 hours. A weekly limit can reset further out.

408* The run hasn't already waited twice. When it hits the limit a third time, the agent fails.408* The run hasn't already waited twice. When it hits the limit a third time, the agent fails.

409 409 

410### When an agent stalls and restarts

411 

412An agent whose output stops arriving for long enough starts over from the same prompt. In [`/workflows`](#watch-the-run), its name gains a `(retry 1)` suffix and its detail shows `attempt 2 (stalled)`. The restart is automatic, so you don't need to do anything.

413 

414The new attempt starts without the stalled attempt's transcript. Files the stalled attempt already changed stay changed, and the tokens it spent stay in the run's total. The stall window is how long Claude Code waits for output from an agent before it ends the attempt. Time the agent spends waiting on its own tool calls or on a [usage-limit reset](#when-a-run-hits-your-usage-limit) doesn't count toward the stall window.

415 

416An agent restarts at most five times, counting any restart you ask for with `r`. If the sixth attempt stalls as well, the `agent()` call fails, and the start of the error says why:

417 

418* `agent stalled on all 6 attempts`: every attempt went the whole window without output. If the agent's work keeps it silent that long, lengthen the window

419* `agent lost its reply on all 6 attempts`: every attempt's response stream went silent and Claude Code gave up waiting on it. Lengthening the stall window doesn't help, since a [streaming idle watchdog](/docs/en/network-config#streaming-idle-watchdogs) ended the response first and `CLAUDE_STREAM_IDLE_TIMEOUT_MS` sets that watchdog's timeout

420* `agent abandoned after 6 attempts`: the attempts ended in different ways, which the error lists in order

421 

422To give an agent more time to produce output before the window ends:

423 

424* **One agent**: pass `stallMs` in milliseconds on its `agent()` call, such as `agent(prompt, { stallMs: 1800000 })` for 30 minutes

425* **Every agent**: set [`CLAUDE_ASYNC_AGENT_STALL_TIMEOUT_MS`](/docs/en/env-vars#variables), which also applies to subagents outside workflows

426 

427Whether the run continues after the failure depends on how your script called the agent:

428 

429* **Inside [`parallel()` or `pipeline()`](#what-the-saved-script-looks-like)**: the run carries on with `null` in place of the agent's result

430* **Awaited directly**: the run ends with the error

431 

432To try again, ask Claude to relaunch the workflow. [Resume after a pause](#resume-after-a-pause) covers what runs again.

433 

410### Cost434### Cost

411 435 

412A workflow spawns many agents, so a single run can use meaningfully more tokens than working through the same task in conversation. Runs count toward your plan's usage and rate limits.436A workflow spawns many agents, so a single run can use meaningfully more tokens than working through the same task in conversation. Runs count toward your plan's usage and rate limits.

worktrees.md +1 −1

Details

92* **Git redirects**: Claude Code blocks a Bash or Monitor command that redirects git into the main checkout. The redirect can come through `git -C`, `--git-dir`, a `GIT_DIR` or `GIT_WORK_TREE` variable, or a `cd` into the main checkout before running git.92* **Git redirects**: Claude Code blocks a Bash or Monitor command that redirects git into the main checkout. The redirect can come through `git -C`, `--git-dir`, a `GIT_DIR` or `GIT_WORK_TREE` variable, or a `cd` into the main checkout before running git.

93* **Command shape**: Claude Code blocks a Bash or Monitor command when it can't verify from the command text that any git the command runs stays inside the worktree. That happens, for example, when the command name is computed at runtime, when the syntax can't be parsed, or when an expansion such as `${!name}` or `${ command; }` could run a command the text doesn't spell out. Claude Code tells Claude how to rewrite the refused command, such as splitting it into plain, separate commands. You can't turn this check off.93* **Command shape**: Claude Code blocks a Bash or Monitor command when it can't verify from the command text that any git the command runs stays inside the worktree. That happens, for example, when the command name is computed at runtime, when the syntax can't be parsed, or when an expansion such as `${!name}` or `${ command; }` could run a command the text doesn't spell out. Claude Code tells Claude how to rewrite the refused command, such as splitting it into plain, separate commands. You can't turn this check off.

94 94 

95These checks read the path an edit targets, the directory a command runs in, and the text of the command. None of them tracks which files a shell command writes, so a command that writes into the main checkout without running git there, such as `cp` or a shell redirect, isn't refused by them. Claude Code treats that command like any other shell command, so whether it runs or prompts you depends on your [permission mode](/docs/en/permission-modes) and rules.95These checks read the path an edit targets, the directory a command runs in, and the text of the command. None of them tracks which files a shell command writes, so a command that writes into the main checkout without running git there, such as `cp` or a shell redirect, isn't refused by them. Claude Code treats that command like any other shell command under your [permissions](/docs/en/permissions) and [sandboxing](/docs/en/sandboxing) settings.

96 96 

97The checks apply to the repository you launched Claude Code from. They also cover the main checkout a linked worktree is linked from. For PowerShell commands, Claude Code applies only the working-directory check.97The checks apply to the repository you launched Claude Code from. They also cover the main checkout a linked worktree is linked from. For PowerShell commands, Claude Code applies only the working-directory check.

98 98