One read of Claude Code CLIclaude-code-20260928T233702Z
154 pages moved out of 210 read.
Pages moved
154
significant first
Pages read
210
in this capture
Captured
23:37 UTC
Corpus hash
82a8d4497843
corpus-hash
What this read moved
76-100 of 154, page 4 of 7This capture is too large to show at once. Changes 76-100 of 154 are below, significant first; the rest are on the following screens.
goal Changed · +5 / -5 lines
from line 15
1515
1616Three approaches keep the current session running between prompts. Pick based on what should start the next turn:
1717
18| Approach | Next turn starts when | Stops when |
19| :------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
20| `/goal` | The previous turn finishes, or, in an interactive session, an [idle check-in](#background-work-defers-evaluation) or an [automatic retry](#other-errors-retry-or-pause-the-goal) comes due | A model confirms the condition is met or judges it impossible, or a turn fails on [an error you have to fix](#errors-you-have-to-fix-clear-the-goal), or you run [`/goal clear`](#clear-a-goal) |
21| [`/loop`](/docs/en/scheduled-tasks#run-a-prompt-repeatedly-with-%2Floop) | A time interval elapses | You stop it, or Claude decides the work is done |
22| [Stop hook](/docs/en/hooks-guide#prompt-based-hooks) | The previous turn finishes | Your own script or prompt decides |
18| Approach | Next turn starts when | Stops when |
19| :- | :- | :- |
20| `/goal` | The previous turn finishes, or, in an interactive session, an [idle check-in](#background-work-defers-evaluation) or an [automatic retry](#other-errors-retry-or-pause-the-goal) comes due | A model confirms the condition is met or judges it impossible, or a turn fails on [an error you have to fix](#errors-you-have-to-fix-clear-the-goal), or you run [`/goal clear`](#clear-a-goal) |
21| [`/loop`](/docs/en/scheduled-tasks#run-a-prompt-repeatedly-with-%2Floop) | A time interval elapses | You stop it, or Claude decides the work is done |
22| [Stop hook](/docs/en/hooks-guide#prompt-based-hooks) | The previous turn finishes | Your own script or prompt decides |
2323
2424`/goal` and a Stop hook both fire after every turn. `/goal` is a session-scoped shortcut: you type a condition and it's active for the current session only. A Stop hook lives in your settings file, applies to every session in its scope, and can run a script for deterministic checks or a prompt for model-evaluated ones.
2525
google-vertex-ai Changed · +3 / -3 lines
from line 226
226226
227227Claude Code uses these default models when no pinning variables are set:
228228
229| Model type | Default value |
230| :--------------- | :--------------------------- |
231| Primary model | `claude-opus-5-5` |
229| Model type | Default value |
230| :- | :- |
231| Primary model | `claude-opus-5-5` |
232232| Small/fast model | `claude-sonnet-4-5@20250929` |
233233
234234Background tasks such as session title generation use the small/fast model, normally a Haiku-class model. On Google Cloud's Agent Platform, Claude Code uses the default Sonnet model for background tasks because Haiku may not be enabled in every project or region. Two selections change which model carries them:
headless Changed · +33 / -33 lines
from line 46
4646
4747In bare mode Claude has access to the Bash, file read, and file edit tools. Pass any context you need with a flag:
4848
49| To load | Use |
50| ----------------------- | ------------------------------------------------------- |
49| To load | Use |
50| - | - |
5151| System prompt additions | `--append-system-prompt`, `--append-system-prompt-file` |
52| Settings | `--settings <file-or-json>` |
53| MCP servers | `--mcp-config <file-or-json>` |
54| Custom agents | `--agents <json>` |
55| A plugin | `--plugin-dir <path>`, `--plugin-url <url>` |
52| Settings | `--settings <file-or-json>` |
53| MCP servers | `--mcp-config <file-or-json>` |
54| Custom agents | `--agents <json>` |
55| A plugin | `--plugin-dir <path>`, `--plugin-url <url>` |
5656
5757<Note>
5858 `--bare` is the recommended mode for scripted and SDK calls, and will become the default for `-p` in a future release.
from line 200
200200
201201When an API request fails with a retryable error, Claude Code emits a `system/api_retry` event before retrying. On v2.1.246 or later, when a `401` or `403` rejects an [`apiKeyHelper`](/docs/en/settings-reference#apikeyhelper) credential, Claude Code makes the first two retries quietly with no event, then emits the event as usual from the third consecutive retry onward. The quiet retries still count toward `attempt`. You can use the event to show retry progress in your own interface.
202202
203| Field | Type | Description |
204| ---------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
205| `type` | `"system"` | message type |
206| `subtype` | `"api_retry"` | identifies this as a retry event |
207| `attempt` | integer | current attempt number, starting at 1 |
208| `max_retries` | integer | total retries permitted for this failure's cause, which can be fewer than the session-wide budget |
209| `retry_delay_ms` | integer | milliseconds until the next attempt |
210| `error_status` | integer or null | HTTP status code of the failed attempt, or `null` when the attempt got no HTTP response from the API |
211| `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 |
212| `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` |
213| `uuid` | string | unique event identifier |
214| `session_id` | string | session the event belongs to |
203| Field | Type | Description |
204| - | - | - |
205| `type` | `"system"` | message type |
206| `subtype` | `"api_retry"` | identifies this as a retry event |
207| `attempt` | integer | current attempt number, starting at 1 |
208| `max_retries` | integer | total retries permitted for this failure's cause, which can be fewer than the session-wide budget |
209| `retry_delay_ms` | integer | milliseconds until the next attempt |
210| `error_status` | integer or null | HTTP status code of the failed attempt, or `null` when the attempt got no HTTP response from the API |
211| `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 |
212| `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` |
213| `uuid` | string | unique event identifier |
214| `session_id` | string | session the event belongs to |
215215
216216#### Read session metadata
217217
from line 226
226226
227227Use the plugin fields in the `system/init` event to catch a plugin that didn't load:
228228
229| Field | Type | Description |
230| --------------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
231| `plugins` | array | plugins that loaded successfully, each with `name` and `path` |
229| Field | Type | Description |
230| - | - | - |
231| `plugins` | array | plugins that loaded successfully, each with `name` and `path` |
232232| `plugin_errors` | array | plugin load-time errors, each with `plugin`, `type`, and `message`. Includes unsatisfied dependency versions and `--plugin-dir` load failures such as a missing path or invalid archive. A plugin that didn't load is absent from `plugins`. The key is omitted when there are no errors |
233233
234234When a `--plugin-dir` directory or archive itself fails to load, its `plugin_errors` entry includes the resolved absolute path as `path`. Use it to tell which of several `--plugin-dir` values failed. The `path` field requires Claude Code v2.1.283 or later.
from line 237
237237
238238Claude Code validates each `--mcp-config` entry at startup and skips entries that fail validation, for example a `url` entry with no `type`. The run continues and exits cleanly, so check these fields to catch a server that never loaded:
239239
240| Field | Type | Description |
241| ------------------- | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
242| `mcp_servers` | array | MCP servers in the session, each with `name` and `status` |
240| Field | Type | Description |
241| - | - | - |
242| `mcp_servers` | array | MCP servers in the session, each with `name` and `status` |
243243| `mcp_server_errors` | array | `--mcp-config` entries skipped by config validation, each with `name`, `type`, and `message`. `type` is a skip category such as `unknown_type`, `url_missing_type`, `invalid_config`, or `reserved_name`; treat values you don't recognize as a generic skip. Affected servers are absent from `mcp_servers`. The key is omitted when there are no errors, so a CI gate can fail on a non-empty array. Requires Claude Code v2.1.219 or later |
244244
245245When you run the command by hand in a terminal, Claude Code also prints a startup warning to stderr, such as `Warning: 1 MCP server skipped due to invalid config:`, followed by the reason for each skipped entry. When you redirect stderr, or when a program such as a CI runner or an SDK host captures it, Claude Code prints no warning and reports the skipped entries only in the `mcp_server_errors` field. The warning requires Claude Code v2.1.219 or later.
from line 248
248248
249249When [`CLAUDE_CODE_SYNC_PLUGIN_INSTALL`](/docs/en/env-vars) is set, Claude Code emits `system/plugin_install` events while marketplace plugins install before the first turn. Use these to surface install progress in your own UI.
250250
251| Field | Type | Description |
252| ------------ | -------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
253| `type` | `"system"` | message type |
254| `subtype` | `"plugin_install"` | identifies this as a plugin install event |
255| `status` | `"started"`, `"installed"`, `"failed"`, or `"completed"` | `started` and `completed` bracket the overall install; `installed` and `failed` report individual marketplaces |
256| `name` | string, optional | marketplace name, present on `installed` and `failed` |
257| `error` | string, optional | failure message, present on `failed` |
258| `uuid` | string | unique event identifier |
259| `session_id` | string | session the event belongs to |
251| Field | Type | Description |
252| - | - | - |
253| `type` | `"system"` | message type |
254| `subtype` | `"plugin_install"` | identifies this as a plugin install event |
255| `status` | `"started"`, `"installed"`, `"failed"`, or `"completed"` | `started` and `completed` bracket the overall install; `installed` and `failed` report individual marketplaces |
256| `name` | string, optional | marketplace name, present on `installed` and `failed` |
257| `error` | string, optional | failure message, present on `failed` |
258| `uuid` | string | unique event identifier |
259| `session_id` | string | session the event belongs to |
260260
261261### Auto-approve tools
262262
hooks Changed · +492 / -492 lines
This page is larger than the 256 KiB this site keeps, so one side of the diff below stops where the stored text does.
The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.
from line 28
2828
2929The table below summarizes when each event fires. The [Hook events](#hook-events) section documents the full input schema and decision control options for each one.
3030
31| Event | When it fires |
32| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
33| `SessionStart` | When a session begins or resumes |
34| `Setup` | When you start Claude Code with `--init-only`, or with `--init` or `--maintenance` in `-p` mode. For one-time preparation in CI or scripts |
35| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |
36| `UserPromptExpansion` | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |
37| `PreToolUse` | Before a tool call executes. Can block it |
38| `PermissionRequest` | When a tool call needs a permission decision |
39| `PermissionDenied` | When auto mode denies a tool call, including denials without a classifier verdict. Use JSON `hookSpecificOutput.retry: true` to tell the model it may retry the denied tool call. Claude Code ignores `retry` when the classifier produced no verdict |
40| `PostToolUse` | After a tool call succeeds |
41| `PostToolUseFailure` | After a tool call fails |
42| `PostToolBatch` | After a full batch of parallel tool calls resolves, before the next model call |
43| `Notification` | When Claude Code sends a notification |
44| `MessageDisplay` | While assistant message text is displayed |
45| `SubagentStart` | When a subagent is spawned |
46| `SubagentStop` | When a subagent finishes |
47| `TaskCreated` | When a task is being created via `TaskCreate` |
48| `TaskCompleted` | When a task is being marked as completed |
49| `Stop` | When Claude finishes responding |
50| `StopFailure` | When the turn ends due to an API error |
51| `TeammateIdle` | When an [agent team](/docs/en/agent-teams) teammate is about to go idle |
52| `InstructionsLoaded` | When a CLAUDE.md or `.claude/rules/*.md` file is loaded into context. Fires at session start and when files are lazily loaded during a session |
53| `ConfigChange` | When a configuration file changes during a session |
54| `CwdChanged` | When the working directory changes, for example when Claude executes a `cd` command. Useful for reactive environment management with tools like direnv |
55| `DirectoryAdded` | When a working directory is added mid-session via `/add-dir` or the SDK `register_repo_root` control request |
56| `FileChanged` | When a watched file changes on disk. The `matcher` field specifies which filenames to watch |
57| `WorktreeCreate` | When a worktree is being created via `--worktree`, `isolation: "worktree"`, or for a background session. Replaces default git behavior |
58| `WorktreeRemove` | When a worktree is being removed at session exit, when a subagent finishes, or when you delete a background session |
59| `PreCompact` | Before context compaction |
60| `PostCompact` | After context compaction completes |
61| `PreModelSwitch` | Before Claude Code applies a model switch that you or a client requested. Can block the switch |
62| `PostModelSwitch` | After the session's model changes, including changes Claude Code makes on its own, such as restoring the model when you resume a session |
63| `Elicitation` | When an MCP server requests user input during a tool call |
64| `ElicitationResult` | After a user responds to an MCP elicitation, before the response is sent back to the server |
65| `SessionEnd` | When a session terminates |
31| Event | When it fires |
32| :- | :- |
33| `SessionStart` | When a session begins or resumes |
34| `Setup` | When you start Claude Code with `--init-only`, or with `--init` or `--maintenance` in `-p` mode. For one-time preparation in CI or scripts |
35| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |
36| `UserPromptExpansion` | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |
37| `PreToolUse` | Before a tool call executes. Can block it |
38| `PermissionRequest` | When a tool call needs a permission decision |
39| `PermissionDenied` | When auto mode denies a tool call, including denials without a classifier verdict. Use JSON `hookSpecificOutput.retry: true` to tell the model it may retry the denied tool call. Claude Code ignores `retry` when the classifier produced no verdict |
40| `PostToolUse` | After a tool call succeeds |
41| `PostToolUseFailure` | After a tool call fails |
42| `PostToolBatch` | After a full batch of parallel tool calls resolves, before the next model call |
43| `Notification` | When Claude Code sends a notification |
44| `MessageDisplay` | While assistant message text is displayed |
45| `SubagentStart` | When a subagent is spawned |
46| `SubagentStop` | When a subagent finishes |
47| `TaskCreated` | When a task is being created via `TaskCreate` |
48| `TaskCompleted` | When a task is being marked as completed |
49| `Stop` | When Claude finishes responding |
50| `StopFailure` | When the turn ends due to an API error |
51| `TeammateIdle` | When an [agent team](/docs/en/agent-teams) teammate is about to go idle |
52| `InstructionsLoaded` | When a CLAUDE.md or `.claude/rules/*.md` file is loaded into context. Fires at session start and when files are lazily loaded during a session |
53| `ConfigChange` | When a configuration file changes during a session |
54| `CwdChanged` | When the working directory changes, for example when Claude executes a `cd` command. Useful for reactive environment management with tools like direnv |
55| `DirectoryAdded` | When a working directory is added mid-session via `/add-dir` or the SDK `register_repo_root` control request |
56| `FileChanged` | When a watched file changes on disk. The `matcher` field specifies which filenames to watch |
57| `WorktreeCreate` | When a worktree is being created via `--worktree`, `isolation: "worktree"`, or for a background session. Replaces default git behavior |
58| `WorktreeRemove` | When a worktree is being removed at session exit, when a subagent finishes, or when you delete a background session |
59| `PreCompact` | Before context compaction |
60| `PostCompact` | After context compaction completes |
61| `PreModelSwitch` | Before Claude Code applies a model switch that you or a client requested. Can block the switch |
62| `PostModelSwitch` | After the session's model changes, including changes Claude Code makes on its own, such as restoring the model when you resume a session |
63| `Elicitation` | When an MCP server requests user input during a tool call |
64| `ElicitationResult` | After a user responds to an MCP elicitation, before the response is sent back to the server |
65| `SessionEnd` | When a session terminates |
6666
6767### How a hook resolves
6868
from line 246
246246
247247Where you define a hook determines its scope:
248248
249| Location | Scope | Shareable |
250| :------------------------------------------------ | :--------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------- |
251| `~/.claude/settings.json` | All your projects | No, local to your machine |
252| `.claude/settings.json` | Single project | Yes, can be committed to the repo |
253| `.claude/settings.local.json` | Single project | No, gitignored when Claude Code saves a setting to it |
254| Managed policy settings | Organization-wide | Yes, admin-controlled |
255| [Plugin](/docs/en/plugins/overview) `hooks/hooks.json` | When plugin is enabled | Yes, bundled with the plugin |
256| [Skill](/docs/en/skills) frontmatter | The rest of the session once the skill is invoked. See [Hooks in skills and agents](#hooks-in-skills-and-agents) | Yes, defined in the skill file |
257| [Subagent](/docs/en/sub-agents) frontmatter | While that subagent is running | Yes, defined in the subagent file |
249| Location | Scope | Shareable |
250| :- | :- | :- |
251| `~/.claude/settings.json` | All your projects | No, local to your machine |
252| `.claude/settings.json` | Single project | Yes, can be committed to the repo |
253| `.claude/settings.local.json` | Single project | No, gitignored when Claude Code saves a setting to it |
254| Managed policy settings | Organization-wide | Yes, admin-controlled |
255| [Plugin](/docs/en/plugins/overview) `hooks/hooks.json` | When plugin is enabled | Yes, bundled with the plugin |
256| [Skill](/docs/en/skills) frontmatter | The rest of the session once the skill is invoked. See [Hooks in skills and agents](#hooks-in-skills-and-agents) | Yes, defined in the skill file |
257| [Subagent](/docs/en/sub-agents) frontmatter | While that subagent is running | Yes, defined in the subagent file |
258258
259259[Cloud sessions](/docs/en/claude-code-on-the-web) don't read your local `~/.claude/settings.json`. In a [self-hosted environment](/docs/en/self-hosted-environments-configuration#permissions-and-tool-approval), Claude Code also runs the hooks the operator seeded from the runner host's `~/.claude/`, and it runs the hooks in the runner image's managed settings file when that file is among the [managed sources Claude Code applies](/docs/en/managed-settings#how-claude-code-combines-managed-sources), which by default means only when neither server-managed settings nor an MDM-delivered Claude Code policy supplies the managed tier. See [what carries over from your setup](/docs/en/cloud-environments#what-carries-over-from-your-setup) for which settings files and plugins, and so which hooks, reach a cloud session.
260260
from line 282
282282
283283The `matcher` field filters when hooks fire. How a matcher is evaluated depends on the characters it contains:
284284
285| Matcher value | Evaluated as | Example |
286| :---------------------------------------------------- | :--------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------- |
287| `"*"`, `""`, or omitted | Match all | fires on every occurrence of the event |
285| Matcher value | Evaluated as | Example |
286| :- | :- | :- |
287| `"*"`, `""`, or omitted | Match all | fires on every occurrence of the event |
288288| Only letters, digits, `_`, `-`, spaces, `,`, and `\|` | Exact string, or list of exact strings separated by `\|` or `,` with optional surrounding whitespace | `Bash` matches only the Bash tool; `Edit\|Write` and `Edit, Write` each match either tool exactly; `code-reviewer` matches only that agent type |
289| Contains any other character | JavaScript regular expression, unanchored | `^Notebook` matches any tool whose name starts with `Notebook`; `mcp__memory__.*` matches every tool from the `memory` server |
289| Contains any other character | JavaScript regular expression, unanchored | `^Notebook` matches any tool whose name starts with `Notebook`; `mcp__memory__.*` matches every tool from the `memory` server |
290290
291291A matcher on the regular-expression path is tested with JavaScript's `RegExp.prototype.test`, which succeeds on a match anywhere in the value. `Edit.*` matches both `Edit` and `NotebookEdit`; wrap the pattern in `^` and `$`, as in `^Edit$`, when you need a whole-string match.
292292
from line 298
298298
299299Each event type matches on a different field:
300300
301| Event | What the matcher filters | Example matcher values |
302| :------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
303| `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied` | tool name | `Bash`, `Edit\|Write`, `mcp__.*` |
304| `SessionStart` | how the session started | `startup`, `resume`, `clear`, `compact`, `fork` |
305| `Setup` | which CLI flag triggered setup | `init`, `maintenance` |
306| `SessionEnd` | why the session ended | `clear`, `resume`, `logout`, `prompt_input_exit`, `other` |
307| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`, `elicitation_url_dialog`, `elicitation_complete`, `elicitation_response`, `agent_needs_input`, `agent_completed`, `quota_auto_resume_fired`, `quota_auto_resume_stale`, `quota_auto_resume_disabled` |
308| `SubagentStart` | agent type | `general-purpose`, `Explore`, `Plan`, custom agent names, or plugin-scoped names like `^my-plugin:reviewer$` |
309| `PreCompact`, `PostCompact` | what triggered compaction | `manual`, `auto` |
310| `PreModelSwitch`, `PostModelSwitch` | canonical name of the model the session switches to, as described under [PreModelSwitch](#premodelswitch) | `claude-opus-5`, `claude-opus-4-6\|claude-opus-5`, `.*opus.*` |
311| `SubagentStop` | agent type | same values as `SubagentStart` |
312| `ConfigChange` | configuration source | `user_settings`, `project_settings`, `local_settings`, `policy_settings`, `skills` |
313| `CwdChanged` | no matcher support | always fires on every occurrence |
314| `DirectoryAdded` | how the directory was added | `slash_command`, `register_repo_root` |
315| `FileChanged` | literal filenames to watch (see [FileChanged](#filechanged)) | `.envrc\|.env` |
316| `StopFailure` | error type | `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, `unknown` |
317| `InstructionsLoaded` | load reason | `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact` |
318| `UserPromptExpansion` | command name | your skill or command names |
319| `Elicitation` | MCP server name | your configured MCP server names |
320| `ElicitationResult` | MCP server name | same values as `Elicitation` |
321| `UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, `MessageDisplay` | no matcher support | always fires on every occurrence |
301| Event | What the matcher filters | Example matcher values |
302| :- | :- | :- |
303| `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied` | tool name | `Bash`, `Edit\|Write`, `mcp__.*` |
304| `SessionStart` | how the session started | `startup`, `resume`, `clear`, `compact`, `fork` |
305| `Setup` | which CLI flag triggered setup | `init`, `maintenance` |
306| `SessionEnd` | why the session ended | `clear`, `resume`, `logout`, `prompt_input_exit`, `other` |
307| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`, `elicitation_url_dialog`, `elicitation_complete`, `elicitation_response`, `agent_needs_input`, `agent_completed`, `quota_auto_resume_fired`, `quota_auto_resume_stale`, `quota_auto_resume_disabled` |
308| `SubagentStart` | agent type | `general-purpose`, `Explore`, `Plan`, custom agent names, or plugin-scoped names like `^my-plugin:reviewer$` |
309| `PreCompact`, `PostCompact` | what triggered compaction | `manual`, `auto` |
310| `PreModelSwitch`, `PostModelSwitch` | canonical name of the model the session switches to, as described under [PreModelSwitch](#premodelswitch) | `claude-opus-5`, `claude-opus-4-6\|claude-opus-5`, `.*opus.*` |
311| `SubagentStop` | agent type | same values as `SubagentStart` |
312| `ConfigChange` | configuration source | `user_settings`, `project_settings`, `local_settings`, `policy_settings`, `skills` |
313| `CwdChanged` | no matcher support | always fires on every occurrence |
314| `DirectoryAdded` | how the directory was added | `slash_command`, `register_repo_root` |
315| `FileChanged` | literal filenames to watch (see [FileChanged](#filechanged)) | `.envrc\|.env` |
316| `StopFailure` | error type | `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, `unknown` |
317| `InstructionsLoaded` | load reason | `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact` |
318| `UserPromptExpansion` | command name | your skill or command names |
319| `Elicitation` | MCP server name | your configured MCP server names |
320| `ElicitationResult` | MCP server name | same values as `Elicitation` |
321| `UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, `MessageDisplay` | no matcher support | always fires on every occurrence |
322322
323323Matching `StopFailure` on `cloud_credential_error` requires Claude Code v2.1.267 or later, the first version that reports credential-load failures under that value rather than `server_error` or `unknown`.
324324
from line 417
417417
418418These fields apply to all hook types:
419419
420| Field | Required | Description |
421| :-------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
422| `type` | yes | `"command"`, `"http"`, `"mcp_tool"`, `"prompt"`, or `"agent"` |
423| `if` | no | Permission rule syntax to filter when this hook runs, such as `"Bash(git *)"` or `"Edit(*.ts)"`. The hook command only runs if the tool call matches the pattern. See the [Bash matching table](#bash-if-matching) below for how Bash patterns evaluate against subcommands, `$()`, and backticks. Only evaluated on tool events: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, and `PermissionDenied`. On other events, a hook with `if` set never runs. Uses the same syntax as [permission rules](/docs/en/permissions) |
424| `timeout` | no | Seconds before canceling. Claude Code doesn't enforce it on a command hook you run with [`async: true`](#run-hooks-in-the-background). Defaults: 600 for `command`, `http`, and `mcp_tool`; 30 for `prompt`; 60 for `agent`. Claude Code lowers the `command`, `http`, and `mcp_tool` default to 30 on [`UserPromptSubmit`](#userpromptsubmit), [`PreModelSwitch`](#premodelswitch), and [`PostModelSwitch`](#postmodelswitch), and to 10 on [`MessageDisplay`](#messagedisplay). [`SessionEnd`](#sessionend) hooks share a 1.5-second budget; if your settings set a longer per-hook `timeout`, Claude Code raises the budget to match, up to 60 seconds |
425| `statusMessage` | no | Custom spinner message displayed while the hook runs |
426| `once` | no | If `true`, Claude Code removes the hook after its first successful run. A run that fails, blocks with exit code 2, or times out leaves the hook in place, so it runs again on the next matching event. Only honored for hooks declared in [skill frontmatter](#hooks-in-skills-and-agents); ignored in settings files and agent frontmatter |
420| Field | Required | Description |
421| :- | :- | :- |
422| `type` | yes | `"command"`, `"http"`, `"mcp_tool"`, `"prompt"`, or `"agent"` |
423| `if` | no | Permission rule syntax to filter when this hook runs, such as `"Bash(git *)"` or `"Edit(*.ts)"`. The hook command only runs if the tool call matches the pattern. See the [Bash matching table](#bash-if-matching) below for how Bash patterns evaluate against subcommands, `$()`, and backticks. Only evaluated on tool events: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, and `PermissionDenied`. On other events, a hook with `if` set never runs. Uses the same syntax as [permission rules](/docs/en/permissions) |
424| `timeout` | no | Seconds before canceling. Claude Code doesn't enforce it on a command hook you run with [`async: true`](#run-hooks-in-the-background). Defaults: 600 for `command`, `http`, and `mcp_tool`; 30 for `prompt`; 60 for `agent`. Claude Code lowers the `command`, `http`, and `mcp_tool` default to 30 on [`UserPromptSubmit`](#userpromptsubmit), [`PreModelSwitch`](#premodelswitch), and [`PostModelSwitch`](#postmodelswitch), and to 10 on [`MessageDisplay`](#messagedisplay). [`SessionEnd`](#sessionend) hooks share a 1.5-second budget; if your settings set a longer per-hook `timeout`, Claude Code raises the budget to match, up to 60 seconds |
425| `statusMessage` | no | Custom spinner message displayed while the hook runs |
426| `once` | no | If `true`, Claude Code removes the hook after its first successful run. A run that fails, blocks with exit code 2, or times out leaves the hook in place, so it runs again on the next matching event. Only honored for hooks declared in [skill frontmatter](#hooks-in-skills-and-agents); ignored in settings files and agent frontmatter |
427427
428428The `if` field holds exactly one permission rule. There is no `&&`, `||`, or list syntax for combining rules; to apply multiple conditions, define a separate hook handler for each.
429429
from line 431
431431
432432<span id="bash-if-matching" />For Bash patterns, whether your hook command runs depends on the shape of the pattern and the Bash command Claude is invoking. Leading `VAR=value` assignments are stripped before matching.
433433
434| `if` pattern | Bash command | Hook runs? | Why |
435| :----------------- | :-------------------------- | :--------- | :------------------------------------------------------------------------------------------------------------------------ |
436| `Bash(git *)` | `FOO=bar git push` | yes | leading assignments are stripped; `git push` matches |
437| `Bash(git *)` | `npm test && git push` | yes | each subcommand is checked; `git push` matches |
438| `Bash(rm *)` | `echo $(rm -rf /)` | yes | commands inside `$()` and backticks are checked; `rm -rf /` matches |
439| `Bash(rm *)` | `echo $(date)` | no | no subcommand matches `rm *` |
440| `Bash(cat *)` | `echo before $(date) after` | no | a substitution can sit at any argument position, so the full command and `date` are both checked; neither matches `cat *` |
441| `Bash(git *)` | `$TOOL git push` | yes | Claude Code can't tell what the command name expands to, so it runs the hook |
442| `Bash(git push *)` | `echo $(date)` | yes | patterns that specify more than the command name run the hook anyway on `$()`, backticks, or `$VAR` |
434| `if` pattern | Bash command | Hook runs? | Why |
435| :- | :- | :- | :- |
436| `Bash(git *)` | `FOO=bar git push` | yes | leading assignments are stripped; `git push` matches |
437| `Bash(git *)` | `npm test && git push` | yes | each subcommand is checked; `git push` matches |
438| `Bash(rm *)` | `echo $(rm -rf /)` | yes | commands inside `$()` and backticks are checked; `rm -rf /` matches |
439| `Bash(rm *)` | `echo $(date)` | no | no subcommand matches `rm *` |
440| `Bash(cat *)` | `echo before $(date) after` | no | a substitution can sit at any argument position, so the full command and `date` are both checked; neither matches `cat *` |
441| `Bash(git *)` | `$TOOL git push` | yes | Claude Code can't tell what the command name expands to, so it runs the hook |
442| `Bash(git push *)` | `echo $(date)` | yes | patterns that specify more than the command name run the hook anyway on `$()`, backticks, or `$VAR` |
443443
444444When Claude Code can't determine which commands the Bash input runs, it runs your hook regardless of the pattern. Because the `if` filter is best-effort, use the [permission system](/docs/en/permissions) rather than a hook to enforce a hard allow or deny.
445445
from line 447
447447
448448In addition to the [common fields](#common-fields), command hooks accept these fields:
449449
450| Field | Required | Description |
451| :------------ | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
452| `command` | yes | Shell command to execute. With `args`, the executable to spawn directly. See [Exec form and shell form](#exec-form-and-shell-form) |
453| `args` | no | Argument list. When present, `command` is resolved as an executable and spawned directly with `args` as the argument vector, with no shell involved. See [Exec form and shell form](#exec-form-and-shell-form) |
454| `async` | no | If `true`, runs in the background without blocking. See [Run hooks in the background](#run-hooks-in-the-background) |
455| `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 |
456| `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 |
450| Field | Required | Description |
451| :- | :- | :- |
452| `command` | yes | Shell command to execute. With `args`, the executable to spawn directly. See [Exec form and shell form](#exec-form-and-shell-form) |
453| `args` | no | Argument list. When present, `command` is resolved as an executable and spawned directly with `args` as the argument vector, with no shell involved. See [Exec form and shell form](#exec-form-and-shell-form) |
454| `async` | no | If `true`, runs in the background without blocking. See [Run hooks in the background](#run-hooks-in-the-background) |
455| `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 |
456| `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 |
457457
458458<a id="exec-form-and-shell-form" />
459459
from line 502
502502
503503In addition to the [common fields](#common-fields), HTTP hooks accept these fields:
504504
505| Field | Required | Description |
506| :--------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
507| `url` | yes | URL to send the POST request to |
508| `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 |
509| `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 |
505| Field | Required | Description |
506| :- | :- | :- |
507| `url` | yes | URL to send the POST request to |
508| `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 |
509| `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 |
510510
511511Claude 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.
512512
from line 541
541541
542542In addition to the [common fields](#common-fields), MCP tool hooks accept these fields:
543543
544| Field | Required | Description |
545| :------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
546| `server` | yes | Name of a configured MCP server. For a [plugin-bundled server](/docs/en/mcp#plugin-provided-mcp-servers), this is the scoped name `plugin:<plugin-name>:<server-name>`, such as `plugin:my-plugin:db`, not the bare server key |
547| `tool` | yes | Name of the tool to call on that server |
548| `input` | no | Arguments passed to the tool. String values support `${path}` substitution from the hook's [JSON input](#hook-input-and-output), such as `"${tool_input.file_path}"` |
544| Field | Required | Description |
545| :- | :- | :- |
546| `server` | yes | Name of a configured MCP server. For a [plugin-bundled server](/docs/en/mcp#plugin-provided-mcp-servers), this is the scoped name `plugin:<plugin-name>:<server-name>`, such as `plugin:my-plugin:db`, not the bare server key |
547| `tool` | yes | Name of the tool to call on that server |
548| `input` | no | Arguments passed to the tool. String values support `${path}` substitution from the hook's [JSON input](#hook-input-and-output), such as `"${tool_input.file_path}"` |
549549
550550This example calls the `security_scan` tool on the `my_server` MCP server after each `Write` or `Edit`, passing the edited file's path:
551551
from line 587
587587
588588In addition to the [common fields](#common-fields), prompt and agent hooks accept these fields:
589589
590| Field | Required | Description |
591| :------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
592| `prompt` | yes | Prompt text to send to the model. Use `$ARGUMENTS` as a placeholder for the hook input JSON. Escape with a backslash to include literal text: `\$1.00` renders as `$1.00` |
593| `model` | no | Model to use for evaluation. Defaults to a fast model |
590| Field | Required | Description |
591| :- | :- | :- |
592| `prompt` | yes | Prompt text to send to the model. Use `$ARGUMENTS` as a placeholder for the hook input JSON. Escape with a backslash to include literal text: `\$1.00` renders as `$1.00` |
593| `model` | no | Model to use for evaluation. Defaults to a fast model |
594594
595595### Reference scripts by path
596596
from line 727
727727
728728Hook events receive these fields as JSON, in addition to event-specific fields documented in each [hook event](#hook-events) section. For command hooks, this JSON arrives via stdin. For HTTP hooks, it arrives as the POST request body.
729729
730| Field | Description |
731| :---------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
732| `session_id` | Current session identifier |
733| `prompt_id` | UUID identifying the user prompt currently being processed. Matches the [`prompt.id` attribute on OpenTelemetry events](/docs/en/monitoring-usage#event-correlation-attributes), so you can correlate hook output with telemetry for a single prompt. Absent until the first user input. Requires Claude Code v2.1.196 or later |
734| `transcript_path` | Path to conversation JSON. The transcript file is written asynchronously and may lag the in-memory conversation, so it may not yet include the current turn's most recent messages when a hook fires. Hooks that need the final assistant text of the current turn should use `last_assistant_message` on [Stop](#stop) and [SubagentStop](#subagentstop) instead of reading the transcript |
735| `cwd` | Current working directory when the hook is invoked |
736| `scratchpad_dir` | Path to the session's [scratchpad directory](/docs/en/claude-directory#session-scratchpad-directory), where Claude keeps temporary working files. Absent when the session has no scratchpad or the temp directory is unavailable. Requires Claude Code v2.1.257 or later |
737| `permission_mode` | Current [permission mode](/docs/en/permissions#permission-modes): `"default"`, `"plan"`, `"acceptEdits"`, `"auto"`, `"dontAsk"`, or `"bypassPermissions"`. The mode labeled **Manual** arrives as `"default"`, never as `"manual"`, so scripts that match `"default"` keep working. Not all events receive this field. Check the JSON example in each [hook event](#hook-events) section |
738| `effort` | Object with a `level` field holding the [effort level](/docs/en/model-config#adjust-effort-level) in effect when the hook runs: `"low"`, `"medium"`, `"high"`, `"xhigh"`, or `"max"`. If you set a level the active model doesn't support, `level` reports the level Claude Code ran instead; [Adjust effort level](/docs/en/model-config#adjust-effort-level) says how it picks that level. Ultracode is not a distinct level and reports as `"xhigh"`. The object matches the [status line](/docs/en/statusline#available-data) `effort` field. Present for events that fire within a tool-use context, such as `PreToolUse`, `PostToolUse`, `Stop`, and `SubagentStop`, when the current model supports the effort parameter. The level is also available to hook commands and the Bash tool as the `$CLAUDE_EFFORT` environment variable. |
739| `hook_event_name` | Name of the event that fired |
730| Field | Description |
731| :- | :- |
732| `session_id` | Current session identifier |
733| `prompt_id` | UUID identifying the user prompt currently being processed. Matches the [`prompt.id` attribute on OpenTelemetry events](/docs/en/monitoring-usage#event-correlation-attributes), so you can correlate hook output with telemetry for a single prompt. Absent until the first user input. Requires Claude Code v2.1.196 or later |
734| `transcript_path` | Path to conversation JSON. The transcript file is written asynchronously and may lag the in-memory conversation, so it may not yet include the current turn's most recent messages when a hook fires. Hooks that need the final assistant text of the current turn should use `last_assistant_message` on [Stop](#stop) and [SubagentStop](#subagentstop) instead of reading the transcript |
735| `cwd` | Current working directory when the hook is invoked |
736| `scratchpad_dir` | Path to the session's [scratchpad directory](/docs/en/claude-directory#session-scratchpad-directory), where Claude keeps temporary working files. Absent when the session has no scratchpad or the temp directory is unavailable. Requires Claude Code v2.1.257 or later |
737| `permission_mode` | Current [permission mode](/docs/en/permissions#permission-modes): `"default"`, `"plan"`, `"acceptEdits"`, `"auto"`, `"dontAsk"`, or `"bypassPermissions"`. The mode labeled **Manual** arrives as `"default"`, never as `"manual"`, so scripts that match `"default"` keep working. Not all events receive this field. Check the JSON example in each [hook event](#hook-events) section |
738| `effort` | Object with a `level` field holding the [effort level](/docs/en/model-config#adjust-effort-level) in effect when the hook runs: `"low"`, `"medium"`, `"high"`, `"xhigh"`, or `"max"`. If you set a level the active model doesn't support, `level` reports the level Claude Code ran instead; [Adjust effort level](/docs/en/model-config#adjust-effort-level) says how it picks that level. Ultracode is not a distinct level and reports as `"xhigh"`. The object matches the [status line](/docs/en/statusline#available-data) `effort` field. Present for events that fire within a tool-use context, such as `PreToolUse`, `PostToolUse`, `Stop`, and `SubagentStop`, when the current model supports the effort parameter. The level is also available to hook commands and the Bash tool as the `$CLAUDE_EFFORT` environment variable. |
739| `hook_event_name` | Name of the event that fired |
740740
741741When running with `--agent` or inside a subagent, two additional fields are included:
742742
743| Field | Description |
744| :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
745| `agent_id` | Unique identifier for the subagent. Present only when the hook fires inside a subagent call. Use this to distinguish subagent hook calls from main-thread calls. |
743| Field | Description |
744| :- | :- |
745| `agent_id` | Unique identifier for the subagent. Present only when the hook fires inside a subagent call. Use this to distinguish subagent hook calls from main-thread calls. |
746746| `agent_type` | Agent name (for example, `"Explore"` or `"security-reviewer"`). Present when the session uses `--agent` or the hook fires inside a subagent. For subagents, the subagent's type takes precedence over the session's `--agent` value. See [SubagentStart](#subagentstart) for the values custom and plugin subagents report and how to write a matcher against a plugin-scoped name. |
747747
748748Only [`SessionStart`](#sessionstart) hooks can receive a `model` field, and Claude Code doesn't always include it. [`PreModelSwitch`](#premodelswitch) and [`PostModelSwitch`](#postmodelswitch) hooks receive `from_model` and `to_model` instead, so use a PostModelSwitch hook to follow the model as it changes during a session.
from line 855
855855
856856Exit 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.
857857
858| Hook event | Can block? | What happens on exit 2 |
859| :-------------------- | :--------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
860| `PreToolUse` | Yes | Blocks the tool call |
861| `PermissionRequest` | No | Exit code 2 isn't honored for this event and the permission flow proceeds unchanged. Deny through the [`decision` object](#permissionrequest-decision-control) instead |
862| `UserPromptSubmit` | Yes | Blocks prompt processing and erases the prompt |
863| `UserPromptExpansion` | Yes | Blocks the expansion |
864| `Stop` | Yes | Prevents Claude from stopping, continues the conversation |
865| `SubagentStop` | Yes | Prevents the subagent from stopping |
866| `TeammateIdle` | Yes | Prevents the teammate from going idle, so it continues working |
867| `TaskCreated` | Yes | Rolls back the task creation |
868| `TaskCompleted` | Yes | Prevents the task from being marked as completed |
869| `ConfigChange` | Yes | Blocks the configuration change from taking effect (except `policy_settings`) |
870| `StopFailure` | No | Output and exit code are ignored, except `terminalSequence` |
871| `PostToolUse` | No | Shows stderr to Claude; the tool already ran |
872| `PostToolUseFailure` | No | Shows stderr to Claude; the tool already failed |
873| `PostToolBatch` | Yes | Stops the agentic loop before the next model call |
874| `PermissionDenied` | No | Exit code and stderr are ignored because the denial already occurred. Use JSON `hookSpecificOutput.retry: true` to tell the model it may retry; Claude Code ignores `retry: true` for [no-verdict denials](#permissiondenied-decision-control) |
875| `Notification` | No | Exit code and stderr are ignored |
876| `SubagentStart` | No | Shows stderr to user only |
877| `SessionStart` | No | Shows stderr to user only |
878| `Setup` | No | Exit code and stderr are ignored |
879| `SessionEnd` | No | Shows stderr to user only |
880| `CwdChanged` | No | Shows stderr to user only |
881| `DirectoryAdded` | No | Stderr goes to the debug log; the directory is already added |
882| `FileChanged` | No | Shows stderr to user only |
883| `PreCompact` | Yes | Blocks compaction |
884| `PostCompact` | No | Shows stderr to user only |
885| `PreModelSwitch` | Yes | Blocks the model switch and shows stderr to the user |
886| `PostModelSwitch` | No | Shows stderr to user only; the model already switched |
887| `Elicitation` | Yes | Denies the elicitation |
888| `ElicitationResult` | Yes | Blocks the response (action becomes decline) |
889| `WorktreeCreate` | Yes | Any non-zero exit code causes worktree creation to fail |
890| `WorktreeRemove` | Yes | Any non-zero exit code causes worktree removal to fail if the directory still exists afterward. See [WorktreeRemove](#worktreeremove) for what happens to the directory |
891| `InstructionsLoaded` | No | Exit code is ignored |
892| `MessageDisplay` | No | The original text is displayed |
858| Hook event | Can block? | What happens on exit 2 |
859| :- | :- | :- |
860| `PreToolUse` | Yes | Blocks the tool call |
861| `PermissionRequest` | No | Exit code 2 isn't honored for this event and the permission flow proceeds unchanged. Deny through the [`decision` object](#permissionrequest-decision-control) instead |
862| `UserPromptSubmit` | Yes | Blocks prompt processing and erases the prompt |
863| `UserPromptExpansion` | Yes | Blocks the expansion |
864| `Stop` | Yes | Prevents Claude from stopping, continues the conversation |
865| `SubagentStop` | Yes | Prevents the subagent from stopping |
866| `TeammateIdle` | Yes | Prevents the teammate from going idle, so it continues working |
867| `TaskCreated` | Yes | Rolls back the task creation |
868| `TaskCompleted` | Yes | Prevents the task from being marked as completed |
869| `ConfigChange` | Yes | Blocks the configuration change from taking effect (except `policy_settings`) |
870| `StopFailure` | No | Output and exit code are ignored, except `terminalSequence` |
871| `PostToolUse` | No | Shows stderr to Claude; the tool already ran |
872| `PostToolUseFailure` | No | Shows stderr to Claude; the tool already failed |
873| `PostToolBatch` | Yes | Stops the agentic loop before the next model call |
874| `PermissionDenied` | No | Exit code and stderr are ignored because the denial already occurred. Use JSON `hookSpecificOutput.retry: true` to tell the model it may retry; Claude Code ignores `retry: true` for [no-verdict denials](#permissiondenied-decision-control) |
875| `Notification` | No | Exit code and stderr are ignored |
876| `SubagentStart` | No | Shows stderr to user only |
877| `SessionStart` | No | Shows stderr to user only |
878| `Setup` | No | Exit code and stderr are ignored |
879| `SessionEnd` | No | Shows stderr to user only |
880| `CwdChanged` | No | Shows stderr to user only |
881| `DirectoryAdded` | No | Stderr goes to the debug log; the directory is already added |
882| `FileChanged` | No | Shows stderr to user only |
883| `PreCompact` | Yes | Blocks compaction |
884| `PostCompact` | No | Shows stderr to user only |
885| `PreModelSwitch` | Yes | Blocks the model switch and shows stderr to the user |
886| `PostModelSwitch` | No | Shows stderr to user only; the model already switched |
887| `Elicitation` | Yes | Denies the elicitation |
888| `ElicitationResult` | Yes | Blocks the response (action becomes decline) |
889| `WorktreeCreate` | Yes | Any non-zero exit code causes worktree creation to fail |
890| `WorktreeRemove` | Yes | Any non-zero exit code causes worktree removal to fail if the directory still exists afterward. See [WorktreeRemove](#worktreeremove) for what happens to the directory |
891| `InstructionsLoaded` | No | Exit code is ignored |
892| `MessageDisplay` | No | The original text is displayed |
893893
894894For `SessionStart`, `SubagentStart`, and `PostModelSwitch`, Claude Code renders the exit code 2 stderr in the transcript as a `<hook name> hook error` notice, the same way it renders a [non-blocking error](#exit-code-output). Claude doesn't see it, and the session or subagent proceeds. For `SubagentStart`, the notice appears in the subagent's own transcript, not in the parent conversation.
895895
from line 928
928928* **Top-level `decision` and `reason`** are used by some events to block or provide feedback.
929929* **`hookSpecificOutput`** is a nested object for events that need richer control. It requires a `hookEventName` field set to the event name.
930930
931| Field | Default | Description |
932| :----------------- | :------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
933| `continue` | `true` | If `false`, Claude stops processing entirely after the hook runs. Takes precedence over any event-specific decision fields |
934| `stopReason` | none | Message shown to the user when `continue` is `false`. It stays in the conversation, so Claude sees it if the conversation continues |
935| `suppressOutput` | `false` | Has no effect: Claude Code accepts the field but doesn't act on it. A successful hook's stdout is never shown in the transcript and is recorded in the debug log |
936| `systemMessage` | none | Warning message shown to the user. In [Agent SDK](/docs/en/agent-sdk/overview) and [`--output-format stream-json`](/docs/en/headless) output, it can arrive as an [`SDKInformationalMessage`](/docs/en/agent-sdk/typescript#sdkinformationalmessage) |
937| `terminalSequence` | none | A terminal escape sequence for Claude Code to emit on your behalf, such as a desktop notification, window title, or bell. Restricted to OSC `0`/`1`/`2`/`9`/`99`/`777` and BEL. If the value contains anything outside the allowlist, the field is ignored. Use this instead of writing to `/dev/tty`, which is unavailable to hooks |
931| Field | Default | Description |
932| :- | :- | :- |
933| `continue` | `true` | If `false`, Claude stops processing entirely after the hook runs. Takes precedence over any event-specific decision fields |
934| `stopReason` | none | Message shown to the user when `continue` is `false`. It stays in the conversation, so Claude sees it if the conversation continues |
935| `suppressOutput` | `false` | Has no effect: Claude Code accepts the field but doesn't act on it. A successful hook's stdout is never shown in the transcript and is recorded in the debug log |
936| `systemMessage` | none | Warning message shown to the user. In [Agent SDK](/docs/en/agent-sdk/overview) and [`--output-format stream-json`](/docs/en/headless) output, it can arrive as an [`SDKInformationalMessage`](/docs/en/agent-sdk/typescript#sdkinformationalmessage) |
937| `terminalSequence` | none | A terminal escape sequence for Claude Code to emit on your behalf, such as a desktop notification, window title, or bell. Restricted to OSC `0`/`1`/`2`/`9`/`99`/`777` and BEL. If the value contains anything outside the allowlist, the field is ignored. Use this instead of writing to `/dev/tty`, which is unavailable to hooks |
938938
939939To stop Claude entirely:
940940
from line 1020
10201020
10211021Not every event supports blocking or controlling behavior through JSON. The events that do each use a different set of fields to express that decision. Use this table as a quick reference before writing a hook:
10221022
1023| Events | Decision pattern | Key fields |
1024| :---------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1025| UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, SubagentStop, ConfigChange, PreCompact | Top-level `decision` | `decision: "block"`, `reason`. Stop and SubagentStop also accept `hookSpecificOutput.additionalContext` for [non-error feedback that continues the conversation](#stop-decision-control) |
1026| TeammateIdle, TaskCompleted | Exit code or `continue: false` | Exit code 2 blocks the action with stderr feedback. JSON `{"continue": false, "stopReason": "..."}` also stops the teammate entirely, matching `Stop` hook behavior; [TaskCompleted ignores it when the `TaskUpdate` tool triggered the event](#taskcompleted-decision-control) |
1027| TaskCreated | Exit code or top-level `decision` | Exit code 2 or `decision: "block"` [cancels the task](#taskcreated-decision-control) and returns the message to Claude. `continue: false` is ignored |
1028| PreToolUse | `hookSpecificOutput` | `permissionDecision` (allow/deny/ask/defer), `permissionDecisionReason` |
1029| PreModelSwitch | `hookSpecificOutput` or top-level `decision` | `permissionDecision` (allow/deny/ask), `permissionDecisionReason`. `decision: "block"` also [cancels the switch](#premodelswitch-decision-control) |
1030| PermissionRequest | `hookSpecificOutput` | `decision.behavior` (allow/deny) |
1031| PermissionDenied | `hookSpecificOutput` | `retry: true` tells the model it may retry the denied tool call; Claude Code ignores it for [no-verdict denials](#permissiondenied-decision-control) |
1032| WorktreeCreate | path return | Command hook prints path on stdout; HTTP hook returns `hookSpecificOutput.worktreePath`. Hook failure or missing path fails creation |
1033| WorktreeRemove | Exit code | Any non-zero exit code makes the removal fail if the directory still exists afterward. JSON output is discarded |
1034| Elicitation | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (form field values for accept) |
1035| ElicitationResult | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (form field values override) |
1036| MessageDisplay | `hookSpecificOutput` | `displayContent` replaces the displayed text on screen. Display-only: the transcript and what Claude sees keep the original |
1037| SessionStart, SubagentStart, PostModelSwitch | Context only | `hookSpecificOutput.additionalContext` adds context for Claude. SessionStart also accepts [`initialUserMessage`, `watchPaths`, `sessionTitle`, and `reloadSkills`](#sessionstart-decision-control). No blocking or decision control |
1038| Setup, Notification, SessionEnd, PostCompact, InstructionsLoaded, StopFailure, CwdChanged, DirectoryAdded, FileChanged | None | No decision control. Used for side effects like logging or cleanup |
1023| Events | Decision pattern | Key fields |
1024| :- | :- | :- |
1025| UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, SubagentStop, ConfigChange, PreCompact | Top-level `decision` | `decision: "block"`, `reason`. Stop and SubagentStop also accept `hookSpecificOutput.additionalContext` for [non-error feedback that continues the conversation](#stop-decision-control) |
1026| TeammateIdle, TaskCompleted | Exit code or `continue: false` | Exit code 2 blocks the action with stderr feedback. JSON `{"continue": false, "stopReason": "..."}` also stops the teammate entirely, matching `Stop` hook behavior; [TaskCompleted ignores it when the `TaskUpdate` tool triggered the event](#taskcompleted-decision-control) |
1027| TaskCreated | Exit code or top-level `decision` | Exit code 2 or `decision: "block"` [cancels the task](#taskcreated-decision-control) and returns the message to Claude. `continue: false` is ignored |
1028| PreToolUse | `hookSpecificOutput` | `permissionDecision` (allow/deny/ask/defer), `permissionDecisionReason` |
1029| PreModelSwitch | `hookSpecificOutput` or top-level `decision` | `permissionDecision` (allow/deny/ask), `permissionDecisionReason`. `decision: "block"` also [cancels the switch](#premodelswitch-decision-control) |
1030| PermissionRequest | `hookSpecificOutput` | `decision.behavior` (allow/deny) |
1031| PermissionDenied | `hookSpecificOutput` | `retry: true` tells the model it may retry the denied tool call; Claude Code ignores it for [no-verdict denials](#permissiondenied-decision-control) |
1032| WorktreeCreate | path return | Command hook prints path on stdout; HTTP hook returns `hookSpecificOutput.worktreePath`. Hook failure or missing path fails creation |
1033| WorktreeRemove | Exit code | Any non-zero exit code makes the removal fail if the directory still exists afterward. JSON output is discarded |
1034| Elicitation | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (form field values for accept) |
1035| ElicitationResult | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (form field values override) |
1036| MessageDisplay | `hookSpecificOutput` | `displayContent` replaces the displayed text on screen. Display-only: the transcript and what Claude sees keep the original |
1037| SessionStart, SubagentStart, PostModelSwitch | Context only | `hookSpecificOutput.additionalContext` adds context for Claude. SessionStart also accepts [`initialUserMessage`, `watchPaths`, `sessionTitle`, and `reloadSkills`](#sessionstart-decision-control). No blocking or decision control |
1038| Setup, Notification, SessionEnd, PostCompact, InstructionsLoaded, StopFailure, CwdChanged, DirectoryAdded, FileChanged | None | No decision control. Used for side effects like logging or cleanup |
10391039
10401040A few events can also rewrite content rather than only allow or block it:
10411041
from line 1107
11071107
11081108The matcher value corresponds to how the session was initiated:
11091109
1110| Matcher | When it fires |
1111| :-------- | :------------------------------------------------------------------------------------------------------------------------------------- |
1112| `startup` | New session |
1113| `resume` | `--resume`, `--continue`, or `/resume` |
1114| `clear` | `/clear` |
1115| `compact` | Auto or manual compaction |
1116| `fork` | A new session forked from an existing one: `--fork-session` with `--resume` or `--continue`, the `/fork` background copy, or `/branch` |
1110| Matcher | When it fires |
1111| :- | :- |
1112| `startup` | New session |
1113| `resume` | `--resume`, `--continue`, or `/resume` |
1114| `clear` | `/clear` |
1115| `compact` | Auto or manual compaction |
1116| `fork` | A new session forked from an existing one: `--fork-session` with `--resume` or `--continue`, the `/fork` background copy, or `/branch` |
11171117
11181118Before v2.1.214, forked sessions reported source `"resume"`.
11191119
from line 1129
11291129
11301130In addition to the [common input fields](#common-input-fields), SessionStart hooks receive `source` and optionally `model`, `agent_type`, and `session_title`:
11311131
1132| Field | Description |
1133| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1134| `source` | How the session started: `"startup"` for new sessions, `"resume"` for resumed sessions, `"clear"` after `/clear`, `"compact"` after compaction, or `"fork"` for a new session forked from an existing one |
1135| `model` | The active model identifier. It can be omitted, for example after `/clear` or when a session is restored through conversation recovery, so check for the field before reading it |
1136| `agent_type` | The agent name, present when you start Claude Code with `claude --agent <name>` |
1132| Field | Description |
1133| :- | :- |
1134| `source` | How the session started: `"startup"` for new sessions, `"resume"` for resumed sessions, `"clear"` after `/clear`, `"compact"` after compaction, or `"fork"` for a new session forked from an existing one |
1135| `model` | The active model identifier. It can be omitted, for example after `/clear` or when a session is restored through conversation recovery, so check for the field before reading it |
1136| `agent_type` | The agent name, present when you start Claude Code with `claude --agent <name>` |
11371137| `session_title` | The current session title if one is already set, for example via `--name` or `/rename`. A hook that emits `sessionTitle` can check `session_title` first to avoid overwriting a title the user set explicitly |
11381138
11391139When `source` is `"resume"` or `"fork"` and the transcript contains at least one response from Claude, SessionStart hooks also receive the four fields below. Your hook can use them to report what resuming a stale conversation costs before the first request, for example in a [`systemMessage`](#json-output). These fields require Claude Code v2.1.251 or later.
11401140
1141| Field | Description |
1142| :---------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1143| `seconds_since_last_response` | Wall-clock seconds since the last response in the resumed transcript |
1144| `context_tokens` | Tokens the first request of the resumed session re-sends as its prompt |
1141| Field | Description |
1142| :- | :- |
1143| `seconds_since_last_response` | Wall-clock seconds since the last response in the resumed transcript |
1144| `context_tokens` | Tokens the first request of the resumed session re-sends as its prompt |
11451145| `prompt_cache_likely_expired` | `true` when the last response is older than the session's [prompt cache lifetime](/docs/en/prompt-caching#cache-lifetime) or a later compaction replaced the cached conversation |
1146| `estimated_cache_write_usd` | Estimated cost in US dollars of writing `context_tokens` to the prompt cache on the session's model, excluding the response |
1146| `estimated_cache_write_usd` | Estimated cost in US dollars of writing `context_tokens` to the prompt cache on the session's model, excluding the response |
11471147
11481148This example shows the input for a session resumed 90 minutes after its last response:
11491149
from line 1166
11661166
11671167Claude Code adds stdout it [treats as plain text](#exit-code-0) to Claude's context. In addition to the [JSON output fields](#json-output) available to all hooks, you can return these event-specific fields:
11681168
1169| Field | Description |
1170| :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1171| `additionalContext` | String added to Claude's context at the start of the conversation, before the first prompt. See [Add context for Claude](#add-context-for-claude) for how the text is delivered and what to put in it |
1169| Field | Description |
1170| :- | :- |
1171| `additionalContext` | String added to Claude's context at the start of the conversation, before the first prompt. See [Add context for Claude](#add-context-for-claude) for how the text is delivered and what to put in it |
11721172| `initialUserMessage` | String used as the first user message of the session. Applies in [non-interactive mode](/docs/en/headless) with the `-p` flag, where it becomes the first turn even if no prompt is provided. If a prompt is provided, it follows as the next turn. Unlike `additionalContext`, which attaches to an existing turn, this creates the turn |
1173| `sessionTitle` | Sets the session title, with the same effect as `/rename`. Use to name sessions automatically from the launch folder, git branch, or worktree name. Applies when `source` is `"startup"`, `"resume"`, or `"fork"`; ignored on `"clear"` and `"compact"` |
1174| `watchPaths` | Array of absolute paths to watch for [FileChanged](#filechanged) events during this session |
1175| `reloadSkills` | Boolean. When `true`, Claude Code re-scans the [skill](/docs/en/skills) and command directories after the SessionStart hooks complete, so skills the hook installed are available in the same session, starting with the first prompt |
1173| `sessionTitle` | Sets the session title, with the same effect as `/rename`. Use to name sessions automatically from the launch folder, git branch, or worktree name. Applies when `source` is `"startup"`, `"resume"`, or `"fork"`; ignored on `"clear"` and `"compact"` |
1174| `watchPaths` | Array of absolute paths to watch for [FileChanged](#filechanged) events during this session |
1175| `reloadSkills` | Boolean. When `true`, Claude Code re-scans the [skill](/docs/en/skills) and command directories after the SessionStart hooks complete, so skills the hook installed are available in the same session, starting with the first prompt |
11761176
11771177```json theme={null}
11781178{
from line 1246
12461246
12471247The matcher value corresponds to the CLI flag that triggered the hook:
12481248
1249| Matcher | When it fires |
1250| :------------ | :----------------------------------------- |
1251| `init` | `claude --init-only` or `claude -p --init` |
1252| `maintenance` | `claude -p --maintenance` |
1249| Matcher | When it fires |
1250| :- | :- |
1251| `init` | `claude --init-only` or `claude -p --init` |
1252| `maintenance` | `claude -p --maintenance` |
12531253
12541254When you run `claude --init-only`, Claude Code runs Setup hooks and `SessionStart` hooks with the `startup` matcher, then exits without starting a conversation.
12551255
from line 1291
12911291
12921292In addition to the [common input fields](#common-input-fields), InstructionsLoaded hooks receive these fields:
12931293
1294| Field | Description |
1295| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1296| `file_path` | Absolute path to the instruction file that was loaded |
1297| `memory_type` | Scope of the file: `"User"`, `"Project"`, `"Local"`, or `"Managed"` |
1298| `load_reason` | Why the file was loaded: `"session_start"`, `"nested_traversal"`, `"path_glob_match"`, `"include"`, or `"compact"`. The `"compact"` value fires when instruction files are re-loaded after a compaction event |
1299| `globs` | Path glob patterns from the file's `paths:` frontmatter, if any. Present only for `path_glob_match` loads |
1300| `trigger_file_path` | Path to the file whose access triggered this load, for lazy loads |
1301| `parent_file_path` | Path to the parent instruction file that included this one, for `include` loads |
1294| Field | Description |
1295| :- | :- |
1296| `file_path` | Absolute path to the instruction file that was loaded |
1297| `memory_type` | Scope of the file: `"User"`, `"Project"`, `"Local"`, or `"Managed"` |
1298| `load_reason` | Why the file was loaded: `"session_start"`, `"nested_traversal"`, `"path_glob_match"`, `"include"`, or `"compact"`. The `"compact"` value fires when instruction files are re-loaded after a compaction event |
1299| `globs` | Path glob patterns from the file's `paths:` frontmatter, if any. Present only for `path_glob_match` loads |
1300| `trigger_file_path` | Path to the file whose access triggered this load, for lazy loads |
1301| `parent_file_path` | Path to the parent instruction file that included this one, for `include` loads |
13021302
13031303```json theme={null}
13041304{
from line 1356
13561356
13571357To block a prompt, return a JSON object with `decision` set to `"block"`:
13581358
1359| Field | Description |
1360| :----------------------- | :--------------------------------------------------------------------------------------------------------------------- |
1361| `decision` | `"block"` prevents the prompt from being processed and erases it from context. Omit to allow the prompt to proceed |
1362| `reason` | Shown to the user when `decision` is `"block"`. Not added to context |
1363| `additionalContext` | String added to Claude's context alongside the submitted prompt. See [Add context for Claude](#add-context-for-claude) |
1364| `sessionTitle` | Sets the session title. Use to name sessions automatically based on the prompt content |
1365| `suppressOriginalPrompt` | If `true` when `decision` is `"block"`, omits the original prompt text from the block message shown to the user |
1359| Field | Description |
1360| :- | :- |
1361| `decision` | `"block"` prevents the prompt from being processed and erases it from context. Omit to allow the prompt to proceed |
1362| `reason` | Shown to the user when `decision` is `"block"`. Not added to context |
1363| `additionalContext` | String added to Claude's context alongside the submitted prompt. See [Add context for Claude](#add-context-for-claude) |
1364| `sessionTitle` | Sets the session title. Use to name sessions automatically based on the prompt content |
1365| `suppressOriginalPrompt` | If `true` when `decision` is `"block"`, omits the original prompt text from the block message shown to the user |
13661366
13671367A hook that blocks by exiting 2 routes the same way as `reason`: the block message shows the stderr text to the user, and it isn't added to context.
13681368
from line 1409
14091409
14101410`UserPromptExpansion` hooks can block the expansion or add context. All [JSON output fields](#json-output) are available.
14111411
1412| Field | Description |
1413| :------------------ | :-------------------------------------------------------------------------------------------------------------------- |
1414| `decision` | `"block"` prevents the command from expanding. Omit to allow it to proceed |
1415| `reason` | Shown to the user when `decision` is `"block"` |
1412| Field | Description |
1413| :- | :- |
1414| `decision` | `"block"` prevents the command from expanding. Omit to allow it to proceed |
1415| `reason` | Shown to the user when `decision` is `"block"` |
14161416| `additionalContext` | String added to Claude's context alongside the expanded prompt. See [Add context for Claude](#add-context-for-claude) |
14171417
14181418A hook that blocks by exiting 2 routes the same way as `reason`: the block message shows the stderr text to the user.
from line 1450
14501450
14511451In addition to the [common input fields](#common-input-fields), MessageDisplay hooks receive identifiers for the turn and message, the position of this call within the message, and the new text in `delta`. Batch boundaries depend on how the text streams, so use `index` and `final` to track progress through a message rather than expecting lines to be grouped a particular way.
14521452
1453| Field | Description |
1454| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1455| `turn_id` | UUID of the current turn |
1456| `message_id` | UUID of the assistant message being displayed. Stable across every batch of the same message. This is not the API `msg_…` id, so it can't be correlated with transcript message ids |
1457| `index` | Zero-based index of this batch within the message |
1458| `final` | `true` on the message's last batch. Each message has exactly one final batch |
1459| `delta` | The newly completed lines since the prior batch, terminating newlines included. Always whole lines, except the final batch which may end mid-line. In interactive runs, the final batch's delta is empty when the message ends on a newline, so treat `final`, not a non-empty delta, as the end-of-message signal. In Agent SDK and `claude -p` runs, the single call carries the entire message |
1453| Field | Description |
1454| :- | :- |
1455| `turn_id` | UUID of the current turn |
1456| `message_id` | UUID of the assistant message being displayed. Stable across every batch of the same message. This is not the API `msg_…` id, so it can't be correlated with transcript message ids |
1457| `index` | Zero-based index of this batch within the message |
1458| `final` | `true` on the message's last batch. Each message has exactly one final batch |
1459| `delta` | The newly completed lines since the prior batch, terminating newlines included. Always whole lines, except the final batch which may end mid-line. In interactive runs, the final batch's delta is empty when the message ends on a newline, so treat `final`, not a non-empty delta, as the end-of-message signal. In Agent SDK and `claude -p` runs, the single call carries the entire message |
14601460
14611461```json theme={null}
14621462{
from line 1476
14761476
14771477In addition to the [JSON output fields](#json-output) available to all hooks, MessageDisplay hooks can return `displayContent` to replace the delta on screen:
14781478
1479| Field | Description |
1480| :--------------- | :-------------------------------------------------------------------- |
1479| Field | Description |
1480| :- | :- |
14811481| `displayContent` | Text displayed in place of the delta. Omit it to display the original |
14821482
14831483MessageDisplay hooks have no decision control. They can't block the message or change what is stored in the transcript or sent to Claude. Claude Code acts on `displayContent` from their JSON output and discards `systemMessage` and `continue`.
from line 1611
16111611
16121612Executes shell commands.
16131613
1614| Field | Type | Example | Description |
1615| :------------------ | :------ | :----------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------- |
1616| `command` | string | `"npm test"` | The shell command to execute |
1617| `description` | string | `"Run test suite"` | Optional description of what the command does |
1618| `timeout` | number | `120000` | Optional timeout in milliseconds. Values above the [maximum](/docs/en/tools-reference#bash-tool-behavior) are reduced to the maximum rather than rejected |
1619| `run_in_background` | boolean | `false` | Whether to run the command in background |
1614| Field | Type | Example | Description |
1615| :- | :- | :- | :- |
1616| `command` | string | `"npm test"` | The shell command to execute |
1617| `description` | string | `"Run test suite"` | Optional description of what the command does |
1618| `timeout` | number | `120000` | Optional timeout in milliseconds. Values above the [maximum](/docs/en/tools-reference#bash-tool-behavior) are reduced to the maximum rather than rejected |
1619| `run_in_background` | boolean | `false` | Whether to run the command in background |
16201620
16211621When a Bash command changes files in a Git repository, Claude Code can record what changed. It records the changes in every permission mode when the [`bashEditDiffEnabled`](/docs/en/settings-reference#basheditdiffenabled) setting turns recording on; that setting's entry says which files can set it. Otherwise it records them only in auto mode and `bypassPermissions` mode, and only when Claude Code directs Claude to edit files through Bash. Set `bashEditDiffEnabled` to `false` to turn the recording off. Background commands and read-only commands carry no diff.
16221622
from line 1628
16281628
16291629`changedFiles` and `files` list what the command changed; the remaining fields say how complete and how reliable that list is.
16301630
1631| Field | Type | Example | Description |
1632| :------------- | :------ | :------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------- |
1633| `changedFiles` | array | `["/path/to/src/app.ts"]` | Absolute paths of the files the command changed, at most 200. Present whenever `files` holds a diff or `moreFiles` is above zero |
1634| `files` | array | `[{"filePath": "/path/to/src/app.ts", "hunks": [...]}]` | Diffs of up to 5 changed files, for display. `created` or `deleted` is `true` for a file the command added or removed |
1635| `moreFiles` | number | `2` | Count of changed files with no diff in `files` |
1636| `unavailable` | boolean | `true` | Set when the diff is incomplete or couldn't be taken |
1637| `skipped` | boolean | `true` | Set for a Git command that moves the working tree, such as `git checkout` or `git stash`, so Claude Code takes no diff |
1638| `shared` | boolean | `true` | Set when another Bash tool call, such as a subagent's, ran in the same repository at the same time, so some listed changes may be that command's |
1631| Field | Type | Example | Description |
1632| :- | :- | :- | :- |
1633| `changedFiles` | array | `["/path/to/src/app.ts"]` | Absolute paths of the files the command changed, at most 200. Present whenever `files` holds a diff or `moreFiles` is above zero |
1634| `files` | array | `[{"filePath": "/path/to/src/app.ts", "hunks": [...]}]` | Diffs of up to 5 changed files, for display. `created` or `deleted` is `true` for a file the command added or removed |
1635| `moreFiles` | number | `2` | Count of changed files with no diff in `files` |
1636| `unavailable` | boolean | `true` | Set when the diff is incomplete or couldn't be taken |
1637| `skipped` | boolean | `true` | Set for a Git command that moves the working tree, such as `git checkout` or `git stash`, so Claude Code takes no diff |
1638| `shared` | boolean | `true` | Set when another Bash tool call, such as a subagent's, ran in the same repository at the same time, so some listed changes may be that command's |
16391639
16401640<a id="powershell" />
16411641
from line 1645
16451645
16461646The fields match the Bash tool, with the command string in `command`:
16471647
1648| Field | Type | Example | Description |
1649| :------------------ | :------ | :------------------------- | :-------------------------------------------- |
1650| `command` | string | `"Get-ChildItem -Recurse"` | The PowerShell command to execute |
1651| `description` | string | `"List files recursively"` | Optional description of what the command does |
1652| `timeout` | number | `120000` | Optional timeout in milliseconds |
1653| `run_in_background` | boolean | `false` | Whether to run the command in background |
1648| Field | Type | Example | Description |
1649| :- | :- | :- | :- |
1650| `command` | string | `"Get-ChildItem -Recurse"` | The PowerShell command to execute |
1651| `description` | string | `"List files recursively"` | Optional description of what the command does |
1652| `timeout` | number | `120000` | Optional timeout in milliseconds |
1653| `run_in_background` | boolean | `false` | Whether to run the command in background |
16541654
16551655Match `Bash|PowerShell` in hooks that inspect shell commands, so they cover both tools:
16561656
from line 1662
16621662
16631663Creates or overwrites a file.
16641664
1665| Field | Type | Example | Description |
1666| :---------- | :----- | :-------------------- | :--------------------------------- |
1665| Field | Type | Example | Description |
1666| :- | :- | :- | :- |
16671667| `file_path` | string | `"/path/to/file.txt"` | Absolute path to the file to write |
1668| `content` | string | `"file content"` | Content to write to the file |
1668| `content` | string | `"file content"` | Content to write to the file |
16691669
16701670##### Edit
16711671
16721672Replaces a string in an existing file.
16731673
1674| Field | Type | Example | Description |
1675| :------------ | :------ | :-------------------- | :--------------------------------- |
1676| `file_path` | string | `"/path/to/file.txt"` | Absolute path to the file to edit |
1677| `old_string` | string | `"original text"` | Text to find and replace |
1678| `new_string` | string | `"replacement text"` | Replacement text |
1679| `replace_all` | boolean | `false` | Whether to replace all occurrences |
1674| Field | Type | Example | Description |
1675| :- | :- | :- | :- |
1676| `file_path` | string | `"/path/to/file.txt"` | Absolute path to the file to edit |
1677| `old_string` | string | `"original text"` | Text to find and replace |
1678| `new_string` | string | `"replacement text"` | Replacement text |
1679| `replace_all` | boolean | `false` | Whether to replace all occurrences |
16801680
16811681##### Read
16821682
16831683Reads file contents.
16841684
1685| Field | Type | Example | Description |
1686| :---------- | :----- | :-------------------- | :----------------------------------------- |
1687| `file_path` | string | `"/path/to/file.txt"` | Absolute path to the file to read |
1688| `offset` | number | `10` | Optional line number to start reading from |
1689| `limit` | number | `50` | Optional number of lines to read |
1685| Field | Type | Example | Description |
1686| :- | :- | :- | :- |
1687| `file_path` | string | `"/path/to/file.txt"` | Absolute path to the file to read |
1688| `offset` | number | `10` | Optional line number to start reading from |
1689| `limit` | number | `50` | Optional number of lines to read |
16901690
16911691##### Glob
16921692
16931693Finds files matching a glob pattern.
16941694
1695| Field | Type | Example | Description |
1696| :-------- | :----- | :--------------- | :--------------------------------------------------------------------- |
1697| `pattern` | string | `"**/*.ts"` | Glob pattern to match files against |
1698| `path` | string | `"/path/to/dir"` | Optional directory to search in. Defaults to current working directory |
1695| Field | Type | Example | Description |
1696| :- | :- | :- | :- |
1697| `pattern` | string | `"**/*.ts"` | Glob pattern to match files against |
1698| `path` | string | `"/path/to/dir"` | Optional directory to search in. Defaults to current working directory |
16991699
17001700##### Grep
17011701
17021702Searches file contents with regular expressions.
17031703
1704| Field | Type | Example | Description |
1705| :------------ | :------ | :--------------- | :------------------------------------------------------------------------------------ |
1706| `pattern` | string | `"TODO.*fix"` | Regular expression pattern to search for |
1707| `path` | string | `"/path/to/dir"` | Optional file or directory to search in |
1708| `glob` | string | `"*.ts"` | Optional glob pattern to filter files |
1709| `output_mode` | string | `"content"` | `"content"`, `"files_with_matches"`, or `"count"`. Defaults to `"files_with_matches"` |
1710| `-i` | boolean | `true` | Case insensitive search |
1711| `multiline` | boolean | `false` | Enable multiline matching |
1704| Field | Type | Example | Description |
1705| :- | :- | :- | :- |
1706| `pattern` | string | `"TODO.*fix"` | Regular expression pattern to search for |
1707| `path` | string | `"/path/to/dir"` | Optional file or directory to search in |
1708| `glob` | string | `"*.ts"` | Optional glob pattern to filter files |
1709| `output_mode` | string | `"content"` | `"content"`, `"files_with_matches"`, or `"count"`. Defaults to `"files_with_matches"` |
1710| `-i` | boolean | `true` | Case insensitive search |
1711| `multiline` | boolean | `false` | Enable multiline matching |
17121712
17131713##### WebFetch
17141714
17151715Fetches and processes web content.
17161716
1717| Field | Type | Example | Description |
1718| :------- | :----- | :---------------------------- | :----------------------------------- |
1719| `url` | string | `"https://example.com/api"` | URL to fetch content from |
1717| Field | Type | Example | Description |
1718| :- | :- | :- | :- |
1719| `url` | string | `"https://example.com/api"` | URL to fetch content from |
17201720| `prompt` | string | `"Extract the API endpoints"` | Prompt to run on the fetched content |
17211721
17221722##### WebSearch
17231723
17241724Searches the web.
17251725
1726| Field | Type | Example | Description |
1727| :---------------- | :----- | :----------------------------- | :------------------------------------------------ |
1728| `query` | string | `"react hooks best practices"` | Search query |
1729| `allowed_domains` | array | `["docs.example.com"]` | Optional: only include results from these domains |
1730| `blocked_domains` | array | `["spam.example.com"]` | Optional: exclude results from these domains |
1726| Field | Type | Example | Description |
1727| :- | :- | :- | :- |
1728| `query` | string | `"react hooks best practices"` | Search query |
1729| `allowed_domains` | array | `["docs.example.com"]` | Optional: only include results from these domains |
1730| `blocked_domains` | array | `["spam.example.com"]` | Optional: exclude results from these domains |
17311731
17321732##### Agent
17331733
17341734Spawns a [subagent](/docs/en/sub-agents).
17351735
1736| Field | Type | Example | Description |
1737| :-------------- | :----- | :------------------------- | :------------------------------------------- |
1738| `prompt` | string | `"Find all API endpoints"` | The task for the agent to perform |
1739| `description` | string | `"Find API endpoints"` | Short description of the task |
1740| `subagent_type` | string | `"Explore"` | Type of specialized agent to use |
1741| `model` | string | `"sonnet"` | Optional model alias to override the default |
1736| Field | Type | Example | Description |
1737| :- | :- | :- | :- |
1738| `prompt` | string | `"Find all API endpoints"` | The task for the agent to perform |
1739| `description` | string | `"Find API endpoints"` | Short description of the task |
1740| `subagent_type` | string | `"Explore"` | Type of specialized agent to use |
1741| `model` | string | `"sonnet"` | Optional model alias to override the default |
17421742
17431743When a foreground Agent call completes, your [PostToolUse hook](#posttooluse) receives the subagent's result and run telemetry in `tool_response`. Read these fields to inspect the run; for token and cost rollups across subagents, use the [token and cost counters](/docs/en/monitoring-usage#token-counter) filtered to `query_source` `"subagent"`, since `totalTokens` and `usage` cover the final request only:
17441744
1745| Field | Type | Example | Description |
1746| :------------------ | :----- | :---------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1747| `status` | string | `"completed"` | `"completed"` for foreground subagents, `"async_launched"` for background subagents. As of v2.1.198, subagents run in the background by default, so an omitted `run_in_background` also produces `"async_launched"` |
1748| `agentId` | string | `"a4d2c8f1e0b3a297"` | Identifier for the subagent run |
1749| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | The subagent's final text blocks, or, for a subagent whose report goes through `SubagentHandback`, a short note about that hand-back in their place |
1750| `resolvedModel` | string | `"claude-sonnet-4-5"` | Model the subagent started on, which may differ from the requested model |
1751| `modelsUsed` | array | `["claude-sonnet-4-5", "claude-haiku-4-5"]` | Models used in order, with consecutive repeats collapsed; set only when the model was swapped mid-run. Requires Claude Code v2.1.212 or later |
1752| `totalTokens` | number | `12450` | Token count from the subagent's final API request: input, output, and cache tokens combined. This isn't a total across the whole run |
1753| `totalDurationMs` | number | `48211` | Wall-clock duration of the subagent run |
1754| `totalToolUseCount` | number | `7` | Count of tool calls the subagent made |
1755| `usage` | object | `{"input_tokens": 8320, ...}` | Per-type token breakdown of the final API request: `input_tokens`, `output_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens` |
1745| Field | Type | Example | Description |
1746| :- | :- | :- | :- |
1747| `status` | string | `"completed"` | `"completed"` for foreground subagents, `"async_launched"` for background subagents. As of v2.1.198, subagents run in the background by default, so an omitted `run_in_background` also produces `"async_launched"` |
1748| `agentId` | string | `"a4d2c8f1e0b3a297"` | Identifier for the subagent run |
1749| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | The subagent's final text blocks, or, for a subagent whose report goes through `SubagentHandback`, a short note about that hand-back in their place |
1750| `resolvedModel` | string | `"claude-sonnet-4-5"` | Model the subagent started on, which may differ from the requested model |
1751| `modelsUsed` | array | `["claude-sonnet-4-5", "claude-haiku-4-5"]` | Models used in order, with consecutive repeats collapsed; set only when the model was swapped mid-run. Requires Claude Code v2.1.212 or later |
1752| `totalTokens` | number | `12450` | Token count from the subagent's final API request: input, output, and cache tokens combined. This isn't a total across the whole run |
1753| `totalDurationMs` | number | `48211` | Wall-clock duration of the subagent run |
1754| `totalToolUseCount` | number | `7` | Count of tool calls the subagent made |
1755| `usage` | object | `{"input_tokens": 8320, ...}` | Per-type token breakdown of the final API request: `input_tokens`, `output_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens` |
17561756
17571757On Claude Code v2.1.271 or later, a subagent that runs with the [`SubagentHandback`](/docs/en/tools-reference) tool, which Claude Code provides in [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode), delivers its report through that tool rather than returning it as text. The `content` field of its `completed` result then carries a short note about that hand-back rather than the report itself. To read the report, match a `PreToolUse` or `PostToolUse` hook on `SubagentHandback` and read `tool_input.message`.
17581758
from line 1766
17661766
17671767Asks the user one to four multiple-choice questions.
17681768
1769| Field | Type | Example | Description |
1770| :---------- | :----- | :----------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1771| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]` | Questions to present, each with a `question` string, short `header`, `options` array, and optional `multiSelect` flag |
1772| `answers` | object | `{"Which framework?": "React"}` | Optional. Maps question text to the selected option label. Multi-select answers join labels with commas. Claude doesn't set this field; supply it via `updatedInput` to answer programmatically |
1769| Field | Type | Example | Description |
1770| :- | :- | :- | :- |
1771| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]` | Questions to present, each with a `question` string, short `header`, `options` array, and optional `multiSelect` flag |
1772| `answers` | object | `{"Which framework?": "React"}` | Optional. Maps question text to the selected option label. Multi-select answers join labels with commas. Claude doesn't set this field; supply it via `updatedInput` to answer programmatically |
17731773
17741774##### ExitPlanMode
17751775
17761776Presents a plan and asks the user to approve it before Claude leaves [plan mode](/docs/en/permission-modes#analyze-before-you-edit-with-plan-mode). Claude writes the plan to a file on disk before calling the tool, so the literal `tool_input` from the model is typically empty. Claude Code injects the plan content and file path before passing the input to hooks.
17771777
1778| Field | Type | Example | Description |
1779| :--------------- | :----- | :------------------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------- |
1780| `plan` | string | `"## Refactor auth\n1. Extract..."` | Plan content in Markdown. Injected from the plan file on disk |
1781| `planFilePath` | string | `"/Users/.../plans/refactor-auth.md"` | Path to the plan file. Injected |
1782| `allowedPrompts` | array | `[{"tool": "Bash", "prompt": "run tests"}]` | Deprecated. Claude Code accepts the field but ignores it. Before v2.1.205, it carried prompt-based permissions Claude requested to implement the plan |
1778| Field | Type | Example | Description |
1779| :- | :- | :- | :- |
1780| `plan` | string | `"## Refactor auth\n1. Extract..."` | Plan content in Markdown. Injected from the plan file on disk |
1781| `planFilePath` | string | `"/Users/.../plans/refactor-auth.md"` | Path to the plan file. Injected |
1782| `allowedPrompts` | array | `[{"tool": "Bash", "prompt": "run tests"}]` | Deprecated. Claude Code accepts the field but ignores it. Before v2.1.205, it carried prompt-based permissions Claude requested to implement the plan |
17831783
17841784In `PostToolUse`, `tool_response` is an object with `plan` and `filePath` fields holding the approved plan, plus internal status flags. Read `tool_response.plan` for the plan content rather than re-reading the file from disk.
17851785
from line 1787
17871787
17881788`PreToolUse` hooks can control whether a tool call proceeds. Unlike other hooks that use a top-level `decision` field, PreToolUse returns its decision inside a `hookSpecificOutput` object. This gives it richer control: four outcomes (allow, deny, ask, or defer) plus the ability to modify tool input before execution.
17891789
1790| Field | Description |
1791| :------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1792| `permissionDecision` | `"allow"` skips the permission prompt, except for the [actions no mode auto-approves](/docs/en/permission-modes#actions-no-mode-auto-approves) and for `AskUserQuestion` and `ExitPlanMode`, which need [`updatedInput` paired with it](#allow-with-updatedinput). `"deny"` prevents the tool call. `"ask"` prompts the user to confirm. `"defer"` exits gracefully so the tool can be resumed later. [Deny and ask rules](/docs/en/permissions#manage-permissions) are still evaluated regardless of what the hook returns |
1793| `permissionDecisionReason` | For `"allow"` and `"ask"`, shown to the user but not Claude. For `"deny"`, shown to Claude. For `"defer"`, ignored |
1794| `updatedInput` | Modifies the tool's input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones. Claude Code evaluates permission rules and a Bash command's [auto-background eligibility](/docs/en/tools-reference#background-commands) against the input your hook returns, not the input Claude sent. Combine with `"allow"` to auto-approve, or `"ask"` to show the modified input to the user. For `"defer"`, ignored |
1795| `additionalContext` | String added to Claude's context alongside the tool result. Ignored when `permissionDecision` is `"defer"`. See [Add context for Claude](#add-context-for-claude) |
1790| Field | Description |
1791| :- | :- |
1792| `permissionDecision` | `"allow"` skips the permission prompt, except for the [actions no mode auto-approves](/docs/en/permission-modes#actions-no-mode-auto-approves) and for `AskUserQuestion` and `ExitPlanMode`, which need [`updatedInput` paired with it](#allow-with-updatedinput). `"deny"` prevents the tool call. `"ask"` prompts the user to confirm. `"defer"` exits gracefully so the tool can be resumed later. [Deny and ask rules](/docs/en/permissions#manage-permissions) are still evaluated regardless of what the hook returns |
1793| `permissionDecisionReason` | For `"allow"` and `"ask"`, shown to the user but not Claude. For `"deny"`, shown to Claude. For `"defer"`, ignored |
1794| `updatedInput` | Modifies the tool's input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones. Claude Code evaluates permission rules and a Bash command's [auto-background eligibility](/docs/en/tools-reference#background-commands) against the input your hook returns, not the input Claude sent. Combine with `"allow"` to auto-approve, or `"ask"` to show the modified input to the user. For `"defer"`, ignored |
1795| `additionalContext` | String added to Claude's context alongside the tool result. Ignored when `permissionDecision` is `"defer"`. See [Add context for Claude](#add-context-for-claude) |
17961796
17971797When multiple PreToolUse hooks return different decisions, precedence is `deny` > `defer` > `ask` > `allow`.
17981798
from line 1912
19121912
19131913`PermissionRequest` hooks can allow or deny permission requests. In addition to the [JSON output fields](#json-output) available to all hooks, your hook script can return a `decision` object with these event-specific fields:
19141914
1915| Field | Description |
1916| :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1917| `behavior` | `"allow"` grants the permission, `"deny"` denies it. [Deny and ask rules](/docs/en/permissions#manage-permissions) are still evaluated, so a hook returning `"allow"` doesn't override a matching deny rule |
1918| `updatedInput` | For `"allow"` only: modifies the tool's input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones. The modified input is re-evaluated against deny and ask rules |
1919| `updatedPermissions` | For `"allow"` only: array of [permission update entries](#permission-update-entries) to apply, such as adding an allow rule or changing the session permission mode |
1920| `message` | For `"deny"` only: tells Claude why the permission was denied |
1921| `interrupt` | For `"deny"` only: if `true`, stops Claude |
1915| Field | Description |
1916| :- | :- |
1917| `behavior` | `"allow"` grants the permission, `"deny"` denies it. [Deny and ask rules](/docs/en/permissions#manage-permissions) are still evaluated, so a hook returning `"allow"` doesn't override a matching deny rule |
1918| `updatedInput` | For `"allow"` only: modifies the tool's input parameters before execution. Replaces the entire input object, so include unchanged fields alongside modified ones. The modified input is re-evaluated against deny and ask rules |
1919| `updatedPermissions` | For `"allow"` only: array of [permission update entries](#permission-update-entries) to apply, such as adding an allow rule or changing the session permission mode |
1920| `message` | For `"deny"` only: tells Claude why the permission was denied |
1921| `interrupt` | For `"deny"` only: if `true`, stops Claude |
19221922
19231923A 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.
19241924
from line 1940
19401940
19411941The `updatedPermissions` output field and the [`permission_suggestions` input field](#permissionrequest-input) both use the same array of entry objects. Each entry has a `type` that determines its other fields, and a `destination` that controls where the change is written.
19421942
1943| `type` | Fields | Effect |
1944| :------------------ | :--------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1945| `addRules` | `rules`, `behavior`, `destination` | Adds permission rules. `rules` is an array of `{toolName, ruleContent?}` objects. Omit `ruleContent` to match the whole tool. `behavior` is `"allow"`, `"deny"`, or `"ask"` |
1946| `replaceRules` | `rules`, `behavior`, `destination` | Replaces all rules of the given `behavior` at the `destination` with the provided `rules` |
1947| `removeRules` | `rules`, `behavior`, `destination` | Removes matching rules of the given `behavior` |
1948| `setMode` | `mode`, `destination` | Changes the permission mode. Valid modes are `default`, `auto`, `acceptEdits`, `dontAsk`, `bypassPermissions`, `plan`, and `manual` as an alias for `default`. The `manual` alias requires Claude Code v2.1.200 or later |
1949| `addDirectories` | `directories`, `destination` | Adds working directories. `directories` is an array of path strings |
1950| `removeDirectories` | `directories`, `destination` | Removes working directories |
1943| `type` | Fields | Effect |
1944| :- | :- | :- |
1945| `addRules` | `rules`, `behavior`, `destination` | Adds permission rules. `rules` is an array of `{toolName, ruleContent?}` objects. Omit `ruleContent` to match the whole tool. `behavior` is `"allow"`, `"deny"`, or `"ask"` |
1946| `replaceRules` | `rules`, `behavior`, `destination` | Replaces all rules of the given `behavior` at the `destination` with the provided `rules` |
1947| `removeRules` | `rules`, `behavior`, `destination` | Removes matching rules of the given `behavior` |
1948| `setMode` | `mode`, `destination` | Changes the permission mode. Valid modes are `default`, `auto`, `acceptEdits`, `dontAsk`, `bypassPermissions`, `plan`, and `manual` as an alias for `default`. The `manual` alias requires Claude Code v2.1.200 or later |
1949| `addDirectories` | `directories`, `destination` | Adds working directories. `directories` is an array of path strings |
1950| `removeDirectories` | `directories`, `destination` | Removes working directories |
19511951
19521952<Note>
19531953 `setMode` with `bypassPermissions` only takes effect if you launched the session with bypass mode already available: `--dangerously-skip-permissions`, `--permission-mode bypassPermissions`, `--allow-dangerously-skip-permissions`, or `permissions.defaultMode: "bypassPermissions"` in [user, `--settings`, or managed settings](/docs/en/settings-reference#permissions-defaultmode). Otherwise the update is a no-op. The update is also a no-op when [`permissions.disableBypassPermissionsMode`](/docs/en/permissions#managed-settings) disables the mode, or when the session starts in [restricted mode](/docs/en/cli-reference#cli-flags).
from line 1957
19571957
19581958The `destination` field on every entry determines whether the change stays in memory or persists to a settings file.
19591959
1960| `destination` | Writes to |
1961| :---------------- | :---------------------------------------------- |
1962| `session` | in-memory only, discarded when the session ends |
1963| `localSettings` | `.claude/settings.local.json` |
1964| `projectSettings` | `.claude/settings.json` |
1965| `userSettings` | `~/.claude/settings.json` |
1960| `destination` | Writes to |
1961| :- | :- |
1962| `session` | in-memory only, discarded when the session ends |
1963| `localSettings` | `.claude/settings.local.json` |
1964| `projectSettings` | `.claude/settings.json` |
1965| `userSettings` | `~/.claude/settings.json` |
19661966
19671967A hook can echo one of the `permission_suggestions` it received as its own `updatedPermissions` output.
19681968
from line 2002
20022002}
20032003```
20042004
2005| Field | Description |
2006| :------------ | :------------------------------------------------------------------------------------------------------------ |
2005| Field | Description |
2006| :- | :- |
20072007| `duration_ms` | Optional. Tool execution time in milliseconds. Excludes time spent in permission prompts and PreToolUse hooks |
20082008
20092009#### PostToolUse decision control
20102010
20112011`PostToolUse` hooks can provide feedback to Claude after tool execution. In addition to the [JSON output fields](#json-output) available to all hooks, your hook script can return these event-specific fields:
20122012
2013| Field | Description |
2014| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2015| `decision` | `"block"` adds the `reason` next to the tool result. Claude still sees the original output; to replace it, use `updatedToolOutput` |
2016| `reason` | Explanation shown to Claude when `decision` is `"block"` |
2017| `additionalContext` | String added to Claude's context alongside the tool result. See [Add context for Claude](#add-context-for-claude) |
2018| `classifierContext` | Short note about this call's result for the [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) classifier rather than for Claude. See [Annotate a result for the auto mode classifier](#annotate-a-result-for-the-auto-mode-classifier). Requires Claude Code v2.1.236 or later |
2019| `updatedToolOutput` | Replaces the tool's output with the provided value before it is sent to Claude. The value must match the tool's output shape |
2020| `updatedMCPToolOutput` | Replaces the output for [MCP tools](#match-mcp-tools) only. Prefer `updatedToolOutput`, which works for all tools |
2013| Field | Description |
2014| :- | :- |
2015| `decision` | `"block"` adds the `reason` next to the tool result. Claude still sees the original output; to replace it, use `updatedToolOutput` |
2016| `reason` | Explanation shown to Claude when `decision` is `"block"` |
2017| `additionalContext` | String added to Claude's context alongside the tool result. See [Add context for Claude](#add-context-for-claude) |
2018| `classifierContext` | Short note about this call's result for the [auto mode](/docs/en/permission-modes#eliminate-prompts-with-auto-mode) classifier rather than for Claude. See [Annotate a result for the auto mode classifier](#annotate-a-result-for-the-auto-mode-classifier). Requires Claude Code v2.1.236 or later |
2019| `updatedToolOutput` | Replaces the tool's output with the provided value before it is sent to Claude. The value must match the tool's output shape |
2020| `updatedMCPToolOutput` | Replaces the output for [MCP tools](#match-mcp-tools) only. Prefer `updatedToolOutput`, which works for all tools |
20212021
20222022The example below replaces the output of a `Bash` call. The replacement value matches the `Bash` tool's output shape:
20232023
from line 2106
21062106}
21072107```
21082108
2109| Field | Description |
2110| :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2111| `error` | String describing what went wrong. The format depends on the tool that failed |
2109| Field | Description |
2110| :- | :- |
2111| `error` | String describing what went wrong. The format depends on the tool that failed |
21122112| `is_interrupt` | Optional boolean. True when the failure reached Claude Code as an abort rather than as an error the tool reported. Cancelling a running tool does not fire this hook; the tool result carries the interruption message instead |
2113| `duration_ms` | Optional. Tool execution time in milliseconds. Excludes time spent in permission prompts and PreToolUse hooks |
2113| `duration_ms` | Optional. Tool execution time in milliseconds. Excludes time spent in permission prompts and PreToolUse hooks |
21142114
21152115The `error` string is generally the same text Claude receives as the failed tool's result. Its format varies by tool and failure. Key your hook on `tool_name`, `is_interrupt`, and the `Exit code N` first line; treat the rest of the string as display text, not a stable format.
21162116
from line 2122
21222122
21232123`PostToolUseFailure` hooks can provide context to Claude after a tool failure. In addition to the [JSON output fields](#json-output) available to all hooks, your hook script can return these event-specific fields:
21242124
2125| Field | Description |
2126| :------------------ | :---------------------------------------------------------------------------------------------------------- |
2125| Field | Description |
2126| :- | :- |
21272127| `additionalContext` | String added to Claude's context alongside the error. See [Add context for Claude](#add-context-for-claude) |
21282128
21292129```json theme={null}
from line 2177
21772177
21782178`PostToolBatch` hooks can inject context for Claude. In addition to the [JSON output fields](#json-output) available to all hooks, your hook script can return these event-specific fields:
21792179
2180| Field | Description |
2181| :------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2180| Field | Description |
2181| :- | :- |
21822182| `additionalContext` | Context string injected once before the next model call. See [Add context for Claude](#add-context-for-claude) for delivery details, what to put in it, and how resumed sessions handle past values |
21832183
21842184```json theme={null}
from line 2219
22192219}
22202220```
22212221
2222| Field | Description |
2223| :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2222| Field | Description |
2223| :- | :- |
22242224| `reason` | The denial reason. For a classifier verdict, in most sessions it names the matched rule in square brackets, such as `[Data Exfiltration]`; see [Review denials](/docs/en/auto-mode-config#review-denials) for the other forms. For a [no-verdict denial](#permissiondenied-decision-control), it starts with `Auto mode could not evaluate this action and is blocking it for safety`. For a denial because the classifier model was unavailable, it is the fixed text `Classifier unavailable` |
22252225
22262226#### PermissionDenied decision control
from line 2246
22462246
22472247You receive these hook events even with desktop notifications turned off: the `preferredNotifChannel` setting, including `notifications_disabled`, changes only how you're alerted, not whether your hook runs.
22482248
2249| Matcher | When it fires |
2250| :--------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2251| `permission_prompt` | Claude needs you to approve a tool use or a sandboxed command's [network request](/docs/en/sandboxing#network-isolation), and the prompt has waited about six seconds |
2252| `idle_prompt` | Claude finished responding about 60 seconds ago and you haven't typed since |
2253| `auth_success` | Authentication completes |
2254| `elicitation_dialog` | An MCP server opens an elicitation form and you haven't typed for about six seconds |
2255| `elicitation_url_dialog` | An MCP server asks you to open a browser URL and you haven't typed for about six seconds |
2256| `elicitation_complete` | An MCP server reports that a [URL-mode elicitation](#elicitation-input) is complete |
2257| `elicitation_response` | An MCP elicitation response is sent back to the server |
2258| `agent_needs_input` | A background session starts waiting on your input while [agent view](/docs/en/agent-view) is open in a terminal, or the current session asks you an [agent team teammate's terminal setup question](/docs/en/agent-teams#choose-a-display-mode) and you haven't typed for about six seconds |
2259| `agent_completed` | A background session finishes or fails. Fires only while [agent view](/docs/en/agent-view) is open in a terminal |
2260| `quota_auto_resume_fired` | Claude Code continues your task after a claude.ai usage limit paused it: at the reset, or sooner when something you do in Claude Code during the wait, such as adding usage credits, upgrading your plan, or switching models, makes usage available again, with the [model-setting exception](/docs/en/interactive-mode#wait-for-a-usage-limit-to-reset) |
2261| `quota_auto_resume_stale` | A claude.ai usage limit reset while your computer slept for more than about 30 minutes. Claude Code waits for you to press `Enter` instead of continuing. After a shorter sleep it continues and fires `quota_auto_resume_fired` instead |
2249| Matcher | When it fires |
2250| :- | :- |
2251| `permission_prompt` | Claude needs you to approve a tool use or a sandboxed command's [network request](/docs/en/sandboxing#network-isolation), and the prompt has waited about six seconds |
2252| `idle_prompt` | Claude finished responding about 60 seconds ago and you haven't typed since |
2253| `auth_success` | Authentication completes |
2254| `elicitation_dialog` | An MCP server opens an elicitation form and you haven't typed for about six seconds |
2255| `elicitation_url_dialog` | An MCP server asks you to open a browser URL and you haven't typed for about six seconds |
2256| `elicitation_complete` | An MCP server reports that a [URL-mode elicitation](#elicitation-input) is complete |
2257| `elicitation_response` | An MCP elicitation response is sent back to the server |
2258| `agent_needs_input` | A background session starts waiting on your input while [agent view](/docs/en/agent-view) is open in a terminal, or the current session asks you an [agent team teammate's terminal setup question](/docs/en/agent-teams#choose-a-display-mode) and you haven't typed for about six seconds |
2259| `agent_completed` | A background session finishes or fails. Fires only while [agent view](/docs/en/agent-view) is open in a terminal |
2260| `quota_auto_resume_fired` | Claude Code continues your task after a claude.ai usage limit paused it: at the reset, or sooner when something you do in Claude Code during the wait, such as adding usage credits, upgrading your plan, or switching models, makes usage available again, with the [model-setting exception](/docs/en/interactive-mode#wait-for-a-usage-limit-to-reset) |
2261| `quota_auto_resume_stale` | A claude.ai usage limit reset while your computer slept for more than about 30 minutes. Claude Code waits for you to press `Enter` instead of continuing. After a shorter sleep it continues and fires `quota_auto_resume_fired` instead |
22622262| `quota_auto_resume_disabled` | Claude Code ends its wait for a claude.ai usage limit without continuing your task: [`autoContinueAtUsageLimit`](/docs/en/settings-reference#autocontinueatusagelimit) turned off or the reset moved more than 24 hours away during a wait Claude Code started on its own, the continued task kept hitting the limit, or the continuation was blocked before it reached the model. Doesn't fire when you press `Esc` or `Ctrl+C`, or pick **Don't continue automatically** |
22632263
22642264The `agent_needs_input` and `agent_completed` types require Claude Code v2.1.198 or later.
from line 2357
23572357
23582358SubagentStart hooks can't block subagent creation, but they can inject context into the subagent. In addition to the [JSON output fields](#json-output) available to all hooks, you can return:
23592359
2360| Field | Description |
2361| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------ |
2360| Field | Description |
2361| :- | :- |
23622362| `additionalContext` | String added to the subagent's context at the start of its conversation, before its first prompt. See [Add context for Claude](#add-context-for-claude) |
23632363
23642364```json theme={null}
from line 2431
24312431}
24322432```
24332433
2434| Field | Description |
2435| :----------------- | :------------------------------------------------------------------------- |
2436| `task_id` | Identifier of the task being created |
2437| `task_subject` | Title of the task |
2438| `task_description` | Detailed description of the task. May be absent |
2439| `teammate_name` | Name of the teammate creating the task. May be absent |
2440| `team_name` | Deprecated. Session-derived team name; will be removed in a future release |
2434| Field | Description |
2435| :- | :- |
2436| `task_id` | Identifier of the task being created |
2437| `task_subject` | Title of the task |
2438| `task_description` | Detailed description of the task. May be absent |
2439| `teammate_name` | Name of the teammate creating the task. May be absent |
2440| `team_name` | Deprecated. Session-derived team name; will be removed in a future release |
24412441
24422442#### TaskCreated decision control
24432443
from line 2486
24862486}
24872487```
24882488
2489| Field | Description |
2490| :----------------- | :------------------------------------------------------------------------- |
2491| `task_id` | Identifier of the task being completed |
2492| `task_subject` | Title of the task |
2493| `task_description` | Detailed description of the task. May be absent |
2494| `teammate_name` | Name of the teammate completing the task. May be absent |
2495| `team_name` | Deprecated. Session-derived team name; will be removed in a future release |
2489| Field | Description |
2490| :- | :- |
2491| `task_id` | Identifier of the task being completed |
2492| `task_subject` | Title of the task |
2493| `task_description` | Detailed description of the task. May be absent |
2494| `teammate_name` | Name of the teammate completing the task. May be absent |
2495| `team_name` | Deprecated. Session-derived team name; will be removed in a future release |
24962496
24972497#### TaskCompleted decision control
24982498
from line 2537
25372537
25382538Each entry in `background_tasks` describes one in-flight task and uses these fields:
25392539
2540| Field | Description |
2541| :------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2542| `id` | Task identifier |
2543| `type` | Friendly task-type label such as `shell`, `subagent`, `monitor`, `workflow`, `teammate`, `cloud session`, or `MCP task`. Each label identifies which Claude Code feature created the task. Falls back to the raw discriminant for unrecognized types |
2544| `status` | Current task status |
2545| `description` | Free-text description, capped at 1000 characters with an in-string `… [+N chars]` marker when clipped |
2546| `command` | Shell command line, capped at 1000 characters. Present only for `shell` tasks |
2547| `agent_type` | Subagent type name. Present only for `subagent` tasks |
2548| `server` | MCP server name. Present only for `monitor` and `MCP task` tasks |
2549| `tool` | MCP tool name. Present only for `monitor` and `MCP task` tasks |
2550| `name` | Workflow name. Present only for `workflow` tasks |
2540| Field | Description |
2541| :- | :- |
2542| `id` | Task identifier |
2543| `type` | Friendly task-type label such as `shell`, `subagent`, `monitor`, `workflow`, `teammate`, `cloud session`, or `MCP task`. Each label identifies which Claude Code feature created the task. Falls back to the raw discriminant for unrecognized types |
2544| `status` | Current task status |
2545| `description` | Free-text description, capped at 1000 characters with an in-string `… [+N chars]` marker when clipped |
2546| `command` | Shell command line, capped at 1000 characters. Present only for `shell` tasks |
2547| `agent_type` | Subagent type name. Present only for `subagent` tasks |
2548| `server` | MCP server name. Present only for `monitor` and `MCP task` tasks |
2549| `tool` | MCP tool name. Present only for `monitor` and `MCP task` tasks |
2550| `name` | Workflow name. Present only for `workflow` tasks |
25512551
25522552Each entry in `session_crons` describes one session-scoped scheduled wakeup, sourced from `CronCreate`, `ScheduleWakeup`, and `/loop`:
25532553
2554| Field | Description |
2555| :---------- | :------------------------------------------------------------------------------------------------------------------- |
2556| `id` | Cron task identifier |
2557| `schedule` | Cron expression, for example `0 9 * * 1-5` |
2554| Field | Description |
2555| :- | :- |
2556| `id` | Cron task identifier |
2557| `schedule` | Cron expression, for example `0 9 * * 1-5` |
25582558| `recurring` | `false` for one-shot wakeups whose schedule encodes a single fire time, `true` for tasks that re-fire on every match |
2559| `prompt` | Prompt submitted when the cron fires, capped at 1000 characters with the same `… [+N chars]` marker |
2559| `prompt` | Prompt submitted when the cron fires, capped at 1000 characters with the same `… [+N chars]` marker |
25602560
25612561This example shows a Stop input with one in-flight shell task and one recurring cron:
25622562
from line 2593
25932593
25942594`Stop` and `SubagentStop` hooks can control whether Claude continues. In addition to the [JSON output fields](#json-output) available to all hooks, your hook script can return these event-specific fields:
25952595
2596| Field | Description |
2597| :------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2598| `decision` | `"block"` prevents Claude from stopping. Omit to allow Claude to stop |
2599| `reason` | Required when `decision` is `"block"`. Tells Claude why it should continue |
2596| Field | Description |
2597| :- | :- |
2598| `decision` | `"block"` prevents Claude from stopping. Omit to allow Claude to stop |
2599| `reason` | Required when `decision` is `"block"`. Tells Claude why it should continue |
26002600| `hookSpecificOutput.additionalContext` | Non-error feedback for Claude. The conversation continues so Claude can act on it, but unlike `decision: "block"` it is shown in the transcript as hook feedback rather than a hook error |
26012601
26022602A hook that blocks by exiting 2 routes the same way as `reason`: Claude receives the stderr message as the explanation for why it should continue.
from line 2627
26272627
26282628In addition to the [common input fields](#common-input-fields), StopFailure hooks receive `error`, optional `error_details`, and optional `last_assistant_message`. The `error` field identifies the error type and is used for matcher filtering.
26292629
2630| Field | Description |
2631| :----------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2632| `error` | Error type: `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, or `unknown` |
2633| `error_details` | Additional details about the error, when available |
2630| Field | Description |
2631| :- | :- |
2632| `error` | Error type: `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, or `unknown` |
2633| `error_details` | Additional details about the error, when available |
26342634| `last_assistant_message` | The rendered error text shown in the conversation. Unlike `Stop` and `SubagentStop`, where this field holds Claude's conversational output, for `StopFailure` it contains the API error string itself, such as `"API Error: Rate limit reached"` |
26352635
26362636```json theme={null}
from line 2669
26692669}
26702670```
26712671
2672| Field | Description |
2673| :-------------- | :------------------------------------------------------------------------- |
2674| `teammate_name` | Name of the teammate that is about to go idle |
2675| `team_name` | Deprecated. Session-derived team name; will be removed in a future release |
2672| Field | Description |
2673| :- | :- |
2674| `teammate_name` | Name of the teammate that is about to go idle |
2675| `team_name` | Deprecated. Session-derived team name; will be removed in a future release |
26762676
26772677#### TeammateIdle decision control
26782678
from line 2702
27022702
27032703The matcher filters on the configuration source:
27042704
2705| Matcher | When it fires |
2706| :----------------- | :----------------------------------------------------------------- |
2707| `user_settings` | `~/.claude/settings.json` changes |
2708| `project_settings` | `.claude/settings.json` changes |
2709| `local_settings` | `.claude/settings.local.json` changes |
2710| `policy_settings` | `managed-settings.json` or a file in `managed-settings.d/` changes |
2711| `skills` | A skill file in `.claude/skills/` changes |
2705| Matcher | When it fires |
2706| :- | :- |
2707| `user_settings` | `~/.claude/settings.json` changes |
2708| `project_settings` | `.claude/settings.json` changes |
2709| `local_settings` | `.claude/settings.local.json` changes |
2710| `policy_settings` | `managed-settings.json` or a file in `managed-settings.d/` changes |
2711| `skills` | A skill file in `.claude/skills/` changes |
27122712
27132713This example logs all configuration changes for security auditing:
27142714
from line 2749
27492749
27502750ConfigChange hooks can block configuration changes from taking effect. Use exit code 2 or a JSON `decision` to prevent the change. When blocked, the new settings are not applied to the running session.
27512751
2752| Field | Description |
2753| :--------- | :--------------------------------------------------------------------------------------- |
2752| Field | Description |
2753| :- | :- |
27542754| `decision` | `"block"` prevents the configuration change from being applied. Omit to allow the change |
2755| `reason` | Accepted but never shown |
2755| `reason` | Accepted but never shown |
27562756
27572757```json theme={null}
27582758{
from line 2792
27922792
27932793In addition to the [JSON output fields](#json-output) available to all hooks, CwdChanged hooks can return `watchPaths` to dynamically set which file paths [FileChanged](#filechanged) watches:
27942794
2795| Field | Description |
2796| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2795| Field | Description |
2796| :- | :- |
27972797| `watchPaths` | Array of absolute paths. Replaces the current dynamic watch list. Paths from your `matcher` configuration are always watched. Returning an empty array clears the dynamic list, which is typical when entering a new directory |
27982798
27992799CwdChanged hooks have no decision control. They can't block the directory change.
from line 2816
28162816
28172817The matcher filters on how the directory was added:
28182818
2819| Matcher | When it fires |
2820| :------------------- | :--------------------------------------------------------------------------- |
2821| `slash_command` | You add a directory with `/add-dir` |
2819| Matcher | When it fires |
2820| :- | :- |
2821| `slash_command` | You add a directory with `/add-dir` |
28222822| `register_repo_root` | An SDK client adds a directory with the `register_repo_root` control request |
28232823
28242824#### DirectoryAdded input
28252825
28262826In addition to the [common input fields](#common-input-fields), DirectoryAdded hooks receive `directory` and `source`.
28272827
2828| Field | Description |
2829| :---------- | :------------------------------------------------------------------------------------------------------------------ |
2830| `directory` | Absolute path of the directory that was added |
2831| `source` | How the directory was added, `"slash_command"` for `/add-dir` or `"register_repo_root"` for the SDK control request |
2828| Field | Description |
2829| :- | :- |
2830| `directory` | Absolute path of the directory that was added |
2831| `source` | How the directory was added, `"slash_command"` for `/add-dir` or `"register_repo_root"` for the SDK control request |
28322832
28332833```json theme={null}
28342834{
from line 2895
28952895
28962896In addition to the [common input fields](#common-input-fields), FileChanged hooks receive `file_path` and `event`.
28972897
2898| Field | Description |
2899| :---------- | :---------------------------------------------------------------------------------------------------------- |
2900| `file_path` | Absolute path to the file that changed |
2901| `event` | What happened: `"change"` for a modified file, `"add"` for a created file, or `"unlink"` for a deleted file |
2898| Field | Description |
2899| :- | :- |
2900| `file_path` | Absolute path to the file that changed |
2901| `event` | What happened: `"change"` for a modified file, `"add"` for a created file, or `"unlink"` for a deleted file |
29022902
29032903```json theme={null}
29042904{
from line 2915
29152915
29162916In addition to the [JSON output fields](#json-output) available to all hooks, FileChanged hooks can return `watchPaths` to dynamically update which file paths are watched:
29172917
2918| Field | Description |
2919| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2918| Field | Description |
2919| :- | :- |
29202920| `watchPaths` | Array of absolute paths. Replaces the current dynamic watch list. Paths from your `matcher` configuration are always watched. Use this when your hook script discovers additional files to watch based on the changed file |
29212921
29222922FileChanged hooks have no decision control. They can't block the file change from occurring.
from line 3039
30393039
30403040The matcher value indicates whether compaction was triggered manually or automatically:
30413041
3042| Matcher | When it fires |
3043| :------- | :----------------------------------------------------------------------------------------------------------------- |
3044| `manual` | `/compact` |
3045| `auto` | Auto-compact when the conversation reaches the [auto-compact window](/docs/en/model-config#set-the-auto-compact-window) |
3042| Matcher | When it fires |
3043| :- | :- |
3044| `manual` | `/compact` |
3045| `auto` | Auto-compact when the conversation reaches the [auto-compact window](/docs/en/model-config#set-the-auto-compact-window) |
30463046
30473047Exit with code 2 to block compaction. For a manual `/compact`, the stderr message is shown to the user. You can also block by returning JSON with `"decision": "block"`.
30483048
from line 3071
30713071
30723072The same matcher values apply as for `PreCompact`:
30733073
3074| Matcher | When it fires |
3075| :------- | :----------------------------------------------------------------------------------------------------------------------- |
3076| `manual` | After `/compact` |
3077| `auto` | After auto-compact when the conversation reaches the [auto-compact window](/docs/en/model-config#set-the-auto-compact-window) |
3074| Matcher | When it fires |
3075| :- | :- |
3076| `manual` | After `/compact` |
3077| `auto` | After auto-compact when the conversation reaches the [auto-compact window](/docs/en/model-config#set-the-auto-compact-window) |
30783078
30793079#### PostCompact input
30803080
from line 3183
31833183
31843184In addition to the [common input fields](#common-input-fields), PreModelSwitch hooks receive the fields in this table. The last five describe what re-sending the conversation to the new model costs, so a hook can show that figure before the switch happens.
31853185
3186| Field | Type | Description |
3187| :-------------------------- | :--------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3188| `from_model` | string | Model ID the switch changes from |
3189| `to_model` | string | Model ID the switch changes to. The matcher compares against this model's canonical name |
3190| `requested_model` | string or `null` | The model the request named: an alias such as `opus`, a full model ID, or `null` when the request was for the default model |
3191| `source` | string | Where the request came from: `"command"` for `/model <name>`, the Model setting in `/config`, or turning on fast mode; `"picker"` for a model picker; `"sdk"` for a `set_model` request, or a model change in an `apply_flag_settings` request, from an Agent SDK host or Remote Control |
3192| `context_tokens` | number | Tokens the next request re-sends as its prompt: the input, cache read, cache creation, and output tokens of the last response in the main conversation, combined. `0` before the first response |
3193| `prompt_cache_warm` | boolean | Whether the current model's prompt cache is likely still warm, meaning the switch forfeits it |
3194| `cache_ttl` | string | [Prompt cache lifetime](/docs/en/prompt-caching#cache-lifetime) Claude Code requests for this session: `"5m"` or `"1h"` |
3195| `estimated_cache_write_usd` | number | Estimated cost in US dollars of writing `context_tokens` to the prompt cache on `to_model` at the `cache_ttl` rate, excluding the next response. The server may not need to re-cache the whole context, so treat it as an estimate |
3196| `pricing` | string | How Claude Code priced `estimated_cache_write_usd`: `"configured"` at your organization's own rates when it has configured them, `"catalog"` at list price, or `"default"` when `to_model` has no known price and Claude Code assumed a default rate |
3186| Field | Type | Description |
3187| :- | :- | :- |
3188| `from_model` | string | Model ID the switch changes from |
3189| `to_model` | string | Model ID the switch changes to. The matcher compares against this model's canonical name |
3190| `requested_model` | string or `null` | The model the request named: an alias such as `opus`, a full model ID, or `null` when the request was for the default model |
3191| `source` | string | Where the request came from: `"command"` for `/model <name>`, the Model setting in `/config`, or turning on fast mode; `"picker"` for a model picker; `"sdk"` for a `set_model` request, or a model change in an `apply_flag_settings` request, from an Agent SDK host or Remote Control |
3192| `context_tokens` | number | Tokens the next request re-sends as its prompt: the input, cache read, cache creation, and output tokens of the last response in the main conversation, combined. `0` before the first response |
3193| `prompt_cache_warm` | boolean | Whether the current model's prompt cache is likely still warm, meaning the switch forfeits it |
3194| `cache_ttl` | string | [Prompt cache lifetime](/docs/en/prompt-caching#cache-lifetime) Claude Code requests for this session: `"5m"` or `"1h"` |
3195| `estimated_cache_write_usd` | number | Estimated cost in US dollars of writing `context_tokens` to the prompt cache on `to_model` at the `cache_ttl` rate, excluding the next response. The server may not need to re-cache the whole context, so treat it as an estimate |
3196| `pricing` | string | How Claude Code priced `estimated_cache_write_usd`: `"configured"` at your organization's own rates when it has configured them, `"catalog"` at list price, or `"default"` when `to_model` has no known price and Claude Code assumed a default rate |
31973197
31983198This example shows the input for `/model opus` in a session running Sonnet 5:
31993199
from line 3221
32213221
32223222For finer control, return `permissionDecision` and `permissionDecisionReason` in a `hookSpecificOutput` object, as on [PreToolUse](#pretooluse-decision-control). `PreModelSwitch` accepts `"allow"`, `"deny"`, and `"ask"`. It doesn't accept `"defer"`, `updatedInput`, or `additionalContext`. The table below describes both fields:
32233223
3224| Field | Description |
3225| :------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3226| `permissionDecision` | `"allow"` proceeds and skips the [confirmation Claude Code shows while the prompt cache is warm](/docs/en/prompt-caching#switching-models). `"deny"` cancels the switch. `"ask"` prompts the user to confirm it |
3227| `permissionDecisionReason` | For `"deny"`, shown to the user as the reason the switch was blocked, or returned as the error for a `set_model` request. For `"ask"`, shown in the confirmation prompt. Ignored for `"allow"` |
3224| Field | Description |
3225| :- | :- |
3226| `permissionDecision` | `"allow"` proceeds and skips the [confirmation Claude Code shows while the prompt cache is warm](/docs/en/prompt-caching#switching-models). `"deny"` cancels the switch. `"ask"` prompts the user to confirm it |
3227| `permissionDecisionReason` | For `"deny"`, shown to the user as the reason the switch was blocked, or returned as the error for a `set_model` request. For `"ask"`, shown in the confirmation prompt. Ignored for `"allow"` |
32283228
32293229Only `/model` in an interactive session can show the `"ask"` prompt. On every other surface, including non-interactive mode with the `-p` flag, `/config`, and `set_model` requests, Claude Code treats `"ask"` as a refusal.
32303230
from line 3295
32953295
32963296Claude Code takes your hook's [plain-text stdout](#exit-code-0) on exit 0, or `additionalContext` from JSON output, and delivers it to Claude with the next request after the switch. In addition to the [JSON output fields](#json-output) available to all hooks, you can return:
32973297
3298| Field | Description |
3299| :------------------ | :------------------------------------------------------------------------------------------------------------ |
3298| Field | Description |
3299| :- | :- |
33003300| `additionalContext` | String added to Claude's context with the next request. See [Add context for Claude](#add-context-for-claude) |
33013301
33023302If the hook hasn't finished within five seconds after you send the next prompt, Claude Code sends that request without the output and attaches it to the following request instead. If the model changes several times before the next request, Claude Code delivers only the output for the last switch's target model.
from line 3308
33083308
33093309The `reason` field in the hook input indicates why the session ended:
33103310
3311| Reason | Description |
3312| :---------------------------- | :---------------------------------------------------------------------------------------- |
3313| `clear` | Session cleared with `/clear` command |
3314| `resume` | Session switched via interactive `/resume` |
3315| `logout` | User logged out |
3316| `prompt_input_exit` | User exited while prompt input was visible |
3317| `other` | Other exit reasons |
3311| Reason | Description |
3312| :- | :- |
3313| `clear` | Session cleared with `/clear` command |
3314| `resume` | Session switched via interactive `/resume` |
3315| `logout` | User logged out |
3316| `prompt_input_exit` | User exited while prompt input was visible |
3317| `other` | Other exit reasons |
33183318| `bypass_permissions_disabled` | Removed in v2.1.234; Claude Code doesn't send it. Drop it from your `SessionEnd` matchers |
33193319
33203320#### SessionEnd input
from line 3407
34073407}
34083408```
34093409
3410| Field | Values | Description |
3411| :-------- | :---------------------------- | :--------------------------------------------------------------- |
3412| `action` | `accept`, `decline`, `cancel` | Whether to accept, decline, or cancel the request |
3413| `content` | object | Form field values to submit. Only used when `action` is `accept` |
3410| Field | Values | Description |
3411| :- | :- | :- |
3412| `action` | `accept`, `decline`, `cancel` | Whether to accept, decline, or cancel the request |
3413| `content` | object | Form field values to submit. Only used when `action` is `accept` |
34143414
34153415Exit code 2 denies the elicitation. Claude Code doesn't show your stderr message anywhere.
34163416
from line 3454
34543454}
34553455```
34563456
3457| Field | Values | Description |
3458| :-------- | :---------------------------- | :--------------------------------------------------------------------- |
3459| `action` | `accept`, `decline`, `cancel` | Overrides the user's action |
3460| `content` | object | Overrides form field values. Only meaningful when `action` is `accept` |
3457| Field | Values | Description |
3458| :- | :- | :- |
3459| `action` | `accept`, `decline`, `cancel` | Overrides the user's action |
3460| `content` | object | Overrides form field values. Only meaningful when `action` is `accept` |
34613461
34623462Exit code 2 blocks the response, changing the effective action to `decline`. Claude Code doesn't show your stderr message anywhere.
34633463
from line 3538
35383538}
35393539```
35403540
3541| Field | Required | Description |
3542| :---------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3543| `type` | yes | Must be `"prompt"` |
3544| `prompt` | yes | The prompt text to send to the LLM. Use `$ARGUMENTS` as a placeholder for the hook input JSON. If `$ARGUMENTS` is not present, input JSON is appended to the prompt |
3545| `model` | no | Model to use for evaluation. Defaults to a fast model |
3546| `timeout` | no | Timeout in seconds. Default: 30 |
3547| `continueOnBlock` | no | On the events it applies to, `true` feeds an `ok: false` reason back to Claude and continues instead of ending the turn. Default: `false`. See [Response schema](#response-schema) for per-event behavior |
3541| Field | Required | Description |
3542| :- | :- | :- |
3543| `type` | yes | Must be `"prompt"` |
3544| `prompt` | yes | The prompt text to send to the LLM. Use `$ARGUMENTS` as a placeholder for the hook input JSON. If `$ARGUMENTS` is not present, input JSON is appended to the prompt |
3545| `model` | no | Model to use for evaluation. Defaults to a fast model |
3546| `timeout` | no | Timeout in seconds. Default: 30 |
3547| `continueOnBlock` | no | On the events it applies to, `true` feeds an `ok: false` reason back to Claude and continues instead of ending the turn. Default: `false`. See [Response schema](#response-schema) for per-event behavior |
35483548
35493549### Response schema
35503550
from line 3558
35583558}
35593559```
35603560
3561| Field | Description |
3562| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3563| `ok` | `true` to allow. For `false`, see the per-event behavior below |
3564| `reason` | Required when `ok` is `false` |
3561| Field | Description |
3562| :- | :- |
3563| `ok` | `true` to allow. For `false`, see the per-event behavior below |
3564| `reason` | Required when `ok` is `false` |
35653565| `impossible` | Optional. The model returns it with `ok: false` when it judges the condition can never be satisfied. On `Stop` and `SubagentStop`, Claude Code then lets the turn end instead of feeding the reason back. Agent hooks and other events ignore it |
35663566
35673567What happens on `ok: false` depends on the event:
35683568
hooks-guide Changed · +84 / -84 lines
from line 177
177177
178178The empty `matcher` fires on all notification types. To fire only on specific events, set it to one of these values:
179179
180| Matcher | Fires when |
181| :--------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
182| `permission_prompt` | Claude needs you to approve a tool use or a sandboxed command's [network request](/docs/en/sandboxing#network-isolation), and the prompt has waited about six seconds |
183| `idle_prompt` | Claude finished responding about 60 seconds ago and you haven't typed since |
184| `auth_success` | Authentication completes |
185| `elicitation_dialog` | An MCP server opens an elicitation form and you haven't typed for about six seconds |
186| `elicitation_url_dialog` | An MCP server asks you to open a browser URL and you haven't typed for about six seconds |
187| `elicitation_complete` | An MCP server reports that a [URL-mode elicitation](/docs/en/hooks#elicitation-input) is complete |
188| `elicitation_response` | An MCP elicitation response is sent back to the server |
189| `agent_needs_input` | A background session starts waiting on your input while [agent view](/docs/en/agent-view) is open, or the current session asks you an [agent team teammate's terminal setup question](/docs/en/agent-teams#choose-a-display-mode) and you haven't typed for about six seconds |
190| `agent_completed` | A background session finishes or fails. Fires only while [agent view](/docs/en/agent-view) is open |
191| `quota_auto_resume_fired` | Claude Code continues your task after a claude.ai usage limit paused it: at the reset, or sooner when something you do in Claude Code during the wait, such as adding usage credits, upgrading your plan, or switching models, makes usage available again, with the [model-setting exception](/docs/en/interactive-mode#wait-for-a-usage-limit-to-reset) |
192| `quota_auto_resume_stale` | A claude.ai usage limit reset while your computer slept for more than about 30 minutes. Claude Code waits for you to press `Enter` instead of continuing. After a shorter sleep it continues and fires `quota_auto_resume_fired` instead |
180| Matcher | Fires when |
181| :- | :- |
182| `permission_prompt` | Claude needs you to approve a tool use or a sandboxed command's [network request](/docs/en/sandboxing#network-isolation), and the prompt has waited about six seconds |
183| `idle_prompt` | Claude finished responding about 60 seconds ago and you haven't typed since |
184| `auth_success` | Authentication completes |
185| `elicitation_dialog` | An MCP server opens an elicitation form and you haven't typed for about six seconds |
186| `elicitation_url_dialog` | An MCP server asks you to open a browser URL and you haven't typed for about six seconds |
187| `elicitation_complete` | An MCP server reports that a [URL-mode elicitation](/docs/en/hooks#elicitation-input) is complete |
188| `elicitation_response` | An MCP elicitation response is sent back to the server |
189| `agent_needs_input` | A background session starts waiting on your input while [agent view](/docs/en/agent-view) is open, or the current session asks you an [agent team teammate's terminal setup question](/docs/en/agent-teams#choose-a-display-mode) and you haven't typed for about six seconds |
190| `agent_completed` | A background session finishes or fails. Fires only while [agent view](/docs/en/agent-view) is open |
191| `quota_auto_resume_fired` | Claude Code continues your task after a claude.ai usage limit paused it: at the reset, or sooner when something you do in Claude Code during the wait, such as adding usage credits, upgrading your plan, or switching models, makes usage available again, with the [model-setting exception](/docs/en/interactive-mode#wait-for-a-usage-limit-to-reset) |
192| `quota_auto_resume_stale` | A claude.ai usage limit reset while your computer slept for more than about 30 minutes. Claude Code waits for you to press `Enter` instead of continuing. After a shorter sleep it continues and fires `quota_auto_resume_fired` instead |
193193| `quota_auto_resume_disabled` | Claude Code ends its wait for a claude.ai usage limit without continuing your task: [`autoContinueAtUsageLimit`](/docs/en/settings-reference#autocontinueatusagelimit) turned off or the reset moved more than 24 hours away during a wait Claude Code started on its own, the continued task kept hitting the limit, or the continuation was blocked before it reached the model. Doesn't fire when you press `Esc` or `Ctrl+C`, or pick **Don't continue automatically** |
194194
195195Claude Code times `permission_prompt` differently in a terminal and in Claude Desktop, the VS Code extension, and other hosts that answer permission requests through the Agent SDK. See [when each notification type fires](/docs/en/hooks#notification) for both timings.
from line 475
475475
476476Claude Code fires hook events at specific points in its lifecycle. When an event fires, Claude Code runs all matching hooks in parallel; see [Hook handler fields](/docs/en/hooks#hook-handler-fields) for how duplicate handlers are treated. The table below shows each event and when it triggers:
477477
478| Event | When it fires |
479| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
480| `SessionStart` | When a session begins or resumes |
481| `Setup` | When you start Claude Code with `--init-only`, or with `--init` or `--maintenance` in `-p` mode. For one-time preparation in CI or scripts |
482| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |
483| `UserPromptExpansion` | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |
484| `PreToolUse` | Before a tool call executes. Can block it |
485| `PermissionRequest` | When a tool call needs a permission decision |
486| `PermissionDenied` | When auto mode denies a tool call, including denials without a classifier verdict. Use JSON `hookSpecificOutput.retry: true` to tell the model it may retry the denied tool call. Claude Code ignores `retry` when the classifier produced no verdict |
487| `PostToolUse` | After a tool call succeeds |
488| `PostToolUseFailure` | After a tool call fails |
489| `PostToolBatch` | After a full batch of parallel tool calls resolves, before the next model call |
490| `Notification` | When Claude Code sends a notification |
491| `MessageDisplay` | While assistant message text is displayed |
492| `SubagentStart` | When a subagent is spawned |
493| `SubagentStop` | When a subagent finishes |
494| `TaskCreated` | When a task is being created via `TaskCreate` |
495| `TaskCompleted` | When a task is being marked as completed |
496| `Stop` | When Claude finishes responding |
497| `StopFailure` | When the turn ends due to an API error |
498| `TeammateIdle` | When an [agent team](/docs/en/agent-teams) teammate is about to go idle |
499| `InstructionsLoaded` | When a CLAUDE.md or `.claude/rules/*.md` file is loaded into context. Fires at session start and when files are lazily loaded during a session |
500| `ConfigChange` | When a configuration file changes during a session |
501| `CwdChanged` | When the working directory changes, for example when Claude executes a `cd` command. Useful for reactive environment management with tools like direnv |
502| `DirectoryAdded` | When a working directory is added mid-session via `/add-dir` or the SDK `register_repo_root` control request |
503| `FileChanged` | When a watched file changes on disk. The `matcher` field specifies which filenames to watch |
504| `WorktreeCreate` | When a worktree is being created via `--worktree`, `isolation: "worktree"`, or for a background session. Replaces default git behavior |
505| `WorktreeRemove` | When a worktree is being removed at session exit, when a subagent finishes, or when you delete a background session |
506| `PreCompact` | Before context compaction |
507| `PostCompact` | After context compaction completes |
508| `PreModelSwitch` | Before Claude Code applies a model switch that you or a client requested. Can block the switch |
509| `PostModelSwitch` | After the session's model changes, including changes Claude Code makes on its own, such as restoring the model when you resume a session |
510| `Elicitation` | When an MCP server requests user input during a tool call |
511| `ElicitationResult` | After a user responds to an MCP elicitation, before the response is sent back to the server |
512| `SessionEnd` | When a session terminates |
478| Event | When it fires |
479| :- | :- |
480| `SessionStart` | When a session begins or resumes |
481| `Setup` | When you start Claude Code with `--init-only`, or with `--init` or `--maintenance` in `-p` mode. For one-time preparation in CI or scripts |
482| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |
483| `UserPromptExpansion` | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |
484| `PreToolUse` | Before a tool call executes. Can block it |
485| `PermissionRequest` | When a tool call needs a permission decision |
486| `PermissionDenied` | When auto mode denies a tool call, including denials without a classifier verdict. Use JSON `hookSpecificOutput.retry: true` to tell the model it may retry the denied tool call. Claude Code ignores `retry` when the classifier produced no verdict |
487| `PostToolUse` | After a tool call succeeds |
488| `PostToolUseFailure` | After a tool call fails |
489| `PostToolBatch` | After a full batch of parallel tool calls resolves, before the next model call |
490| `Notification` | When Claude Code sends a notification |
491| `MessageDisplay` | While assistant message text is displayed |
492| `SubagentStart` | When a subagent is spawned |
493| `SubagentStop` | When a subagent finishes |
494| `TaskCreated` | When a task is being created via `TaskCreate` |
495| `TaskCompleted` | When a task is being marked as completed |
496| `Stop` | When Claude finishes responding |
497| `StopFailure` | When the turn ends due to an API error |
498| `TeammateIdle` | When an [agent team](/docs/en/agent-teams) teammate is about to go idle |
499| `InstructionsLoaded` | When a CLAUDE.md or `.claude/rules/*.md` file is loaded into context. Fires at session start and when files are lazily loaded during a session |
500| `ConfigChange` | When a configuration file changes during a session |
501| `CwdChanged` | When the working directory changes, for example when Claude executes a `cd` command. Useful for reactive environment management with tools like direnv |
502| `DirectoryAdded` | When a working directory is added mid-session via `/add-dir` or the SDK `register_repo_root` control request |
503| `FileChanged` | When a watched file changes on disk. The `matcher` field specifies which filenames to watch |
504| `WorktreeCreate` | When a worktree is being created via `--worktree`, `isolation: "worktree"`, or for a background session. Replaces default git behavior |
505| `WorktreeRemove` | When a worktree is being removed at session exit, when a subagent finishes, or when you delete a background session |
506| `PreCompact` | Before context compaction |
507| `PostCompact` | After context compaction completes |
508| `PreModelSwitch` | Before Claude Code applies a model switch that you or a client requested. Can block the switch |
509| `PostModelSwitch` | After the session's model changes, including changes Claude Code makes on its own, such as restoring the model when you resume a session |
510| `Elicitation` | When an MCP server requests user input during a tool call |
511| `ElicitationResult` | After a user responds to an MCP elicitation, before the response is sent back to the server |
512| `SessionEnd` | When a session terminates |
513513
514514Each hook has a `type` that determines how it runs. Most hooks use `"type": "command"`, which runs a shell command. Four other types are available:
515515
from line 682
682682
683683Each event type matches on a specific field:
684684
685| Event | What the matcher filters | Example matcher values |
686| :-------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
687| `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied` | tool name | `Bash`, `Edit\|Write`, `mcp__.*` |
688| `SessionStart` | how the session started | `startup`, `resume`, `clear`, `compact`, `fork` |
689| `Setup` | which CLI flag triggered setup | `init`, `maintenance` |
690| `SessionEnd` | why the session ended | `clear`, `resume`, `logout`, `prompt_input_exit`, `other` |
691| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`, `elicitation_url_dialog`, `elicitation_complete`, `elicitation_response`, `agent_needs_input`, `agent_completed`, `quota_auto_resume_fired`, `quota_auto_resume_stale`, `quota_auto_resume_disabled` |
692| `SubagentStart` | agent type | `general-purpose`, `Explore`, `Plan`, or custom agent names |
693| `PreCompact`, `PostCompact` | what triggered compaction | `manual`, `auto` |
694| `PreModelSwitch`, `PostModelSwitch` | canonical name of the model the session switches to, as described under [PreModelSwitch](/docs/en/hooks#premodelswitch) | `claude-opus-5`, `claude-opus-4-6\|claude-opus-5`, `.*opus.*` |
695| `SubagentStop` | agent type | same values as `SubagentStart` |
696| `ConfigChange` | configuration source | `user_settings`, `project_settings`, `local_settings`, `policy_settings`, `skills` |
697| `DirectoryAdded` | how the directory was added | `slash_command`, `register_repo_root` |
698| `StopFailure` | error type | `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, `unknown` |
699| `InstructionsLoaded` | load reason | `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact` |
700| `Elicitation` | MCP server name | your configured MCP server names |
701| `ElicitationResult` | MCP server name | same values as `Elicitation` |
702| `FileChanged` | literal filenames to watch (see [FileChanged](/docs/en/hooks#filechanged)) | `.envrc\|.env` |
703| `UserPromptExpansion` | command name | your skill or command names |
704| `UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, `CwdChanged`, `MessageDisplay` | no matcher support | always fires on every occurrence |
685| Event | What the matcher filters | Example matcher values |
686| :- | :- | :- |
687| `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied` | tool name | `Bash`, `Edit\|Write`, `mcp__.*` |
688| `SessionStart` | how the session started | `startup`, `resume`, `clear`, `compact`, `fork` |
689| `Setup` | which CLI flag triggered setup | `init`, `maintenance` |
690| `SessionEnd` | why the session ended | `clear`, `resume`, `logout`, `prompt_input_exit`, `other` |
691| `Notification` | notification type | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`, `elicitation_url_dialog`, `elicitation_complete`, `elicitation_response`, `agent_needs_input`, `agent_completed`, `quota_auto_resume_fired`, `quota_auto_resume_stale`, `quota_auto_resume_disabled` |
692| `SubagentStart` | agent type | `general-purpose`, `Explore`, `Plan`, or custom agent names |
693| `PreCompact`, `PostCompact` | what triggered compaction | `manual`, `auto` |
694| `PreModelSwitch`, `PostModelSwitch` | canonical name of the model the session switches to, as described under [PreModelSwitch](/docs/en/hooks#premodelswitch) | `claude-opus-5`, `claude-opus-4-6\|claude-opus-5`, `.*opus.*` |
695| `SubagentStop` | agent type | same values as `SubagentStart` |
696| `ConfigChange` | configuration source | `user_settings`, `project_settings`, `local_settings`, `policy_settings`, `skills` |
697| `DirectoryAdded` | how the directory was added | `slash_command`, `register_repo_root` |
698| `StopFailure` | error type | `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, `unknown` |
699| `InstructionsLoaded` | load reason | `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact` |
700| `Elicitation` | MCP server name | your configured MCP server names |
701| `ElicitationResult` | MCP server name | same values as `Elicitation` |
702| `FileChanged` | literal filenames to watch (see [FileChanged](/docs/en/hooks#filechanged)) | `.envrc\|.env` |
703| `UserPromptExpansion` | command name | your skill or command names |
704| `UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, `CwdChanged`, `MessageDisplay` | no matcher support | always fires on every occurrence |
705705
706706The tabs below show a few more matchers on different event types.
707707
from line 802
802802
803803Whether your hook command runs depends on the shape of your `if` pattern and the Bash command Claude is invoking:
804804
805| `if` pattern | Bash command | Hook runs? | Why |
806| :----------------- | :--------------------- | :--------- | :-------------------------------------------------------------------------------------------------- |
807| `Bash(git *)` | `git push` | yes | command name matches |
808| `Bash(git *)` | `npm test && git push` | yes | each subcommand is checked; `git push` matches |
809| `Bash(git *)` | `echo $(git log)` | yes | commands inside `$()` and backticks are checked; `git log` matches |
810| `Bash(git *)` | `echo $(date)` | no | no subcommand matches `git *` |
811| `Bash(git push *)` | `echo $(date)` | yes | patterns that specify more than the command name run the hook anyway on `$()`, backticks, or `$VAR` |
805| `if` pattern | Bash command | Hook runs? | Why |
806| :- | :- | :- | :- |
807| `Bash(git *)` | `git push` | yes | command name matches |
808| `Bash(git *)` | `npm test && git push` | yes | each subcommand is checked; `git push` matches |
809| `Bash(git *)` | `echo $(git log)` | yes | commands inside `$()` and backticks are checked; `git log` matches |
810| `Bash(git *)` | `echo $(date)` | no | no subcommand matches `git *` |
811| `Bash(git push *)` | `echo $(date)` | yes | patterns that specify more than the command name run the hook anyway on `$()`, backticks, or `$VAR` |
812812
813813When Claude Code can't determine which commands the Bash input runs, it runs your hook regardless of the pattern. The [Bash matching table](/docs/en/hooks#bash-if-matching) covers the command shapes Claude Code can and can't narrow by subcommand. Because the filter is best-effort, use the [permission system](/docs/en/permissions) rather than a hook to enforce a hard allow or deny.
814814
from line 820
820820
821821Where you add a hook determines its scope:
822822
823| Location | Scope | Shareable |
824| :------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------- |
825| `~/.claude/settings.json` | All your projects | No, local to your machine |
826| `.claude/settings.json` | Single project | Yes, can be committed to the repo |
827| `.claude/settings.local.json` | Single project | No, gitignored when Claude Code saves a setting to it |
828| Managed policy settings | Organization-wide | Yes, admin-controlled |
829| [Plugin](/docs/en/plugins/overview) `hooks/hooks.json` | When plugin is enabled | Yes, bundled with the plugin |
830| [Skill](/docs/en/skills) frontmatter | The rest of the session once the skill is invoked. See [Hooks in skills and agents](/docs/en/hooks#hooks-in-skills-and-agents) | Yes, defined in the skill file |
831| [Subagent](/docs/en/sub-agents) frontmatter | While that subagent is running | Yes, defined in the subagent file |
823| Location | Scope | Shareable |
824| :- | :- | :- |
825| `~/.claude/settings.json` | All your projects | No, local to your machine |
826| `.claude/settings.json` | Single project | Yes, can be committed to the repo |
827| `.claude/settings.local.json` | Single project | No, gitignored when Claude Code saves a setting to it |
828| Managed policy settings | Organization-wide | Yes, admin-controlled |
829| [Plugin](/docs/en/plugins/overview) `hooks/hooks.json` | When plugin is enabled | Yes, bundled with the plugin |
830| [Skill](/docs/en/skills) frontmatter | The rest of the session once the skill is invoked. See [Hooks in skills and agents](/docs/en/hooks#hooks-in-skills-and-agents) | Yes, defined in the skill file |
831| [Subagent](/docs/en/sub-agents) frontmatter | While that subagent is running | Yes, defined in the subagent file |
832832
833833Run [`/hooks`](/docs/en/hooks#the-%2Fhooks-menu) in Claude Code to browse all configured hooks grouped by event.
834834
how-claude-code-works Changed · +11 / -11 lines
from line 34
3434
3535The built-in tools generally fall into five categories, each representing a different kind of agency.
3636
37| Category | What Claude can do |
38| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
39| **File operations** | Read files, edit code, create new files, rename and reorganize |
40| **Search** | Find files by pattern, search content with regex, explore codebases |
41| **Execution** | Run shell commands, start servers, run tests, use git |
42| **Web** | Search the web, fetch documentation, look up error messages |
37| Category | What Claude can do |
38| - | - |
39| **File operations** | Read files, edit code, create new files, rename and reorganize |
40| **Search** | Find files by pattern, search content with regex, explore codebases |
41| **Execution** | Run shell commands, start servers, run tests, use git |
42| **Web** | Search the web, fetch documentation, look up error messages |
4343| **Code intelligence** | See type errors and warnings after edits, jump to definitions, find references (requires [code intelligence plugins](/docs/en/plugins/code-intelligence)) |
4444
4545These are the primary capabilities. Claude also has tools for spawning subagents, asking you questions, and other orchestration tasks. See [Tools available to Claude](/docs/en/tools-reference) for the complete list.
from line 78
7878
7979Claude Code runs in three environments, each with different tradeoffs for where your code executes.
8080
81| Environment | Where code runs | Use case |
82| ------------------ | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
83| **Local** | Your machine | Default. Full access to your files, tools, and environment |
84| **Cloud** | Anthropic-managed VMs, or [self-hosted environments](/docs/en/self-hosted-environments) your organization operates | Offload tasks, work on repos you don't have locally |
85| **Remote Control** | Your machine, controlled from a browser | Use the web UI while execution and your files stay local |
81| Environment | Where code runs | Use case |
82| - | - | - |
83| **Local** | Your machine | Default. Full access to your files, tools, and environment |
84| **Cloud** | Anthropic-managed VMs, or [self-hosted environments](/docs/en/self-hosted-environments) your organization operates | Offload tasks, work on repos you don't have locally |
85| **Remote Control** | Your machine, controlled from a browser | Use the web UI while execution and your files stay local |
8686
8787### Interfaces
8888
interactive-mode Changed · +150 / -150 lines
from line 12
1212
1313### General controls
1414
15| Shortcut | Description | Context |
16| :------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
17| `Ctrl+C` | Interrupt, or clear input | Interrupts a running operation. If nothing is running, the first press clears the prompt input and a second press exits Claude Code |
18| `Ctrl+X Ctrl+K` | Stop all running [background subagents](/docs/en/sub-agents#run-subagents-in-foreground-or-background) in this session, and turn off [artifact auto-replies](/docs/en/artifacts#let-claude-reply-to-comments-on-its-own) for the rest of it. Press twice within 3 seconds to confirm | Subagent control |
19| `Ctrl+D` | Exit Claude Code session | The first press shows a confirmation hint and a second press within 800ms exits. When the prompt has text, `Ctrl+D` deletes the character after the cursor instead |
20| `Ctrl+G` or `Ctrl+X Ctrl+E` | Open in default text editor | Edit your prompt or custom response in your default text editor. `Ctrl+X Ctrl+E` is the readline-native binding. Turn on **Show last response in external editor** in `/config` to prepend Claude's previous reply as `#`-commented context above your prompt; Claude Code strips the comment block when you save |
21| `Ctrl+L` | Redraw the screen | Forces a full terminal redraw, keeping input and conversation history. Use this to recover if the display becomes garbled or partially blank. See [Clear the conversation](/docs/en/fullscreen#clear-the-conversation) for fullscreen rendering |
22| `Ctrl+O` | Toggle transcript viewer | Shows detailed tool usage and execution, with a timestamp and the model used on each assistant message. Also expands lines that collapse by default, such as MCP calls, shown as a single `Called slack 3 times` line, and [messages from your other sessions](/docs/en/cross-session-messaging#what-a-message-looks-like), shown as a one-line `Message from @<sender>` preview |
23| `Ctrl+R` | Reverse search command history | Search through previous commands interactively |
24| `Ctrl+V` or `Cmd+V` (iTerm2) or `Alt+V` (Windows and WSL) | Paste image from clipboard | Inserts an `[Image #N]` chip at the cursor so you can reference it positionally in your prompt. On WSL, both `Ctrl+V` and `Alt+V` are bound; use `Alt+V` if your terminal intercepts `Ctrl+V` |
25| `Ctrl+B` | Background running tasks | Backgrounds Bash commands and agents. Tmux users press twice |
26| `Ctrl+T` | Toggle Claude's task checklist | Show or hide [Claude's to-do checklist](#task-list) in the status area. This is not the background-task view; use [`/tasks`](/docs/en/commands) to see running shells and subagents |
27| `Ctrl+S` | Stash or restore prompt | With text in the input, stashes it and clears the prompt. Pressed again on an empty prompt, restores the stashed text, cursor position, pasted content, and input mode, so a stashed `!` [shell command](#shell-mode-with-prefix) comes back in shell mode |
28| `Ctrl+Z` | Suspend Claude Code | Unix only. Suspends the process to your shell; run `fg` to resume |
29| `Left/Right arrows` | Cycle through dialog tabs | Navigate between tabs in permission dialogs and menus. In a tabbed dialog, the keys switch tabs while the tab row has focus. See [Tabs actions](/docs/en/keybindings#tabs-actions) for how focus moves |
30| `Tab` | Accept an autocomplete suggestion, or add a comment to a permission answer | While autocomplete suggestions are showing in the prompt input, accepts the selected suggestion. On most permission prompts, with **Yes** or **No** focused, opens a comment field on that option, and pressing it again closes the field. See [add a comment when you answer a permission prompt](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt) |
31| `Up/Down arrows` or `Ctrl+P`/`Ctrl+N` | Move cursor or navigate command history | When the input spans more than one visual row, whether wrapped or multiline, first moves the cursor within the prompt. Once the cursor is on the first or last visual row, pressing again navigates command history. While you have messages queued, `Up` from the first row instead [takes them back](#take-back-what-you-queued) |
32| `Esc` | Interrupt Claude, or close a dialog | Stop the current response or tool call mid-turn so you can redirect. Claude keeps the work done so far. If you have [messages queued](#queue-messages-while-claude-works), Claude Code sends them next. When a dialog is open, `Esc` closes the dialog. While a footer item is selected, such as a row in the [subagent panel](/docs/en/sub-agents#run-subagents-in-foreground-or-background) below the prompt, `Esc` [deselects it](/docs/en/keybindings#footer-actions) instead of interrupting. On a permission prompt, `Esc` declines the action, the same as [**No** without a comment](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt) |
33| `Esc` + `Esc` | Clear input draft, or rewind | When the prompt input contains text, double `Esc` clears it and saves the draft to history so `Up` recalls it. When the input is empty, double `Esc` opens the [rewind menu](/docs/en/checkpointing) to restore or summarize code and conversation from a previous point |
34| `Ctrl+Enter` or `Ctrl+X Ctrl+S` | Send queued messages now | Sends your [queued messages](#queue-messages-while-claude-works), and your draft with them, right away. [When Claude Code sends what you queued](#when-claude-code-sends-what-you-queued) covers what happens to the turn Claude is working on. In [shell mode](#shell-mode-with-prefix), the key only queues your command. In terminals that don't report extended keys, `Ctrl+Enter` arrives as plain `Enter`; `Ctrl+X Ctrl+S` works in any terminal. Requires Claude Code v2.1.275 or later |
35| `Shift+Tab`, or `Alt+M` on Windows when the Node or Bun runtime doesn't enable VT input mode | Cycle permission modes | Cycle through `default` (labeled Manual in the mode indicator), `acceptEdits`, `plan`, and, when available, `bypassPermissions` and then `auto`. From `auto`, the first press switches to `default`. See [permission modes](/docs/en/permission-modes). On a file permission prompt, the same key closes an open [comment field](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt). With no field open, it selects the option that allows the action for the rest of the session, when the prompt offers that option |
36| `Option+P` (macOS) or `Alt+P` (Windows/Linux) | Switch model | Switch models without clearing your prompt |
37| `Option+T` (macOS) or `Alt+T` (Windows/Linux) | Toggle extended thinking | Enable or disable extended thinking mode. Has no effect on Opus 5.5, Sonnet 5.5, or the Fable models, which always use extended thinking. Works on macOS without configuring Option as Meta |
38| `Option+O` (macOS) or `Alt+O` (Windows/Linux) | Toggle fast mode | Enable or disable [fast mode](/docs/en/fast-mode) |
15| Shortcut | Description | Context |
16| :- | :- | :- |
17| `Ctrl+C` | Interrupt, or clear input | Interrupts a running operation. If nothing is running, the first press clears the prompt input and a second press exits Claude Code |
18| `Ctrl+X Ctrl+K` | Stop all running [background subagents](/docs/en/sub-agents#run-subagents-in-foreground-or-background) in this session, and turn off [artifact auto-replies](/docs/en/artifacts#let-claude-reply-to-comments-on-its-own) for the rest of it. Press twice within 3 seconds to confirm | Subagent control |
19| `Ctrl+D` | Exit Claude Code session | The first press shows a confirmation hint and a second press within 800ms exits. When the prompt has text, `Ctrl+D` deletes the character after the cursor instead |
20| `Ctrl+G` or `Ctrl+X Ctrl+E` | Open in default text editor | Edit your prompt or custom response in your default text editor. `Ctrl+X Ctrl+E` is the readline-native binding. Turn on **Show last response in external editor** in `/config` to prepend Claude's previous reply as `#`-commented context above your prompt; Claude Code strips the comment block when you save |
21| `Ctrl+L` | Redraw the screen | Forces a full terminal redraw, keeping input and conversation history. Use this to recover if the display becomes garbled or partially blank. See [Clear the conversation](/docs/en/fullscreen#clear-the-conversation) for fullscreen rendering |
22| `Ctrl+O` | Toggle transcript viewer | Shows detailed tool usage and execution, with a timestamp and the model used on each assistant message. Also expands lines that collapse by default, such as MCP calls, shown as a single `Called slack 3 times` line, and [messages from your other sessions](/docs/en/cross-session-messaging#what-a-message-looks-like), shown as a one-line `Message from @<sender>` preview |
23| `Ctrl+R` | Reverse search command history | Search through previous commands interactively |
24| `Ctrl+V` or `Cmd+V` (iTerm2) or `Alt+V` (Windows and WSL) | Paste image from clipboard | Inserts an `[Image #N]` chip at the cursor so you can reference it positionally in your prompt. On WSL, both `Ctrl+V` and `Alt+V` are bound; use `Alt+V` if your terminal intercepts `Ctrl+V` |
25| `Ctrl+B` | Background running tasks | Backgrounds Bash commands and agents. Tmux users press twice |
26| `Ctrl+T` | Toggle Claude's task checklist | Show or hide [Claude's to-do checklist](#task-list) in the status area. This is not the background-task view; use [`/tasks`](/docs/en/commands) to see running shells and subagents |
27| `Ctrl+S` | Stash or restore prompt | With text in the input, stashes it and clears the prompt. Pressed again on an empty prompt, restores the stashed text, cursor position, pasted content, and input mode, so a stashed `!` [shell command](#shell-mode-with-prefix) comes back in shell mode |
28| `Ctrl+Z` | Suspend Claude Code | Unix only. Suspends the process to your shell; run `fg` to resume |
29| `Left/Right arrows` | Cycle through dialog tabs | Navigate between tabs in permission dialogs and menus. In a tabbed dialog, the keys switch tabs while the tab row has focus. See [Tabs actions](/docs/en/keybindings#tabs-actions) for how focus moves |
30| `Tab` | Accept an autocomplete suggestion, or add a comment to a permission answer | While autocomplete suggestions are showing in the prompt input, accepts the selected suggestion. On most permission prompts, with **Yes** or **No** focused, opens a comment field on that option, and pressing it again closes the field. See [add a comment when you answer a permission prompt](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt) |
31| `Up/Down arrows` or `Ctrl+P`/`Ctrl+N` | Move cursor or navigate command history | When the input spans more than one visual row, whether wrapped or multiline, first moves the cursor within the prompt. Once the cursor is on the first or last visual row, pressing again navigates command history. While you have messages queued, `Up` from the first row instead [takes them back](#take-back-what-you-queued) |
32| `Esc` | Interrupt Claude, or close a dialog | Stop the current response or tool call mid-turn so you can redirect. Claude keeps the work done so far. If you have [messages queued](#queue-messages-while-claude-works), Claude Code sends them next. When a dialog is open, `Esc` closes the dialog. While a footer item is selected, such as a row in the [subagent panel](/docs/en/sub-agents#run-subagents-in-foreground-or-background) below the prompt, `Esc` [deselects it](/docs/en/keybindings#footer-actions) instead of interrupting. On a permission prompt, `Esc` declines the action, the same as [**No** without a comment](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt) |
33| `Esc` + `Esc` | Clear input draft, or rewind | When the prompt input contains text, double `Esc` clears it and saves the draft to history so `Up` recalls it. When the input is empty, double `Esc` opens the [rewind menu](/docs/en/checkpointing) to restore or summarize code and conversation from a previous point |
34| `Ctrl+Enter` or `Ctrl+X Ctrl+S` | Send queued messages now | Sends your [queued messages](#queue-messages-while-claude-works), and your draft with them, right away. [When Claude Code sends what you queued](#when-claude-code-sends-what-you-queued) covers what happens to the turn Claude is working on. In [shell mode](#shell-mode-with-prefix), the key only queues your command. In terminals that don't report extended keys, `Ctrl+Enter` arrives as plain `Enter`; `Ctrl+X Ctrl+S` works in any terminal. Requires Claude Code v2.1.275 or later |
35| `Shift+Tab`, or `Alt+M` on Windows when the Node or Bun runtime doesn't enable VT input mode | Cycle permission modes | Cycle through `default` (labeled Manual in the mode indicator), `acceptEdits`, `plan`, and, when available, `bypassPermissions` and then `auto`. From `auto`, the first press switches to `default`. See [permission modes](/docs/en/permission-modes). On a file permission prompt, the same key closes an open [comment field](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt). With no field open, it selects the option that allows the action for the rest of the session, when the prompt offers that option |
36| `Option+P` (macOS) or `Alt+P` (Windows/Linux) | Switch model | Switch models without clearing your prompt |
37| `Option+T` (macOS) or `Alt+T` (Windows/Linux) | Toggle extended thinking | Enable or disable extended thinking mode. Has no effect on Opus 5.5, Sonnet 5.5, or the Fable models, which always use extended thinking. Works on macOS without configuring Option as Meta |
38| `Option+O` (macOS) or `Alt+O` (Windows/Linux) | Toggle fast mode | Enable or disable [fast mode](/docs/en/fast-mode) |
3939
4040### Text editing
4141
42| Shortcut | Description | Context |
43| :------------------------- | :----------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
44| `Ctrl+A` | Move cursor to start of current line | In multiline input, moves to the start of the current logical line |
45| `Ctrl+E` | Move cursor to end of current line | In multiline input, moves to the end of the current logical line |
46| `Ctrl+K` | Delete to end of line | Stores deleted text for pasting |
47| `Ctrl+U` | Delete from cursor to line start | Stores deleted text for pasting. Repeat to clear across lines in multiline input. On macOS, terminal emulators including iTerm2 and Terminal.app map `Cmd+Backspace` to this shortcut |
48| `Ctrl+W` | Delete back to previous whitespace | Stores deleted text for pasting. One press removes a whole path or `--flag=value`. To delete only the previous word, press `Option+Delete` on macOS or `Ctrl+Backspace` on Windows |
49| `Ctrl+Y` | Paste deleted text | Pastes the text you last deleted with one of the word or line deletion shortcuts, such as `Ctrl+K`, `Ctrl+U`, or `Ctrl+W` |
50| `Alt+Y` (after `Ctrl+Y`) | Cycle paste history | After pasting, cycle through previously deleted text. Requires [Option as Meta](#keyboard-shortcuts) on macOS |
51| `Alt+B` | Move cursor back one word | Word navigation. Requires [Option as Meta](#keyboard-shortcuts) on macOS |
52| `Alt+F` | Move cursor forward one word | Moves to the end of the current word, or to the end of the next word when the cursor is between words. Requires [Option as Meta](#keyboard-shortcuts) on macOS |
53| `Alt+D` | Delete to end of word | Deletes to the end of the current word, or to the end of the next word when the cursor is between words. Stores deleted text for pasting. Requires [Option as Meta](#keyboard-shortcuts) on macOS |
54| `Ctrl+_` or `Ctrl+Shift+-` | Undo last input edit | Restores the previous input text and cursor position |
42| Shortcut | Description | Context |
43| :- | :- | :- |
44| `Ctrl+A` | Move cursor to start of current line | In multiline input, moves to the start of the current logical line |
45| `Ctrl+E` | Move cursor to end of current line | In multiline input, moves to the end of the current logical line |
46| `Ctrl+K` | Delete to end of line | Stores deleted text for pasting |
47| `Ctrl+U` | Delete from cursor to line start | Stores deleted text for pasting. Repeat to clear across lines in multiline input. On macOS, terminal emulators including iTerm2 and Terminal.app map `Cmd+Backspace` to this shortcut |
48| `Ctrl+W` | Delete back to previous whitespace | Stores deleted text for pasting. One press removes a whole path or `--flag=value`. To delete only the previous word, press `Option+Delete` on macOS or `Ctrl+Backspace` on Windows |
49| `Ctrl+Y` | Paste deleted text | Pastes the text you last deleted with one of the word or line deletion shortcuts, such as `Ctrl+K`, `Ctrl+U`, or `Ctrl+W` |
50| `Alt+Y` (after `Ctrl+Y`) | Cycle paste history | After pasting, cycle through previously deleted text. Requires [Option as Meta](#keyboard-shortcuts) on macOS |
51| `Alt+B` | Move cursor back one word | Word navigation. Requires [Option as Meta](#keyboard-shortcuts) on macOS |
52| `Alt+F` | Move cursor forward one word | Moves to the end of the current word, or to the end of the next word when the cursor is between words. Requires [Option as Meta](#keyboard-shortcuts) on macOS |
53| `Alt+D` | Delete to end of word | Deletes to the end of the current word, or to the end of the next word when the cursor is between words. Stores deleted text for pasting. Requires [Option as Meta](#keyboard-shortcuts) on macOS |
54| `Ctrl+_` or `Ctrl+Shift+-` | Undo last input edit | Restores the previous input text and cursor position |
5555
5656<h3 id="make-ctrl-w-delete-back-to-whitespace">
5757 Word boundaries in editing shortcuts
from line 69
6969
7070### Theme and display
7171
72| Shortcut | Description | Context |
73| :------- | :----------------------------------------- | :----------------------------------------------------------------------------------------------------------- |
72| Shortcut | Description | Context |
73| :- | :- | :- |
7474| `Ctrl+T` | Toggle syntax highlighting for code blocks | Only works inside the `/theme` picker menu. Controls whether code in Claude's responses uses syntax coloring |
7575
7676### Multiline input
7777
78| Method | Shortcut | Context |
79| :--------------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
80| Quick escape | `\` + `Enter` | Works in all terminals |
81| Option key | `Option+Enter` | After enabling [Option as Meta](/docs/en/terminal-config#enable-option-key-shortcuts-on-macos) on macOS |
82| Shift+Enter | `Shift+Enter` | Native in iTerm2, WezTerm, Ghostty, Kitty, Warp, Apple Terminal, Windows Terminal. For other terminals, see [Enter multiline prompts](/docs/en/terminal-config#enter-multiline-prompts) |
83| Control sequence | `Ctrl+J` | Works in any terminal without configuration |
84| Paste mode | Paste directly | For code blocks, logs |
78| Method | Shortcut | Context |
79| :- | :- | :- |
80| Quick escape | `\` + `Enter` | Works in all terminals |
81| Option key | `Option+Enter` | After enabling [Option as Meta](/docs/en/terminal-config#enable-option-key-shortcuts-on-macos) on macOS |
82| Shift+Enter | `Shift+Enter` | Native in iTerm2, WezTerm, Ghostty, Kitty, Warp, Apple Terminal, Windows Terminal. For other terminals, see [Enter multiline prompts](/docs/en/terminal-config#enter-multiline-prompts) |
83| Control sequence | `Ctrl+J` | Works in any terminal without configuration |
84| Paste mode | Paste directly | For code blocks, logs |
8585
8686### Quick commands
8787
88| Shortcut | Description | Notes |
89| :----------------- | :----------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
90| `/` at start | Command or skill | See [commands](#commands) and [skills](/docs/en/skills) |
91| `!` at start | Shell mode | Run a command directly, add its output to the session, and have Claude respond to it |
92| `@` | File path mention | Trigger file path autocomplete. In sessions with [cross-session messaging](/docs/en/cross-session-messaging#message-another-session), when you type at least one letter after the `@`, Claude Code also suggests your other live sessions on this machine, so you can tell Claude to message the one you pick. Requires Claude Code v2.1.232 or later |
93| `:` | Emoji shortcode | Type a full `:name:` to insert the emoji, or two or more characters for suggestions. See [Emoji shortcodes](#emoji-shortcodes). Requires Claude Code v2.1.217 or later |
94| `?` on empty input | Toggle the shortcut help panel | Typing `?` when the input already contains text inserts the character |
88| Shortcut | Description | Notes |
89| :- | :- | :- |
90| `/` at start | Command or skill | See [commands](#commands) and [skills](/docs/en/skills) |
91| `!` at start | Shell mode | Run a command directly, add its output to the session, and have Claude respond to it |
92| `@` | File path mention | Trigger file path autocomplete. In sessions with [cross-session messaging](/docs/en/cross-session-messaging#message-another-session), when you type at least one letter after the `@`, Claude Code also suggests your other live sessions on this machine, so you can tell Claude to message the one you pick. Requires Claude Code v2.1.232 or later |
93| `:` | Emoji shortcode | Type a full `:name:` to insert the emoji, or two or more characters for suggestions. See [Emoji shortcodes](#emoji-shortcodes). Requires Claude Code v2.1.217 or later |
94| `?` on empty input | Toggle the shortcut help panel | Typing `?` when the input already contains text inserts the character |
9595
9696### Transcript viewer
9797
9898When the transcript viewer is open (toggled with `Ctrl+O`), these shortcuts are available. Run `/tui` with no argument to check which renderer is active. `Ctrl+E` can be rebound via [`transcript:toggleShowAll`](/docs/en/keybindings).
9999
100| Shortcut | Description |
101| :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
102| `?` | Toggle the keyboard shortcut help panel. Requires [fullscreen rendering](/docs/en/fullscreen) |
103| `{` / `}` | Jump to the previous or next user prompt, like vim paragraph motion. Requires [fullscreen rendering](/docs/en/fullscreen) |
104| `Ctrl+E` | Toggle show all content. Available in the classic renderer only, not in [fullscreen rendering](/docs/en/fullscreen) |
105| `[` | Write the full conversation to your terminal's native scrollback so `Cmd+F`, tmux copy mode, and other native tools can search it. Requires [fullscreen rendering](/docs/en/fullscreen#search-and-review-the-conversation) |
106| `v` | Write the conversation to a temporary file and open it in `$VISUAL` or `$EDITOR`. Requires [fullscreen rendering](/docs/en/fullscreen) |
107| `q`, `Ctrl+C`, `Esc` | Exit transcript view. All three can be rebound via [`transcript:exit`](/docs/en/keybindings) |
100| Shortcut | Description |
101| :- | :- |
102| `?` | Toggle the keyboard shortcut help panel. Requires [fullscreen rendering](/docs/en/fullscreen) |
103| `{` / `}` | Jump to the previous or next user prompt, like vim paragraph motion. Requires [fullscreen rendering](/docs/en/fullscreen) |
104| `Ctrl+E` | Toggle show all content. Available in the classic renderer only, not in [fullscreen rendering](/docs/en/fullscreen) |
105| `[` | Write the full conversation to your terminal's native scrollback so `Cmd+F`, tmux copy mode, and other native tools can search it. Requires [fullscreen rendering](/docs/en/fullscreen#search-and-review-the-conversation) |
106| `v` | Write the conversation to a temporary file and open it in `$VISUAL` or `$EDITOR`. Requires [fullscreen rendering](/docs/en/fullscreen) |
107| `q`, `Ctrl+C`, `Esc` | Exit transcript view. All three can be rebound via [`transcript:exit`](/docs/en/keybindings) |
108108
109109### Voice input
110110
111| Shortcut | Description | Notes |
112| :------------------ | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
111| Shortcut | Description | Notes |
112| :- | :- | :- |
113113| Hold or tap `Space` | Voice dictation | Requires [voice dictation](/docs/en/voice-dictation) to be enabled. Hold to record, or run `/voice tap` for tap-to-toggle. [Rebindable](/docs/en/voice-dictation#rebind-the-dictation-key) |
114114
115115## Commands
from line 139
139139
140140### Mode switching
141141
142| Command | Action | From mode |
143| :---------------- | :-------------------------------------------------------------------------------------------------------- | :------------- |
142| Command | Action | From mode |
143| :- | :- | :- |
144144| `Esc` or `Ctrl+[` | Enter NORMAL mode. In terminals that use the Kitty keyboard protocol, `Ctrl+[` requires v2.1.242 or later | INSERT, VISUAL |
145| `i` | Insert before cursor | NORMAL |
146| `I` | Insert at beginning of line | NORMAL |
147| `a` | Insert after cursor | NORMAL |
148| `A` | Insert at end of line | NORMAL |
149| `o` | Open line below | NORMAL |
150| `O` | Open line above | NORMAL |
151| `v` | Start character-wise visual selection | NORMAL |
152| `V` | Start line-wise visual selection | NORMAL |
145| `i` | Insert before cursor | NORMAL |
146| `I` | Insert at beginning of line | NORMAL |
147| `a` | Insert after cursor | NORMAL |
148| `A` | Insert at end of line | NORMAL |
149| `o` | Open line below | NORMAL |
150| `O` | Open line above | NORMAL |
151| `v` | Start character-wise visual selection | NORMAL |
152| `V` | Start line-wise visual selection | NORMAL |
153153
154154### Remap INSERT-mode key sequences
155155
from line 172
172172
173173### Navigation (NORMAL mode)
174174
175| Command | Action |
176| :-------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- |
177| `h`/`j`/`k`/`l` | Move left/down/up/right |
178| `Space` | Move right |
179| `w` | Next word |
180| `e` | End of word |
181| `b` | Previous word |
182| `0` | Beginning of line |
183| `$` | End of line |
184| `^` | First non-blank character |
185| `gg` | Beginning of input |
186| `G` | End of input |
187| `f{char}` | Jump to next occurrence of character |
188| `F{char}` | Jump to previous occurrence of character |
189| `t{char}` | Jump to just before next occurrence of character |
190| `T{char}` | Jump to just after previous occurrence of character |
191| `;` | Repeat last f/F/t/T motion |
192| `,` | Repeat last f/F/t/T motion in reverse |
193| `/` | 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 |
175| Command | Action |
176| :- | :- |
177| `h`/`j`/`k`/`l` | Move left/down/up/right |
178| `Space` | Move right |
179| `w` | Next word |
180| `e` | End of word |
181| `b` | Previous word |
182| `0` | Beginning of line |
183| `$` | End of line |
184| `^` | First non-blank character |
185| `gg` | Beginning of input |
186| `G` | End of input |
187| `f{char}` | Jump to next occurrence of character |
188| `F{char}` | Jump to previous occurrence of character |
189| `t{char}` | Jump to just before next occurrence of character |
190| `T{char}` | Jump to just after previous occurrence of character |
191| `;` | Repeat last f/F/t/T motion |
192| `,` | Repeat last f/F/t/T motion in reverse |
193| `/` | 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 |
194194
195195<Note>
196196 In vim NORMAL mode, if the cursor is at the beginning or end of input and can't move further, `j`/`k` and `↑`/`↓` navigate command history instead. `←` on an empty prompt opens [agent view](/docs/en/agent-view) from NORMAL mode as well as INSERT; before v2.1.219, `←` on an empty prompt did nothing in NORMAL mode.
from line 198
198198
199199### Editing (NORMAL mode)
200200
201| Command | Action |
202| :-------------------- | :------------------------------------------------------------------------------------------------------------------------ |
203| `x` | Delete character |
204| `r{char}` | Replace character under cursor with `{char}` |
205| `dd` | Delete line |
206| `D` | Delete to end of line |
207| `dw`/`de`/`db` | Delete word/to end/back |
208| `df{char}`/`dt{char}` | Delete to and including, or up to, the next occurrence of a character |
209| `dj`/`dk` | Delete the current line and the line below or above |
210| `dgg`/`dG` | Delete from the current line to the first or last line |
211| `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 |
212| `cc` | Change line |
213| `C` | Change to end of line |
214| `cw`/`ce`/`cb` | Change word/to end/back |
215| `s` | Substitute character: delete the character under the cursor and enter INSERT mode. Requires Claude Code v2.1.211 or later |
216| `S` | Substitute line: clear the line and enter INSERT mode. Requires Claude Code v2.1.211 or later |
217| `yy`/`Y` | Yank (copy) line |
218| `yw`/`ye`/`yb` | Yank word/to end/back |
219| `p` | Paste after cursor |
220| `P` | Paste before cursor |
221| `>>` | Indent line |
222| `<<` | Dedent line |
223| `J` | Join lines |
224| `u` | Undo |
225| `.` | Repeat last change |
201| Command | Action |
202| :- | :- |
203| `x` | Delete character |
204| `r{char}` | Replace character under cursor with `{char}` |
205| `dd` | Delete line |
206| `D` | Delete to end of line |
207| `dw`/`de`/`db` | Delete word/to end/back |
208| `df{char}`/`dt{char}` | Delete to and including, or up to, the next occurrence of a character |
209| `dj`/`dk` | Delete the current line and the line below or above |
210| `dgg`/`dG` | Delete from the current line to the first or last line |
211| `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 |
212| `cc` | Change line |
213| `C` | Change to end of line |
214| `cw`/`ce`/`cb` | Change word/to end/back |
215| `s` | Substitute character: delete the character under the cursor and enter INSERT mode. Requires Claude Code v2.1.211 or later |
216| `S` | Substitute line: clear the line and enter INSERT mode. Requires Claude Code v2.1.211 or later |
217| `yy`/`Y` | Yank (copy) line |
218| `yw`/`ye`/`yb` | Yank word/to end/back |
219| `p` | Paste after cursor |
220| `P` | Paste before cursor |
221| `>>` | Indent line |
222| `<<` | Dedent line |
223| `J` | Join lines |
224| `u` | Undo |
225| `.` | Repeat last change |
226226
227227### Text objects (NORMAL mode)
228228
229229Text objects work with operators like `d`, `c`, and `y`:
230230
231| Command | Action |
232| :-------- | :--------------------------------------- |
233| `iw`/`aw` | Inner/around word |
231| Command | Action |
232| :- | :- |
233| `iw`/`aw` | Inner/around word |
234234| `iW`/`aW` | Inner/around WORD (whitespace-delimited) |
235| `i"`/`a"` | Inner/around double quotes |
236| `i'`/`a'` | Inner/around single quotes |
237| `i(`/`a(` | Inner/around parentheses |
238| `i[`/`a[` | Inner/around brackets |
239| `i{`/`a{` | Inner/around braces |
235| `i"`/`a"` | Inner/around double quotes |
236| `i'`/`a'` | Inner/around single quotes |
237| `i(`/`a(` | Inner/around parentheses |
238| `i[`/`a[` | Inner/around brackets |
239| `i{`/`a{` | Inner/around braces |
240240
241241### Visual mode
242242
243243Press `v` for character-wise selection or `V` for line-wise selection. Motions extend the selection, and operators act on it directly.
244244
245| Command | Action |
246| :--------------- | :--------------------------------------------------- |
247| `d`/`x` | Delete selection |
248| `y` | Yank selection |
249| `c`/`s` | Change selection |
250| `p` | Replace selection with register contents |
251| `r{char}` | Replace every selected character with `{char}` |
252| `~`/`u`/`U` | Toggle, lowercase, or uppercase selection |
253| `>`/`<` | Indent or dedent selected lines |
254| `J` | Join selected lines |
255| `o` | Swap cursor and anchor |
256| `iw`/`aw`/`i"`/… | Select a text object |
257| `v`/`V` | Toggle between character-wise and line-wise, or exit |
245| Command | Action |
246| :- | :- |
247| `d`/`x` | Delete selection |
248| `y` | Yank selection |
249| `c`/`s` | Change selection |
250| `p` | Replace selection with register contents |
251| `r{char}` | Replace every selected character with `{char}` |
252| `~`/`u`/`U` | Toggle, lowercase, or uppercase selection |
253| `>`/`<` | Indent or dedent selected lines |
254| `J` | Join selected lines |
255| `o` | Swap cursor and anchor |
256| `iw`/`aw`/`i"`/… | Select a text object |
257| `v`/`V` | Toggle between character-wise and line-wise, or exit |
258258
259259Block-wise visual mode with `Ctrl+V` is not supported.
260260
from line 611
611611
612612Once the answer appears, the overlay accepts these keys.
613613
614| Key | Action |
615| :--------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
616| `Space`, `Enter`, `Escape` | Dismiss the answer and return to the prompt |
617| `Up` / `Down` | Scroll the answer |
614| Key | Action |
615| :- | :- |
616| `Space`, `Enter`, `Escape` | Dismiss the answer and return to the prompt |
617| `Up` / `Down` | Scroll the answer |
618618| `Shift+Left` / `Shift+Right` | Step between this answer and your earlier `/btw` answers. `Shift+Left` moves to older answers and `Shift+Right` returns toward the current one. `[` and `]` do the same, for terminals that don't report `Shift` with arrow keys. `Tab` / `Shift+Tab` cycle through the same answers. Requires Claude Code v2.1.257 or later. Between v2.1.187 and v2.1.256, the keys were plain `Left` / `Right` |
619| `c` | Copy the answer to your clipboard as raw Markdown. Use this instead of mouse selection, which captures the hard-wrapped terminal rendering rather than the source text |
620| `f` | Start a [forked subagent](/docs/en/sub-agents#fork-the-current-conversation) that inherits the parent conversation plus this question and answer, so it can continue with full tool access. You stay in the current session and find the fork in the [panel below your prompt](/docs/en/sub-agents#observe-and-steer-running-forks). Available in local sessions only |
621| `x` | Clear the list of earlier `/btw` exchanges shown above the current answer |
619| `c` | Copy the answer to your clipboard as raw Markdown. Use this instead of mouse selection, which captures the hard-wrapped terminal rendering rather than the source text |
620| `f` | Start a [forked subagent](/docs/en/sub-agents#fork-the-current-conversation) that inherits the parent conversation plus this question and answer, so it can continue with full tool access. You stay in the current session and find the fork in the [panel below your prompt](/docs/en/sub-agents#observe-and-steer-running-forks). Available in local sessions only |
621| `x` | Clear the list of earlier `/btw` exchanges shown above the current answer |
622622
623623In an attached [background session](/docs/en/agent-view#attach-to-a-session), `Left` detaches and returns you to agent view, even while the answer is still arriving. The side question keeps running while you're away. The next time you attach to the session, the overlay reopens with the side question, or with its answer. Before v2.1.257, `Left` didn't detach there.
624624
from line 755
755755
756756Claude Code builds the link for the host of the repository it identifies from your git remote, not for the repository the reference names:
757757
758| Your repository's host | Where `owner/repo#123` links |
759| :----------------------------------------------------------------- | :------------------------------------------- |
760| github.com, a GitHub Enterprise host, or any host not listed below | `https://<host>/owner/repo/issues/123` |
761| gitlab.com | `https://gitlab.com/owner/repo/-/issues/123` |
762| bitbucket.org, codeberg.org, or gitea.com | No link; the reference stays plain text |
758| Your repository's host | Where `owner/repo#123` links |
759| :- | :- |
760| github.com, a GitHub Enterprise host, or any host not listed below | `https://<host>/owner/repo/issues/123` |
761| gitlab.com | `https://gitlab.com/owner/repo/-/issues/123` |
762| bitbucket.org, codeberg.org, or gitea.com | No link; the reference stays plain text |
763763
764764## See also
765765
jetbrains Changed · +3 / -3 lines
from line 211
211211
212212**Tools exposed to the model.** The server hosts several tools, but only one is visible to the model. The rest are internal RPC the CLI uses for its own UI, such as opening diffs and reading selections, and are filtered out before the tool list reaches Claude.
213213
214| Tool name (as seen by hooks) | What it does | Read-only |
215| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- |
216| `mcp__ide__getDiagnostics` | Returns the IDE's inspection diagnostics, the errors and warnings shown in the editor. Each call covers one file: the file Claude specifies, or the file in your active editor if Claude doesn't specify one. | Yes |
214| Tool name (as seen by hooks) | What it does | Read-only |
215| - | - | - |
216| `mcp__ide__getDiagnostics` | Returns the IDE's inspection diagnostics, the errors and warnings shown in the editor. Each call covers one file: the file Claude specifies, or the file in your active editor if Claude doesn't specify one. | Yes |
217217
218218The JetBrains plugin does not expose a code-execution tool to the model.
219219
keybindings Changed · +213 / -210 lines
The two sides of this change are more than 400 edits apart, too far apart to line up, so this is the differ's own diff of it and the words inside a line are not marked.
from line 10
1010
1111<Note>Changes to the keybindings file are automatically detected and applied without restarting Claude Code.</Note>
1212
13| Field | Description |
14| :--------- | :------------------------------------------------- |
15| `$schema` | Optional JSON Schema URL for editor autocompletion |
16| `$docs` | Optional documentation URL |
17| `bindings` | Array of binding blocks by context |
13| Field | Description |
14| :- | :- |
15| `$schema` | Optional JSON Schema URL for editor autocompletion |
16| `$docs` | Optional documentation URL |
17| `bindings` | Array of binding blocks by context |
1818
1919This example binds `Ctrl+E` to open an external editor in the chat context, and unbinds `Ctrl+U`:
2020
from line 38
3838
3939Each binding block specifies a **context** where the bindings apply:
4040
41| Context | Description |
42| :---------------- | :----------------------------------------------------------- |
43| `Global` | Applies everywhere in the app |
44| `Chat` | Main chat input area |
45| `Autocomplete` | Autocomplete menu is open |
46| `Settings` | Settings menu |
47| `Confirmation` | Permission and confirmation dialogs |
48| `Tabs` | Tab navigation components |
49| `Help` | Help menu is visible |
50| `Transcript` | Transcript viewer |
51| `HistorySearch` | History search mode (Ctrl+R) |
52| `Task` | Background task is running |
53| `ThemePicker` | Theme picker dialog |
54| `Attachments` | Image attachment navigation in select dialogs |
55| `Footer` | Footer indicator navigation (tasks, teams, diff, artifacts) |
56| `MessageSelector` | Rewind and summarize dialog message selection |
57| `DiffDialog` | Diff viewer navigation |
58| `DiffPanel` | The [diff panel](/docs/en/interactive-mode#diff-panel) is open |
59| `ModelPicker` | Model picker effort level |
60| `EffortSlider` | Effort slider opened by `/effort` |
61| `Select` | Generic select/list components |
62| `Plugin` | Plugin dialog (browse, discover, manage) |
63| `Agents` | [Agent view](/docs/en/agent-view) (`claude agents`) |
64| `Scroll` | Conversation scrolling and text selection in fullscreen mode |
41| Context | Description |
42| :- | :- |
43| `Global` | Applies everywhere in the app |
44| `Chat` | Main chat input area |
45| `Autocomplete` | Autocomplete menu is open |
46| `Settings` | Settings menu |
47| `Confirmation` | Permission and confirmation dialogs |
48| `Tabs` | Tab navigation components |
49| `Help` | Help menu is visible |
50| `Transcript` | Transcript viewer |
51| `HistorySearch` | History search mode (Ctrl+R) |
52| `Task` | Background task is running |
53| `ThemePicker` | Theme picker dialog |
54| `Attachments` | Image attachment navigation in select dialogs |
55| `Footer` | Footer indicator navigation (tasks, teams, diff, artifacts) |
56| `MessageSelector` | Rewind and summarize dialog message selection |
57| `DiffDialog` | Diff viewer navigation |
58| `DiffPanel` | The [diff panel](/docs/en/interactive-mode#diff-panel) is open |
59| `ModelPicker` | Model picker effort level |
60| `EffortSlider` | Effort slider opened by `/effort` |
61| `Select` | Generic select/list components |
62| `Plugin` | Plugin dialog (browse, discover, manage) |
63| `Agents` | [Agent view](/docs/en/agent-view) (`claude agents`) |
64| `Scroll` | Conversation scrolling and text selection in fullscreen mode |
6565
6666Before v2.1.205, a `Doctor` context and a `doctor:fix` action existed for the `/doctor` diagnostics screen.
6767
from line 73
7373
7474Actions available in the `Global` context:
7575
76| Action | Default | Description |
77| :--------------------- | :-------- | :----------------------------------------------------------------------------------------------------------- |
78| `app:interrupt` | Ctrl+C | Cancel current operation |
79| `app:exit` | Ctrl+D | Exit Claude Code. Press twice within 800ms to confirm |
80| `app:redraw` | (unbound) | Force terminal redraw |
81| `app:toggleTodos` | Ctrl+T | Toggle visibility of Claude's to-do checklist. This is not the [`/tasks`](/docs/en/commands) background-task view |
82| `app:toggleTranscript` | Ctrl+O | Toggle verbose transcript |
76| Action | Default | Description |
77| :- | :- | :- |
78| `app:interrupt` | Ctrl+C | Cancel current operation |
79| `app:exit` | Ctrl+D | Exit Claude Code. Press twice within 800ms to confirm |
80| `app:redraw` | (unbound) | Force terminal redraw |
81| `app:toggleTodos` | Ctrl+T | Toggle visibility of Claude's to-do checklist. This is not the [`/tasks`](/docs/en/commands) background-task view |
82| `app:toggleTranscript` | Ctrl+O | Toggle verbose transcript |
8383
8484### History actions
8585
8686Actions for navigating command history:
8787
88| Action | Default | Description |
89| :----------------- | :------ | :-------------------- |
90| `history:search` | Ctrl+R | Open history search |
91| `history:previous` | Up | Previous history item |
92| `history:next` | Down | Next history item |
88| Action | Default | Description |
89| :- | :- | :- |
90| `history:search` | Ctrl+R | Open history search |
91| `history:previous` | Up | Previous history item |
92| `history:next` | Down | Next history item |
9393
9494### Chat actions
9595
9696Actions available in the `Chat` context:
9797
98| Action | Default | Description |
99| :-------------------- | :-------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
100| `chat:cancel` | Escape | Cancel current input |
101| `chat:clearInput` | Ctrl+L | Force a full screen redraw, preserving input and conversation |
102| `chat:clearScreen` | Cmd+K | Same as `chat:clearInput`. See [Clear the conversation](/docs/en/fullscreen#clear-the-conversation) for how Cmd+K behaves on iTerm2 and Terminal.app |
103| `chat:killAgents` | Ctrl+X Ctrl+K | Stop all running [background subagents](/docs/en/sub-agents#run-subagents-in-foreground-or-background) in this session and turn off [artifact auto-replies](/docs/en/artifacts#let-claude-reply-to-comments-on-its-own) for the rest of it |
104| `chat:cycleMode` | Shift+Tab\* | Cycle permission modes |
105| `chat:modelPicker` | Meta+P | Open model picker |
106| `chat:fastMode` | Meta+O | Toggle fast mode |
107| `chat:thinkingToggle` | Meta+T | Toggle extended thinking |
108| `chat:submit` | Enter | Submit message |
109| `chat:queueSubmit` | Ctrl+X Enter | Submit the message, marked to wait its turn: while Claude is working, Claude Code [queues it](/docs/en/interactive-mode#queue-messages-while-claude-works) and never interrupts the turn. Unlike `chat:submit`, it submits the draft even while an autocomplete suggestion is highlighted. Requires v2.1.247 or later |
110| `chat:sendNow` | Ctrl+Enter, Ctrl+X Ctrl+S | Send your [queued messages](/docs/en/interactive-mode#queue-messages-while-claude-works), and your draft with them, right away. [When Claude Code sends what you queued](/docs/en/interactive-mode#when-claude-code-sends-what-you-queued) covers what happens to the turn Claude is working on. When nothing is running, the key submits the draft, and in [shell mode](/docs/en/interactive-mode#shell-mode-with-prefix) it only queues the command. Terminals that don't report extended keys deliver `Ctrl+Enter` as plain `Enter`, so `Ctrl+X Ctrl+S` is the binding that works in any terminal. Requires v2.1.275 or later |
111| `chat:newline` | Ctrl+J | Insert a newline without submitting |
112| `chat:undo` | Ctrl+\_, Ctrl+Shift+- | Undo last action |
113| `chat:externalEditor` | Ctrl+G, Ctrl+X Ctrl+E | Open in external editor. The [agent view dispatch input](/docs/en/agent-view#keyboard-shortcuts) follows this action's single-keystroke bindings too |
114| `chat:stash` | Ctrl+S | Stash current prompt |
115| `chat:imagePaste` | Ctrl+V (Alt+V on Windows and WSL) | Paste image from clipboard. On WSL, both shortcuts are bound by default |
98| Action | Default | Description |
99| :- | :- | :- |
100| `chat:cancel` | Escape | Cancel current input |
101| `chat:clearInput` | Ctrl+L | Force a full screen redraw, preserving input and conversation |
102| `chat:clearScreen` | Cmd+K | Same as `chat:clearInput`. See [Clear the conversation](/docs/en/fullscreen#clear-the-conversation) for how Cmd+K behaves on iTerm2 and Terminal.app |
103| `chat:killAgents` | Ctrl+X Ctrl+K | Stop all running [background subagents](/docs/en/sub-agents#run-subagents-in-foreground-or-background) in this session and turn off [artifact auto-replies](/docs/en/artifacts#let-claude-reply-to-comments-on-its-own) for the rest of it |
104| `chat:cycleMode` | Shift+Tab\* | Cycle permission modes |
105| `chat:modelPicker` | Meta+P | Open model picker |
106| `chat:fastMode` | Meta+O | Toggle fast mode |
107| `chat:thinkingToggle` | Meta+T | Toggle extended thinking |
108| `chat:submit` | Enter | Submit message |
109| `chat:queueSubmit` | Ctrl+X Enter | Submit the message, marked to wait its turn: while Claude is working, Claude Code [queues it](/docs/en/interactive-mode#queue-messages-while-claude-works) and never interrupts the turn. Unlike `chat:submit`, it submits the draft even while an autocomplete suggestion is highlighted. Requires v2.1.247 or later |
110| `chat:sendNow` | Ctrl+Enter, Ctrl+X Ctrl+S | Send your [queued messages](/docs/en/interactive-mode#queue-messages-while-claude-works), and your draft with them, right away. [When Claude Code sends what you queued](/docs/en/interactive-mode#when-claude-code-sends-what-you-queued) covers what happens to the turn Claude is working on. When nothing is running, the key submits the draft, and in [shell mode](/docs/en/interactive-mode#shell-mode-with-prefix) it only queues the command. Terminals that don't report extended keys deliver `Ctrl+Enter` as plain `Enter`, so `Ctrl+X Ctrl+S` is the binding that works in any terminal. Requires v2.1.275 or later |
111| `chat:newline` | Ctrl+J | Insert a newline without submitting |
112| `chat:undo` | Ctrl+\_, Ctrl+Shift+- | Undo last action |
113| `chat:externalEditor` | Ctrl+G, Ctrl+X Ctrl+E | Open in external editor. The [agent view dispatch input](/docs/en/agent-view#keyboard-shortcuts) follows this action's single-keystroke bindings too |
114| `chat:stash` | Ctrl+S | Stash current prompt |
115| `chat:imagePaste` | Ctrl+V (Alt+V on Windows and WSL) | Paste image from clipboard. On WSL, both shortcuts are bound by default |
116116
117117\*On Windows without VT mode (Node \<24.2.0/\<22.17.0, Bun \<1.2.23), defaults to Meta+M.
118118
from line 120
120120
121121Actions available in the `Autocomplete` context:
122122
123| Action | Default | Description |
124| :---------------------- | :------ | :------------------ |
125| `autocomplete:accept` | Tab | Accept suggestion |
126| `autocomplete:dismiss` | Escape | Dismiss menu |
127| `autocomplete:previous` | Up | Previous suggestion |
128| `autocomplete:next` | Down | Next suggestion |
123| Action | Default | Description |
124| :- | :- | :- |
125| `autocomplete:accept` | Tab | Accept suggestion |
126| `autocomplete:dismiss` | Escape | Dismiss menu |
127| `autocomplete:previous` | Up | Previous suggestion |
128| `autocomplete:next` | Down | Next suggestion |
129129
130130### Confirmation actions
131131
132132Actions available in the `Confirmation` context:
133133
134| Action | Default | Description |
135| :---------------------- | :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
136| `confirm:yes` | Enter | Confirm action |
137| `confirm:no` | Escape | Decline action |
138| `confirm:previous` | Up | Previous option |
139| `confirm:next` | Down | Next option |
140| `confirm:nextField` | Tab | Next field |
141| `confirm:previousField` | (unbound) | Previous field |
142| `confirm:toggle` | Space | Toggle selection |
143| `confirm:cycleMode` | Shift+Tab\* | Cycle permission modes. On a file permission prompt, closes an open [comment field](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt); with no field open, selects the option that allows the action for the rest of the session, when the prompt offers that option |
134| Action | Default | Description |
135| :- | :- | :- |
136| `confirm:yes` | Enter | Confirm action |
137| `confirm:no` | Escape | Decline action |
138| `confirm:previous` | Up | Previous option |
139| `confirm:next` | Down | Next option |
140| `confirm:nextField` | Tab | Next field |
141| `confirm:previousField` | (unbound) | Previous field |
142| `confirm:toggle` | Space | Toggle selection |
143| `confirm:cycleMode` | Shift+Tab\* | Cycle permission modes. On a file permission prompt, closes an open [comment field](/docs/en/permissions#add-a-comment-when-you-answer-a-permission-prompt); with no field open, selects the option that allows the action for the rest of the session, when the prompt offers that option |
144144
145145\*On Windows without VT mode (Node \<24.2.0/\<22.17.0, Bun \<1.2.23), defaults to Meta+M.
146146
from line 174
174174
175175Actions available in the `Confirmation` context for permission dialogs:
176176
177| Action | Default | Description |
178| :----------------------- | :-------- | :------------------------------------------------------------------------------------------------------------------ |
177| Action | Default | Description |
178| :- | :- | :- |
179179| `permission:toggleDebug` | (unbound) | Toggle permission debug info. The previous default of Ctrl+D was removed in v2.1.146 because it shadowed `app:exit` |
180180
181181### Transcript actions
182182
183183Actions available in the `Transcript` context:
184184
185| Action | Default | Description |
186| :------------------------- | :---------------- | :---------------------- |
187| `transcript:toggleShowAll` | Ctrl+E | Toggle show all content |
188| `transcript:exit` | q, Ctrl+C, Escape | Exit transcript view |
185| Action | Default | Description |
186| :- | :- | :- |
187| `transcript:toggleShowAll` | Ctrl+E | Toggle show all content |
188| `transcript:exit` | q, Ctrl+C, Escape | Exit transcript view |
189189
190190`transcript:toggleShowAll` applies in the classic renderer only; in [fullscreen rendering](/docs/en/fullscreen), the transcript viewer doesn't offer a show-all toggle.
191191
from line 193
193193
194194Actions available in the `HistorySearch` context:
195195
196| Action | Default | Description |
197| :------------------------- | :---------- | :---------------------------------------- |
198| `historySearch:next` | Ctrl+R | Next match |
199| `historySearch:accept` | Escape, Tab | Accept selection |
200| `historySearch:cancel` | Ctrl+C | Cancel search |
201| `historySearch:execute` | Enter | Execute selected command |
202| `historySearch:cycleScope` | Ctrl+S | Cycle scope: session, project, everywhere |
196| Action | Default | Description |
197| :- | :- | :- |
198| `historySearch:next` | Ctrl+R | Next match |
199| `historySearch:accept` | Escape, Tab | Accept selection |
200| `historySearch:cancel` | Ctrl+C | Cancel search |
201| `historySearch:execute` | Enter | Execute selected command |
202| `historySearch:cycleScope` | Ctrl+S | Cycle scope: session, project, everywhere |
203203
204204The `historySearch:next`, `historySearch:accept`, `historySearch:cancel`, and `historySearch:execute` defaults apply to the inline history search in the classic renderer, which always searches prompts from all projects. `historySearch:cycleScope` takes effect only in [fullscreen rendering](/docs/en/fullscreen), where `Ctrl+R` opens a search dialog instead and `Ctrl+S` cycles its scope. The dialog's other keys are fixed and can't be rebound: `Enter` or `Tab` places the highlighted match in the prompt input and `Esc` cancels.
205205
from line 207
207207
208208Actions available in the `Task` context:
209209
210| Action | Default | Description |
211| :---------------- | :-------------------- | :------------------------------------------------------------------------------- |
210| Action | Default | Description |
211| :- | :- | :- |
212212| `task:background` | Ctrl+B, Ctrl+X Ctrl+B | Background current task. The Ctrl+X Ctrl+B chord avoids the tmux prefix conflict |
213213
214214### Theme actions
215215
216216Actions available in the `ThemePicker` context:
217217
218| Action | Default | Description |
219| :------------------------------- | :------ | :------------------------- |
220| `theme:toggleSyntaxHighlighting` | Ctrl+T | Toggle syntax highlighting |
218| Action | Default | Description |
219| :- | :- | :- |
220| `theme:toggleSyntaxHighlighting` | Ctrl+T | Toggle syntax highlighting |
221221
222222### Help actions
223223
224224Actions available in the `Help` context:
225225
226| Action | Default | Description |
227| :------------- | :------ | :-------------- |
228| `help:dismiss` | Escape | Close help menu |
226| Action | Default | Description |
227| :- | :- | :- |
228| `help:dismiss` | Escape | Close help menu |
229229
230230### Tabs actions
231231
232232Actions available in the `Tabs` context:
233233
234| Action | Default | Description |
235| :-------------- | :-------------- | :----------- |
236| `tabs:next` | Tab, Right | Next tab |
234| Action | Default | Description |
235| :- | :- | :- |
236| `tabs:next` | Tab, Right | Next tab |
237237| `tabs:previous` | Shift+Tab, Left | Previous tab |
238238
239239In a tabbed dialog, `tabs:next` and `tabs:previous` switch tabs while the tab row has focus. In some dialogs, such as `/help` and `/sandbox`, the tab-switching keys also work from inside the tab's content.
from line 244
244244
245245Actions available in the `Attachments` context:
246246
247| Action | Default | Description |
248| :--------------------- | :---------------- | :------------------------- |
249| `attachments:next` | Right | Next attachment |
250| `attachments:previous` | Left | Previous attachment |
251| `attachments:remove` | Backspace, Delete | Remove selected attachment |
252| `attachments:exit` | Down, Escape | Exit attachment navigation |
247| Action | Default | Description |
248| :- | :- | :- |
249| `attachments:next` | Right | Next attachment |
250| `attachments:previous` | Left | Previous attachment |
251| `attachments:remove` | Backspace, Delete | Remove selected attachment |
252| `attachments:exit` | Down, Escape | Exit attachment navigation |
253253
254254### Footer actions
255255
256256Actions available in the `Footer` context:
257257
258| Action | Default | Description |
259| :---------------------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
260| `footer:next` | Right | Next footer item |
261| `footer:previous` | Left | Previous footer item |
262| `footer:up` | Up | Navigate up in footer (deselects at top) |
263| `footer:down` | Down | Navigate down in footer |
264| `footer:openSelected` | Enter | Open selected footer item |
265| `footer:clearSelection` | Escape | Clear footer selection |
266| `footer:dismiss` | (unbound) | Removed in v2.1.281. A `keybindings.json` that still names the action remains valid, and the binding does nothing. Before v2.1.281, Backspace and Delete dismissed the selected artifact link from the footer |
258| Action | Default | Description |
259| :- | :- | :- |
260| `footer:next` | Right | Next footer item |
261| `footer:previous` | Left | Previous footer item |
262| `footer:up` | Up | Navigate up in footer (deselects at top) |
263| `footer:down` | Down | Navigate down in footer |
264| `footer:openSelected` | Enter | Open selected footer item |
265| `footer:clearSelection` | Escape | Clear footer selection |
266| `footer:dismiss` | (unbound) | Removed in v2.1.281. A `keybindings.json` that still names the action remains valid, and the binding does nothing. Before v2.1.281, Backspace and Delete dismissed the selected artifact link from the footer |
267267
268268While a footer item is selected, such as a row in the agent panel below the prompt, `Enter` opens it even when you rebind `Enter` in the `Chat` context to `chat:queueSubmit` or `chat:newline`.
269269
from line 294
294294
295295Actions available in the `DiffDialog` context:
296296
297| Action | Default | Description |
298| :-------------------- | :-------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- |
299| `diff:dismiss` | Escape | Close diff viewer; from the detail view, returns to the file list instead |
300| `diff:previousSource` | Left | Previous diff source |
301| `diff:nextSource` | Right | Next diff source |
302| `diff:previousFile` | Up, K | Previous file in the file list; scroll up one line in the detail view |
303| `diff:nextFile` | Down, J | Next file in the file list; scroll down one line in the detail view |
304| `diff:back` | (unbound) | Go back in diff viewer. Escape performs the back action via `diff:dismiss`. The previous default of Left in the detail view was removed in v2.1.203 |
297| Action | Default | Description |
298| :- | :- | :- |
299| `diff:dismiss` | Escape | Close diff viewer; from the detail view, returns to the file list instead |
300| `diff:previousSource` | Left | Previous diff source |
301| `diff:nextSource` | Right | Next diff source |
302| `diff:previousFile` | Up, K | Previous file in the file list; scroll up one line in the detail view |
303| `diff:nextFile` | Down, J | Next file in the file list; scroll down one line in the detail view |
304| `diff:back` | (unbound) | Go back in diff viewer. Escape performs the back action via `diff:dismiss`. The previous default of Left in the detail view was removed in v2.1.203 |
305305
306306The file list also responds to the [Select actions](#select-actions), through their default keys and your `Select` bindings. `select:previous` and `select:next` move to the previous and next file, and `Enter` opens the selected file's diff through `select:accept`. To change one of those keys for the file list alone, bind the Select action in a `DiffDialog` block.
307307
from line 309
309309
310310The diff detail view also binds pager-style keys to the standard [scroll actions](#scroll-actions). These bindings are part of the `DiffDialog` context and apply only in the detail view; the `Scroll` context defaults listed under [Scroll actions](#scroll-actions) are unchanged.
311311
312| Action | Default | Description |
313| :-------------------- | :------------- | :-------------------------- |
314| `scroll:pageUp` | PageUp | Scroll up half a viewport |
315| `scroll:pageDown` | PageDown | Scroll down half a viewport |
316| `scroll:fullPageUp` | Shift+Space, B | Scroll up a full viewport |
317| `scroll:fullPageDown` | Space | Scroll down a full viewport |
318| `scroll:top` | G, Home | Jump to the top |
319| `scroll:bottom` | Shift+G, End | Jump to the bottom |
312| Action | Default | Description |
313| :- | :- | :- |
314| `scroll:pageUp` | PageUp | Scroll up half a viewport |
315| `scroll:pageDown` | PageDown | Scroll down half a viewport |
316| `scroll:fullPageUp` | Shift+Space, B | Scroll up a full viewport |
317| `scroll:fullPageDown` | Space | Scroll down a full viewport |
318| `scroll:top` | G, Home | Jump to the top |
319| `scroll:bottom` | Shift+G, End | Jump to the bottom |
320320
321321### Diff panel actions
322322
323323Actions for the [diff panel](/docs/en/interactive-mode#diff-panel) that `/diff` opens in fullscreen rendering. `app:cycleDiffBase` is in the `DiffPanel` context, which is active while the panel is open; the others are `Global`. The panel requires Claude Code v2.1.260 or later.
324324
325| Action | Default | Description |
326| :-------------------------- | :------------------- | :------------------------------------------------------------------------ |
327| `app:toggleReplTab` | (unbound) | Open or close the diff panel, the same as running `/diff` |
328| `app:cycleDiffBase` | Ctrl+X B | Cycle the panel's comparison base: this session, uncommitted, then branch |
329| `app:diffFileListUp` | Ctrl+Up, Meta+Up | Scroll the panel's file list up when it overflows |
330| `app:diffFileListDown` | Ctrl+Down, Meta+Down | Scroll the panel's file list down when it overflows |
331| `app:toggleDiffNoiseFilter` | (unbound) | Show or hide test and generated files in the panel |
332| `app:toggleDiffPreSession` | (unbound) | Expand or collapse the changes from before this session |
325| Action | Default | Description |
326| :- | :- | :- |
327| `app:toggleReplTab` | (unbound) | Open or close the diff panel, the same as running `/diff` |
328| `app:cycleDiffBase` | Ctrl+X B | Cycle the panel's comparison base: this session, uncommitted, then branch |
329| `app:diffFileListUp` | Ctrl+Up, Meta+Up | Scroll the panel's file list up when it overflows |
330| `app:diffFileListDown` | Ctrl+Down, Meta+Down | Scroll the panel's file list down when it overflows |
331| `app:toggleDiffNoiseFilter` | (unbound) | Show or hide test and generated files in the panel |
332| `app:toggleDiffPreSession` | (unbound) | Expand or collapse the changes from before this session |
333333
334334### Model picker actions
335335
336336Actions available in the `ModelPicker` context:
337337
338| Action | Default | Description |
339| :---------------------------- | :------ | :------------------------------------------- |
340| `modelPicker:decreaseEffort` | Left | Decrease effort level |
341| `modelPicker:increaseEffort` | Right | Increase effort level |
342| `modelPicker:thisSessionOnly` | s | Apply highlighted model to this session only |
338| Action | Default | Description |
339| :- | :- | :- |
340| `modelPicker:decreaseEffort` | Left | Decrease effort level |
341| `modelPicker:increaseEffort` | Right | Increase effort level |
342| `modelPicker:thisSessionOnly` | s | Apply highlighted model to this session only |
343343
344344### Effort slider actions
345345
346Actions available in the `EffortSlider` context, the slider that opens when you run `/effort` with no arguments. The slider's Left, Right, Enter, and Escape keys can't be rebound.
347
348| Action | Default | Description |
349| :----------------------------- | :------ | :---------------------------------------------------------------------------------------------------------------------- |
350| `effortSlider:thisSessionOnly` | s | Apply the focused [effort level](/docs/en/model-config#adjust-effort-level) to this session only. Requires v2.1.257 or later |
346Actions available in the `EffortSlider` context, the slider that opens when you run `/effort` with no arguments. The slider's Enter and Escape keys can't be rebound.
347
348| Action | Default | Description |
349| :- | :- | :- |
350| `effortSlider:decreaseEffort` | Left | Move the slider to the next lower effort level. Requires v2.1.284 or later |
351| `effortSlider:increaseEffort` | Right | Move the slider to the next higher effort level. Requires v2.1.284 or later |
352| `effortSlider:toggleUltracode` | Tab | Turn [ultracode](/docs/en/workflows#let-claude-decide-with-ultracode) on or off for this session, when the slider [offers it](/docs/en/model-config#when-ultracode-is-available). Requires v2.1.284 or later |
353| `effortSlider:thisSessionOnly` | s | Apply the focused [effort level](/docs/en/model-config#adjust-effort-level) to this session only. Requires v2.1.257 or later |
351354
352355### Select actions
353356
354357Actions available in the `Select` context:
355358
356| Action | Default | Description |
357| :---------------- | :-------------- | :---------------------------- |
358| `select:next` | Down, J, Ctrl+N | Next option |
359| `select:previous` | Up, K, Ctrl+P | Previous option |
360| `select:pageUp` | PageUp | Move up one page of options |
361| `select:pageDown` | PageDown | Move down one page of options |
362| `select:first` | Home | First option |
363| `select:last` | End | Last option |
364| `select:accept` | Enter | Accept selection |
365| `select:cancel` | Escape | Cancel selection |
359| Action | Default | Description |
360| :- | :- | :- |
361| `select:next` | Down, J, Ctrl+N | Next option |
362| `select:previous` | Up, K, Ctrl+P | Previous option |
363| `select:pageUp` | PageUp | Move up one page of options |
364| `select:pageDown` | PageDown | Move down one page of options |
365| `select:first` | Home | First option |
366| `select:last` | End | Last option |
367| `select:accept` | Enter | Accept selection |
368| `select:cancel` | Escape | Cancel selection |
366369
367370In list panels such as `/skills` and `/mcp`, Claude Code applies your `select:pageUp`, `select:pageDown`, `select:first`, and `select:last` bindings. In most other lists, such as the `/model` picker, your `select:first` and `select:last` bindings apply. PageUp and PageDown page through the options in those lists regardless of your bindings.
368371
from line 375
372375
373376Actions available in the `Plugin` context:
374377
375| Action | Default | Description |
376| :---------------- | :------ | :------------------------------------------------------------------------- |
377| `plugin:toggle` | Space | Toggle plugin selection |
378| `plugin:install` | I | Install selected plugins |
379| `plugin:favorite` | F | Favorite the selected plugin so it sorts near the top of the Installed tab |
378| Action | Default | Description |
379| :- | :- | :- |
380| `plugin:toggle` | Space | Toggle plugin selection |
381| `plugin:install` | I | Install selected plugins |
382| `plugin:favorite` | F | Favorite the selected plugin so it sorts near the top of the Installed tab |
380383
381384### Settings actions
382385
383386Actions available in the `Settings` context. The `select:accept` and `confirm:no` actions are reused from the [Select](#select-actions) and [Confirmation](#confirmation-actions) contexts with Settings-specific behavior: changes apply to each setting as soon as you change it, so Escape closes the panel with your changes saved rather than declining.
384387
385| Action | Default | Description |
386| :---------------- | :----------- | :---------------------------------------------- |
387| `settings:search` | / | Enter search mode |
388| `settings:retry` | R | Retry loading usage data on error |
389| `select:accept` | Enter, Space | Change the selected setting or open its submenu |
390| `confirm:no` | Escape | Close the panel. Changes are already saved |
388| Action | Default | Description |
389| :- | :- | :- |
390| `settings:search` | / | Enter search mode |
391| `settings:retry` | R | Retry loading usage data on error |
392| `select:accept` | Enter, Space | Change the selected setting or open its submenu |
393| `confirm:no` | Escape | Close the panel. Changes are already saved |
391394
392395### Agents actions
393396
394397Actions available in the `Agents` context, which applies in [agent view](/docs/en/agent-view), opened with `claude agents`. Requires v2.1.257 or later.
395398
396| Action | Default | Description |
397| :------------------ | :------ | :-------------------------------------------------------------------------------------- |
398| `agents:switchView` | Ctrl+S | Switch [session grouping](/docs/en/agent-view#organize-the-list) between state and directory |
399| `agents:togglePin` | Ctrl+T | [Pin or unpin](/docs/en/agent-view#organize-the-list) the selected session |
399| Action | Default | Description |
400| :- | :- | :- |
401| `agents:switchView` | Ctrl+S | Switch [session grouping](/docs/en/agent-view#organize-the-list) between state and directory |
402| `agents:togglePin` | Ctrl+T | [Pin or unpin](/docs/en/agent-view#organize-the-list) the selected session |
400403
401404While agent view is open, Claude Code uses the `Agents` binding for any key the `Agents` context binds, and it ignores a `Chat` or `Global` binding on the same key. For example, pressing Ctrl+S in agent view switches the session grouping rather than triggering the default `chat:stash`.
402405
from line 411
408411
409412Actions available in the `Chat` context when [voice dictation](/docs/en/voice-dictation) is enabled:
410413
411| Action | Default | Description |
412| :----------------- | :------ | :------------------------------------------------------- |
413| `voice:pushToTalk` | Space | Dictate a prompt. Hold or tap depending on `/voice` mode |
414| Action | Default | Description |
415| :- | :- | :- |
416| `voice:pushToTalk` | Space | Dictate a prompt. Hold or tap depending on `/voice` mode |
414417
415418### Scroll actions
416419
417420Actions available in the `Scroll` context when [fullscreen rendering](/docs/en/fullscreen) is enabled:
418421
419| Action | Default | Description |
420| :-------------------------- | :------------------- | :-------------------------------------------------------------------------------------------------------- |
421| `scroll:lineUp` | `wheelup` | Scroll up one line. Mouse wheel scrolling triggers this action |
422| `scroll:lineDown` | `wheeldown` | Scroll down one line. Mouse wheel scrolling triggers this action |
423| `scroll:pageUp` | PageUp | Scroll up half the viewport height |
424| `scroll:pageDown` | PageDown | Scroll down half the viewport height |
425| `scroll:top` | Ctrl+Home | Jump to the start of the conversation |
426| `scroll:bottom` | Ctrl+End | Jump to the latest message and re-enable auto-follow |
427| `scroll:halfPageUp` | (unbound) | Scroll up half the viewport height. Same behavior as `scroll:pageUp`, provided for vi-style rebinds |
428| `scroll:halfPageDown` | (unbound) | Scroll down half the viewport height. Same behavior as `scroll:pageDown`, provided for vi-style rebinds |
429| `scroll:fullPageUp` | (unbound) | Scroll up the full viewport height |
430| `scroll:fullPageDown` | (unbound) | Scroll down the full viewport height |
431| `selection:copy` | Ctrl+Shift+C / Cmd+C | Copy the selected text to the clipboard |
432| `selection:clear` | (unbound) | Clear the active text selection. Requires v2.1.234 or later |
433| `selection:extendLeft` | Shift+Left | Extend the active selection one column left |
434| `selection:extendRight` | Shift+Right | Extend the active selection one column right |
435| `selection:extendUp` | Shift+Up | Extend the active selection one row up. Scrolls the viewport when the selection reaches the top edge |
436| `selection:extendDown` | Shift+Down | Extend the active selection one row down. Scrolls the viewport when the selection reaches the bottom edge |
437| `selection:extendLineStart` | Shift+Home | Extend the active selection to the start of the line |
438| `selection:extendLineEnd` | Shift+End | Extend the active selection to the end of the line |
422| Action | Default | Description |
423| :- | :- | :- |
424| `scroll:lineUp` | `wheelup` | Scroll up one line. Mouse wheel scrolling triggers this action |
425| `scroll:lineDown` | `wheeldown` | Scroll down one line. Mouse wheel scrolling triggers this action |
426| `scroll:pageUp` | PageUp | Scroll up half the viewport height |
427| `scroll:pageDown` | PageDown | Scroll down half the viewport height |
428| `scroll:top` | Ctrl+Home | Jump to the start of the conversation |
429| `scroll:bottom` | Ctrl+End | Jump to the latest message and re-enable auto-follow |
430| `scroll:halfPageUp` | (unbound) | Scroll up half the viewport height. Same behavior as `scroll:pageUp`, provided for vi-style rebinds |
431| `scroll:halfPageDown` | (unbound) | Scroll down half the viewport height. Same behavior as `scroll:pageDown`, provided for vi-style rebinds |
432| `scroll:fullPageUp` | (unbound) | Scroll up the full viewport height |
433| `scroll:fullPageDown` | (unbound) | Scroll down the full viewport height |
434| `selection:copy` | Ctrl+Shift+C / Cmd+C | Copy the selected text to the clipboard |
435| `selection:clear` | (unbound) | Clear the active text selection. Requires v2.1.234 or later |
436| `selection:extendLeft` | Shift+Left | Extend the active selection one column left |
437| `selection:extendRight` | Shift+Right | Extend the active selection one column right |
438| `selection:extendUp` | Shift+Up | Extend the active selection one row up. Scrolls the viewport when the selection reaches the top edge |
439| `selection:extendDown` | Shift+Down | Extend the active selection one row down. Scrolls the viewport when the selection reaches the bottom edge |
440| `selection:extendLineStart` | Shift+Home | Extend the active selection to the start of the line |
441| `selection:extendLineEnd` | Shift+End | Extend the active selection to the end of the line |
439442
440443## Keystroke syntax
441444
from line 559
556559
557560These shortcuts cannot be rebound:
558561
559| Shortcut | Reason |
560| :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
561| Ctrl+C | Hardcoded interrupt/cancel |
562| Ctrl+D | Hardcoded exit |
563| Ctrl+M | Claude Code always receives it as Enter |
564| Ctrl+\[ | Claude Code always receives it as Escape. In terminals that use the Kitty keyboard protocol, this requires v2.1.242 or later |
565| Ctrl+I | Claude Code always receives it as Tab |
566| Ctrl+H | Sends the ASCII backspace byte. [How Claude Code reads it on Windows](/docs/en/terminal-config#fix-backspace-deleting-a-whole-word-on-windows) depends on your terminal and the [`CLAUDE_CODE_BS_AS_CTRL_BACKSPACE`](/docs/en/env-vars) environment variable |
567| Caps Lock | Not delivered to terminal applications |
562| Shortcut | Reason |
563| :- | :- |
564| Ctrl+C | Hardcoded interrupt/cancel |
565| Ctrl+D | Hardcoded exit |
566| Ctrl+M | Claude Code always receives it as Enter |
567| Ctrl+\[ | Claude Code always receives it as Escape. In terminals that use the Kitty keyboard protocol, this requires v2.1.242 or later |
568| Ctrl+I | Claude Code always receives it as Tab |
569| Ctrl+H | Sends the ASCII backspace byte. [How Claude Code reads it on Windows](/docs/en/terminal-config#fix-backspace-deleting-a-whole-word-on-windows) depends on your terminal and the [`CLAUDE_CODE_BS_AS_CTRL_BACKSPACE`](/docs/en/env-vars) environment variable |
570| Caps Lock | Not delivered to terminal applications |
568571
569572## Terminal conflicts
570573
571574Some shortcuts may conflict with terminal multiplexers:
572575
573| Shortcut | Conflict |
574| :------- | :-------------------------------- |
575| Ctrl+B | tmux prefix (press twice to send) |
576| Ctrl+A | GNU screen prefix |
577| Ctrl+Z | Unix process suspend (SIGTSTP) |
576| Shortcut | Conflict |
577| :- | :- |
578| Ctrl+B | tmux prefix (press twice to send) |
579| Ctrl+A | GNU screen prefix |
580| Ctrl+Z | Unix process suspend (SIGTSTP) |
578581
579582## Text fields
580583
581584
large-codebases Changed · +22 / -22 lines
from line 14
1414
1515Each setting below is independent. They layer rather than replace each other, so apply whichever fit your repository. [Choose where to start Claude](#choose-where-to-start-claude) determines where your settings files live, so read it first. [Put it together](#put-it-together) shows all of them combined.
1616
17| I want to | Use |
18| :-------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------- |
19| Load only the conventions for the code you touch, instead of one root file covering every subsystem | Per-directory [CLAUDE.md files](#layer-claude-md-files-by-directory) |
20| Exclude CLAUDE.md files for packages you never work in | [`claudeMdExcludes`](#exclude-irrelevant-claude-md-files) |
21| Block Claude from opening build output, generated code, and vendored dependencies | [`Read` deny rules](#block-reads-of-generated-and-vendored-code) in `permissions.deny` |
22| Find a symbol's definition or callers through the language server instead of scanning files | A [code intelligence plugin](#reduce-file-reads-with-code-intelligence) |
23| Check out only the directories a task needs when Claude creates a worktree | [`worktree.sparsePaths`](#check-out-only-the-directories-you-need) |
24| Read and edit a sibling package or another repository from the same session | [`--add-dir`](#grant-access-across-packages-or-repositories) or `additionalDirectories` |
25| Give Claude procedures specific to one area that load only when relevant | Per-directory [skills](#add-per-directory-skills) |
26| Replace many per-directory CLAUDE.md files with one set of conventions everyone installs | A [plugin](#centralize-conventions-when-layering-stops-scaling) in an internal marketplace |
17| I want to | Use |
18| :- | :- |
19| Load only the conventions for the code you touch, instead of one root file covering every subsystem | Per-directory [CLAUDE.md files](#layer-claude-md-files-by-directory) |
20| Exclude CLAUDE.md files for packages you never work in | [`claudeMdExcludes`](#exclude-irrelevant-claude-md-files) |
21| Block Claude from opening build output, generated code, and vendored dependencies | [`Read` deny rules](#block-reads-of-generated-and-vendored-code) in `permissions.deny` |
22| Find a symbol's definition or callers through the language server instead of scanning files | A [code intelligence plugin](#reduce-file-reads-with-code-intelligence) |
23| Check out only the directories a task needs when Claude creates a worktree | [`worktree.sparsePaths`](#check-out-only-the-directories-you-need) |
24| Read and edit a sibling package or another repository from the same session | [`--add-dir`](#grant-access-across-packages-or-repositories) or `additionalDirectories` |
25| Give Claude procedures specific to one area that load only when relevant | Per-directory [skills](#add-per-directory-skills) |
26| Replace many per-directory CLAUDE.md files with one set of conventions everyone installs | A [plugin](#centralize-conventions-when-layering-stops-scaling) in an internal marketplace |
2727
2828<Tip>
2929 For workflow techniques that keep context small in any repository, such as [running exploration in a subagent](/docs/en/best-practices#use-subagents-for-investigation) so file reads stay out of the main conversation, see [Best practices for Claude Code](/docs/en/best-practices). To roll out a baseline configuration to every developer in your organization, see [Set up Claude Code for your organization](/docs/en/admin-setup).
from line 54
5454
5555Where you launch `claude` determines which files Claude can read and edit without an additional permission grant, which CLAUDE.md files load into context at startup, and which project settings apply.
5656
57| Start from | File access | CLAUDE.md loaded at launch | Use when |
58| :-------------- | :-------------------------------------- | :------------------------------------------------------------------- | :----------------------------------------- |
59| Repository root | Every file | Root only; subdirectory files load on demand when Claude reads there | Tasks span multiple packages or subsystems |
60| A subdirectory | That subtree only, until you grant more | That directory's plus every ancestor's | Work is scoped to one package or subsystem |
57| Start from | File access | CLAUDE.md loaded at launch | Use when |
58| :- | :- | :- | :- |
59| Repository root | Every file | Root only; subdirectory files load on demand when Claude reads there | Tasks span multiple packages or subsystems |
60| A subdirectory | That subtree only, until you grant more | That directory's plus every ancestor's | Work is scoped to one package or subsystem |
6161
6262Project settings in `.claude/settings.json` aren't inherited from parent directories the way CLAUDE.md files are. For which directory's `.claude/settings.json` a session reads, see [where Claude Code looks for each file](/docs/en/settings#where-claude-code-looks-for-each-file).
6363
from line 106
106106
107107Per-directory `CLAUDE.md` files and [path-scoped rules](/docs/en/memory#path-specific-rules) under `.claude/rules/` both let you target instructions to part of the tree. They differ in where the file lives and when it loads.
108108
109| Approach | File location | Loads when | Use when |
110| :----------------------------------- | :--------------------------------------- | :-------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------- |
111| Per-directory `CLAUDE.md` | Inside the directory, alongside its code | At launch when started from that directory, or on demand when Claude reads a file there | Directory owners maintain their own conventions; instructions are versioned with the code |
112| Path-scoped rule in `.claude/rules/` | Central `.claude/` at the repo root | When Claude works with a file matching the rule's `paths:` glob | You want all conventions in one place, or the same rule applies to many scattered paths |
109| Approach | File location | Loads when | Use when |
110| :- | :- | :- | :- |
111| Per-directory `CLAUDE.md` | Inside the directory, alongside its code | At launch when started from that directory, or on demand when Claude reads a file there | Directory owners maintain their own conventions; instructions are versioned with the code |
112| Path-scoped rule in `.claude/rules/` | Central `.claude/` at the repo root | When Claude works with a file matching the rule's `paths:` glob | You want all conventions in one place, or the same rule applies to many scattered paths |
113113
114114For a comparison that also covers skills, see [Compare similar features](/docs/en/features-overview#compare-similar-features).
115115
from line 285
285285
286286However you add a directory, Claude can read and edit files in it. Whether the directory's CLAUDE.md, `.claude/rules/` files, and skills also load depends on how you added it:
287287
288| Added with | Loads CLAUDE.md and rules | Loads skills |
289| :------------------------------------- | :--------------------------------------- | :----------- |
290| `additionalDirectories` setting | Never | Never |
291| `--add-dir` flag or `/add-dir` command | Only with the environment variable below | Yes |
288| Added with | Loads CLAUDE.md and rules | Loads skills |
289| :- | :- | :- |
290| `additionalDirectories` setting | Never | Never |
291| `--add-dir` flag or `/add-dir` command | Only with the environment variable below | Yes |
292292
293293To load CLAUDE.md and rules files from a directory added with `--add-dir` or `/add-dir`, set the `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD` environment variable:
294294
llm-gateway-connect Changed · +25 / -25 lines
from line 53
5353
5454To authenticate Claude Code to the gateway, set your credential in an environment variable. Which variable depends on what your gateway team told you:
5555
56| Set the credential in | Use when |
57| :------------------------------------------------------ | :-------------------------------------------------------------- |
58| `ANTHROPIC_AUTH_TOKEN` | Your gateway team said "bearer token" or "Authorization header" |
59| `ANTHROPIC_API_KEY` | Your gateway team said "API key" or "x-api-key" |
60| [`apiKeyHelper`](#rotate-credentials-with-apikeyhelper) | The credential rotates or comes from a vault |
56| Set the credential in | Use when |
57| :- | :- |
58| `ANTHROPIC_AUTH_TOKEN` | Your gateway team said "bearer token" or "Authorization header" |
59| `ANTHROPIC_API_KEY` | Your gateway team said "API key" or "x-api-key" |
60| [`apiKeyHelper`](#rotate-credentials-with-apikeyhelper) | The credential rotates or comes from a vault |
6161
6262If you weren't told which kind, use `ANTHROPIC_AUTH_TOKEN`; the [verification request](#verify-the-connection) below shows how to tell if you need to switch.
6363
from line 517
517517
518518These are the most common errors when running Claude Code through a gateway, with the gateway-side cause and the fix:
519519
520| Error | Cause | Fix |
521| :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
522| A startup warning naming two credential sources and ending in `auth may not work as expected`. Older versions show `Auth conflict: Both a token (SOURCE) and an API key (SOURCE) are set` instead. | A gateway credential and a saved login are both active; the variable is used for requests, but the stale login can cause unexpected auth behavior | Unset the variable to use the saved login, or run `/logout` to use the gateway credential |
523| `401` errors naming an invalid or unrecognized token | The credential isn't one the gateway issued, or it's in a header the gateway doesn't read | Confirm the variable matches your credential kind in the [credential table](#set-the-credential-variable), and regenerate the key at the gateway if it was revoked |
524| `Your apiKeyHelper script is failing`, or `apiKeyHelper failed:` on stderr in non-interactive mode | The command in the [`apiKeyHelper`](/docs/en/settings-reference#apikeyhelper) setting didn't produce a usable key, so requests carry a placeholder key | Run the command directly to see why it fails, and re-authenticate with your credential provider if it reports an expired session; see [the error reference](/docs/en/errors#your-apikeyhelper-script-is-failing) |
525| `Connection refused — a firewall or proxy may be blocking it (ConnectionRefused)` when nothing answers at the address, or `Can't reach the API server — check your internet or DNS (ENOTFOUND)` when the hostname doesn't resolve, often after a silent pause while Claude Code [retries with backoff](/docs/en/errors#automatic-retries). The code in parentheses varies; [Unable to connect to API](/docs/en/errors#unable-to-connect-to-api) covers the code spellings and the earlier wording | Nothing answered at the base URL: the address is wrong, or a VPN or firewall blocks the path to the gateway | Run the [curl test above](#verify-the-connection), which fails immediately with the same cause, and confirm the URL and network path with your gateway team |
526| `API returned an empty or malformed response (HTTP 200)` | The gateway or an intermediate proxy returned a non-API response, often an HTML error or login page | Test with the [curl request above](#verify-the-connection); fix the gateway route that answers with something other than a Claude API response. [The error reference](/docs/en/errors#api-returned-an-empty-or-malformed-response) explains the detail the message reports |
527| `400` errors naming `context_management`, `Extra inputs are not permitted`, or other unrecognized fields | The gateway forwards requests to an upstream that rejects fields Claude Code sends to Anthropic-format endpoints | Set `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`, which suppresses most pre-release fields; see [feature pass-through](/docs/en/llm-gateway-protocol#feature-pass-through). Some betas aren't gated by this flag; for those, set the matching `CLAUDE_CODE_USE_*` provider variable so Claude Code sends only what that provider accepts |
528| `400` errors naming `thinking` or `adaptive`, such as `Input tag 'adaptive' found` | The upstream model build doesn't accept adaptive reasoning, which Claude Code requests for Claude 4.6 and later models | Upgrade the gateway's upstream. On Opus 4.6 and Sonnet 4.6, `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1` works instead. The [model configuration](/docs/en/model-config) capability variables apply only to the provider configurations, such as `CLAUDE_CODE_USE_BEDROCK` and `CLAUDE_CODE_USE_VERTEX`, not behind an `ANTHROPIC_BASE_URL` gateway |
529| `400` errors stating a context or token limit in the gateway's own words, such as `ContextWindowExceededError` or `prompt token count of N exceeds the limit of M` | The gateway enforces a smaller context than the model's native window and rewrites the upstream error, so Claude Code doesn't recognize it as a [too-long error](/docs/en/errors#prompt-is-too-long) and doesn't compact and retry automatically | Run `/compact` to recover the session. To prevent it, set `CLAUDE_CODE_AUTO_COMPACT_WINDOW` to the gateway's limit; Claude Code clamps the value to at least 100,000 tokens and at most the model's context window, so you can't match a gateway limit below 100,000, and `/compact` remains the recovery there. Also set `CLAUDE_CODE_MAX_OUTPUT_TOKENS` below the gateway model's output limit |
530| `400` errors on every request, in the gateway's own words rejecting a tool's input schema or its `pattern`, on Claude Code v2.1.265 through v2.1.267 | In a gradual rollout on those versions, the [Artifact tool](/docs/en/artifacts#availability) schema carries a regular expression with `\p{...}` Unicode character classes. The Anthropic API accepts it, but a gateway or upstream that checks each tool schema's `pattern` with its own regex engine rejects the whole request | Update to v2.1.268 or later, which doesn't send the regular expression. On an affected version, [turn artifacts off](/docs/en/artifacts#disable-artifacts), which removes the tool and its schema from requests |
531| `400` errors on every request, in the gateway's own words rejecting an unrecognized tool type, such as `Input tag 'advisor_20260301'`, on Claude Code v2.1.275 | In a gradual rollout on that version, requests carry an [advisor tool](/docs/en/advisor) entry even with the advisor off. The Anthropic API accepts it, but a gateway or upstream that validates tool types rejects the whole request; one that [forwards request body fields unchanged](/docs/en/llm-gateway-protocol#forward-as-open-lists) passes it through unaffected. The entry is a declaration that carries no conversation content | Update to v2.1.276 or later, which doesn't send the entry behind an `ANTHROPIC_BASE_URL` gateway unless you turn the advisor on. On v2.1.275, set [`CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1`](/docs/en/env-vars), which removes the entry from requests |
532| Models missing from the `/model` picker | Gateway model names aren't in Claude Code's built-in list, or Claude Code is showing a [`modelPicker`](/docs/en/settings-reference#modelpicker) lineup that replaces the built-in options | Enable [gateway model discovery](#add-gateway-models-to-the-model-picker) or add names with the [model configuration](/docs/en/model-config) variables. If Claude Code shows a replacing `modelPicker` lineup, add the gateway models to it, or ask your administrator to add them when managed settings supply it |
533| `/fast` reports `Fast mode unavailable due to network connectivity issues` while inference requests work | The [fast mode](/docs/en/fast-mode) availability check goes directly to `api.anthropic.com` and doesn't follow `ANTHROPIC_BASE_URL`, so blocked direct egress fails the check. The same message appears on an open network when the check presents a gateway-issued key from `ANTHROPIC_API_KEY` or an `apiKeyHelper` and Anthropic rejects it | Allowlist `api.anthropic.com` if egress is blocked, or set a skip variable; for a rejected gateway key only the skip variables help. See [use fast mode behind proxies and LLM gateways](/docs/en/fast-mode#use-fast-mode-behind-proxies-and-llm-gateways) |
534| `/fast` reports `Fast mode has been disabled by your organization` in a session authenticated with `ANTHROPIC_AUTH_TOKEN`, even though the organization has fast mode enabled | The availability check requires a claude.ai login or an Anthropic API key; with only a bearer token, Claude Code treats fast mode as disabled without sending the check | Set `CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK=1`; see [use fast mode behind proxies and LLM gateways](/docs/en/fast-mode#use-fast-mode-behind-proxies-and-llm-gateways) |
535| Claude Code asks you to log in even though the [curl test](#verify-the-connection) succeeds | The CLI has no credential of its own: a reachable base URL isn't one, and in an interactive session an `env` block in a project's `.claude/settings.json` or `.claude/settings.local.json` applies only after the first-run wizard and [trust prompt](/docs/en/permissions#what-runs-before-you-trust-a-folder) | Set `ANTHROPIC_AUTH_TOKEN` somewhere Claude Code reads before first-run setup: a shell export, the `env` block in `~/.claude/settings.json`, or managed settings |
536| `ANTHROPIC_API_KEY` is set but ignored, with no prompt | The key needs a one-time approval in interactive sessions, and a previously declined key is ignored without asking again | Enable it under `/config` with the `Use custom API key` option |
537| `This machine's managed settings require a first-party login`, or [`Administrator policy requires a Cloud gateway sign-in`](/docs/en/errors#administrator-policy-requires-a-cloud-gateway-sign-in) when managed settings set `forceLoginMethod` to `"gateway"` or also set `forceLoginGatewayUrl` | Managed settings include `forceLoginMethod` or `forceLoginOrgUUID`, which cannot coexist with `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, or `apiKeyHelper` | Your administrator must remove `forceLoginMethod`, `forceLoginOrgUUID`, and `forceLoginGatewayUrl` from managed settings to use gateway credentials, or remove the gateway credential and use the sign-in the managed settings require. The two cannot be combined |
538| `403` with an HTML body such as `403 Forbidden`, when the gateway's own logs show no request received | A web application firewall or reverse proxy in front of the gateway blocked the request body before it reached the gateway. Claude Code prompts include XML-style tags and source code that match cross-site-scripting body rules, so a short curl test passes while a real session doesn't | Exempt the gateway's `/v1/messages` path from request-body inspection. On AWS WAF this is the `CrossSiteScripting_Body` managed rule; on nginx with ModSecurity it is the equivalent OWASP CRS body rules |
539| Certificate or TLS errors such as `SSL certificate verification failed` or `Self-signed certificate detected`, when the [curl test](#verify-the-connection) succeeds | Claude Code's runtime isn't trusting the same certificate authority that `curl` uses. Common behind corporate TLS-inspection proxies | Set `NODE_EXTRA_CA_CERTS` to the CA bundle path; see [CA certificate store](/docs/en/network-config#ca-certificate-store) |
520| Error | Cause | Fix |
521| :- | :- | :- |
522| A startup warning naming two credential sources and ending in `auth may not work as expected`. Older versions show `Auth conflict: Both a token (SOURCE) and an API key (SOURCE) are set` instead. | A gateway credential and a saved login are both active; the variable is used for requests, but the stale login can cause unexpected auth behavior | Unset the variable to use the saved login, or run `/logout` to use the gateway credential |
523| `401` errors naming an invalid or unrecognized token | The credential isn't one the gateway issued, or it's in a header the gateway doesn't read | Confirm the variable matches your credential kind in the [credential table](#set-the-credential-variable), and regenerate the key at the gateway if it was revoked |
524| `Your apiKeyHelper script is failing`, or `apiKeyHelper failed:` on stderr in non-interactive mode | The command in the [`apiKeyHelper`](/docs/en/settings-reference#apikeyhelper) setting didn't produce a usable key, so requests carry a placeholder key | Run the command directly to see why it fails, and re-authenticate with your credential provider if it reports an expired session; see [the error reference](/docs/en/errors#your-apikeyhelper-script-is-failing) |
525| `Connection refused — a firewall or proxy may be blocking it (ConnectionRefused)` when nothing answers at the address, or `Can't reach the API server — check your internet or DNS (ENOTFOUND)` when the hostname doesn't resolve, often after a silent pause while Claude Code [retries with backoff](/docs/en/errors#automatic-retries). The code in parentheses varies; [Unable to connect to API](/docs/en/errors#unable-to-connect-to-api) covers the code spellings and the earlier wording | Nothing answered at the base URL: the address is wrong, or a VPN or firewall blocks the path to the gateway | Run the [curl test above](#verify-the-connection), which fails immediately with the same cause, and confirm the URL and network path with your gateway team |
526| `API returned an empty or malformed response (HTTP 200)` | The gateway or an intermediate proxy returned a non-API response, often an HTML error or login page | Test with the [curl request above](#verify-the-connection); fix the gateway route that answers with something other than a Claude API response. [The error reference](/docs/en/errors#api-returned-an-empty-or-malformed-response) explains the detail the message reports |
527| `400` errors naming `context_management`, `Extra inputs are not permitted`, or other unrecognized fields | The gateway forwards requests to an upstream that rejects fields Claude Code sends to Anthropic-format endpoints | Set `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`, which suppresses most pre-release fields; see [feature pass-through](/docs/en/llm-gateway-protocol#feature-pass-through). Some betas aren't gated by this flag; for those, set the matching `CLAUDE_CODE_USE_*` provider variable so Claude Code sends only what that provider accepts |
528| `400` errors naming `thinking` or `adaptive`, such as `Input tag 'adaptive' found` | The upstream model build doesn't accept adaptive reasoning, which Claude Code requests for Claude 4.6 and later models | Upgrade the gateway's upstream. On Opus 4.6 and Sonnet 4.6, `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1` works instead. The [model configuration](/docs/en/model-config) capability variables apply only to the provider configurations, such as `CLAUDE_CODE_USE_BEDROCK` and `CLAUDE_CODE_USE_VERTEX`, not behind an `ANTHROPIC_BASE_URL` gateway |
529| `400` errors stating a context or token limit in the gateway's own words, such as `ContextWindowExceededError` or `prompt token count of N exceeds the limit of M` | The gateway enforces a smaller context than the model's native window and rewrites the upstream error, so Claude Code doesn't recognize it as a [too-long error](/docs/en/errors#prompt-is-too-long) and doesn't compact and retry automatically | Run `/compact` to recover the session. To prevent it, set `CLAUDE_CODE_AUTO_COMPACT_WINDOW` to the gateway's limit; Claude Code clamps the value to at least 100,000 tokens and at most the model's context window, so you can't match a gateway limit below 100,000, and `/compact` remains the recovery there. Also set `CLAUDE_CODE_MAX_OUTPUT_TOKENS` below the gateway model's output limit |
530| `400` errors on every request, in the gateway's own words rejecting a tool's input schema or its `pattern`, on Claude Code v2.1.265 through v2.1.267 | In a gradual rollout on those versions, the [Artifact tool](/docs/en/artifacts#availability) schema carries a regular expression with `\p{...}` Unicode character classes. The Anthropic API accepts it, but a gateway or upstream that checks each tool schema's `pattern` with its own regex engine rejects the whole request | Update to v2.1.268 or later, which doesn't send the regular expression. On an affected version, [turn artifacts off](/docs/en/artifacts#disable-artifacts), which removes the tool and its schema from requests |
531| `400` errors on every request, in the gateway's own words rejecting an unrecognized tool type, such as `Input tag 'advisor_20260301'`, on Claude Code v2.1.275 | In a gradual rollout on that version, requests carry an [advisor tool](/docs/en/advisor) entry even with the advisor off. The Anthropic API accepts it, but a gateway or upstream that validates tool types rejects the whole request; one that [forwards request body fields unchanged](/docs/en/llm-gateway-protocol#forward-as-open-lists) passes it through unaffected. The entry is a declaration that carries no conversation content | Update to v2.1.276 or later, which doesn't send the entry behind an `ANTHROPIC_BASE_URL` gateway unless you turn the advisor on. On v2.1.275, set [`CLAUDE_CODE_DISABLE_ADVISOR_TOOL=1`](/docs/en/env-vars), which removes the entry from requests |
532| Models missing from the `/model` picker | Gateway model names aren't in Claude Code's built-in list, or Claude Code is showing a [`modelPicker`](/docs/en/settings-reference#modelpicker) lineup that replaces the built-in options | Enable [gateway model discovery](#add-gateway-models-to-the-model-picker) or add names with the [model configuration](/docs/en/model-config) variables. If Claude Code shows a replacing `modelPicker` lineup, add the gateway models to it, or ask your administrator to add them when managed settings supply it |
533| `/fast` reports `Fast mode unavailable due to network connectivity issues` while inference requests work | The [fast mode](/docs/en/fast-mode) availability check goes directly to `api.anthropic.com` and doesn't follow `ANTHROPIC_BASE_URL`, so blocked direct egress fails the check. The same message appears on an open network when the check presents a gateway-issued key from `ANTHROPIC_API_KEY` or an `apiKeyHelper` and Anthropic rejects it | Allowlist `api.anthropic.com` if egress is blocked, or set a skip variable; for a rejected gateway key only the skip variables help. See [use fast mode behind proxies and LLM gateways](/docs/en/fast-mode#use-fast-mode-behind-proxies-and-llm-gateways) |
534| `/fast` reports `Fast mode has been disabled by your organization` in a session authenticated with `ANTHROPIC_AUTH_TOKEN`, even though the organization has fast mode enabled | The availability check requires a claude.ai login or an Anthropic API key; with only a bearer token, Claude Code treats fast mode as disabled without sending the check | Set `CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK=1`; see [use fast mode behind proxies and LLM gateways](/docs/en/fast-mode#use-fast-mode-behind-proxies-and-llm-gateways) |
535| Claude Code asks you to log in even though the [curl test](#verify-the-connection) succeeds | The CLI has no credential of its own: a reachable base URL isn't one, and in an interactive session an `env` block in a project's `.claude/settings.json` or `.claude/settings.local.json` applies only after the first-run wizard and [trust prompt](/docs/en/permissions#what-runs-before-you-trust-a-folder) | Set `ANTHROPIC_AUTH_TOKEN` somewhere Claude Code reads before first-run setup: a shell export, the `env` block in `~/.claude/settings.json`, or managed settings |
536| `ANTHROPIC_API_KEY` is set but ignored, with no prompt | The key needs a one-time approval in interactive sessions, and a previously declined key is ignored without asking again | Enable it under `/config` with the `Use custom API key` option |
537| `This machine's managed settings require a first-party login`, or [`Administrator policy requires a Cloud gateway sign-in`](/docs/en/errors#administrator-policy-requires-a-cloud-gateway-sign-in) when managed settings set `forceLoginMethod` to `"gateway"` or also set `forceLoginGatewayUrl` | Managed settings include `forceLoginMethod` or `forceLoginOrgUUID`, which cannot coexist with `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN`, or `apiKeyHelper` | Your administrator must remove `forceLoginMethod`, `forceLoginOrgUUID`, and `forceLoginGatewayUrl` from managed settings to use gateway credentials, or remove the gateway credential and use the sign-in the managed settings require. The two cannot be combined |
538| `403` with an HTML body such as `403 Forbidden`, when the gateway's own logs show no request received | A web application firewall or reverse proxy in front of the gateway blocked the request body before it reached the gateway. Claude Code prompts include XML-style tags and source code that match cross-site-scripting body rules, so a short curl test passes while a real session doesn't | Exempt the gateway's `/v1/messages` path from request-body inspection. On AWS WAF this is the `CrossSiteScripting_Body` managed rule; on nginx with ModSecurity it is the equivalent OWASP CRS body rules |
539| Certificate or TLS errors such as `SSL certificate verification failed` or `Self-signed certificate detected`, when the [curl test](#verify-the-connection) succeeds | Claude Code's runtime isn't trusting the same certificate authority that `curl` uses. Common behind corporate TLS-inspection proxies | Set `NODE_EXTRA_CA_CERTS` to the CA bundle path; see [CA certificate store](/docs/en/network-config#ca-certificate-store) |
540540
541541If Claude Code prompts you to log in repeatedly after removing gateway configuration, the cause is usually credential storage rather than the gateway; see [authentication errors](/docs/en/errors#authentication-errors).
542542
llm-gateway-protocol Changed · +43 / -43 lines
from line 34
3434
3535Google Cloud's Agent Platform is Google Cloud's Claude endpoint, formerly Vertex AI; its variable names keep the `VERTEX` spelling.
3636
37| Format | Selected by | Endpoints | Forward unchanged |
38| :--------------------------------------- | :------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------- |
39| Anthropic Messages | `ANTHROPIC_BASE_URL` | `/v1/messages`, `/v1/messages/count_tokens` (optional) | `anthropic-beta` and `anthropic-version` request headers |
40| Amazon Bedrock InvokeModel | `ANTHROPIC_BEDROCK_BASE_URL` with `CLAUDE_CODE_USE_BEDROCK=1` | `/model/{model}/invoke`, `/model/{model}/invoke-with-response-stream`, `/model/{model}/count-tokens` (optional) | `anthropic_beta` and `anthropic_version` request body fields |
41| Google Cloud's Agent Platform rawPredict | `ANTHROPIC_VERTEX_BASE_URL` with `CLAUDE_CODE_USE_VERTEX=1` | `:rawPredict`, `:streamRawPredict`, `count-tokens:rawPredict` (optional) | `anthropic-beta` and `anthropic-version` request headers, and the `anthropic_version` request body field |
37| Format | Selected by | Endpoints | Forward unchanged |
38| :- | :- | :- | :- |
39| Anthropic Messages | `ANTHROPIC_BASE_URL` | `/v1/messages`, `/v1/messages/count_tokens` (optional) | `anthropic-beta` and `anthropic-version` request headers |
40| Amazon Bedrock InvokeModel | `ANTHROPIC_BEDROCK_BASE_URL` with `CLAUDE_CODE_USE_BEDROCK=1` | `/model/{model}/invoke`, `/model/{model}/invoke-with-response-stream`, `/model/{model}/count-tokens` (optional) | `anthropic_beta` and `anthropic_version` request body fields |
41| Google Cloud's Agent Platform rawPredict | `ANTHROPIC_VERTEX_BASE_URL` with `CLAUDE_CODE_USE_VERTEX=1` | `:rawPredict`, `:streamRawPredict`, `count-tokens:rawPredict` (optional) | `anthropic-beta` and `anthropic-version` request headers, and the `anthropic_version` request body field |
4242
4343### Foundry and Claude Platform on AWS
4444
from line 92
9292
9393The table below compares the three connection methods, one behavior per row. It leaves out Microsoft Foundry and Claude Platform on AWS, which also use the Anthropic Messages format but which Claude Code reaches through their own variables. For those, see the [Microsoft Foundry](/docs/en/microsoft-foundry) and [Claude Platform on AWS](/docs/en/claude-platform-on-aws) pages.
9494
95| Behavior | Amazon Bedrock or Agent Platform format | Anthropic Messages format | Claude apps gateway sign-in |
96| :------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------- |
97| Model IDs in requests by default | The provider's form, such as `us.anthropic.claude-opus-4-8` on Amazon Bedrock | Anthropic IDs, such as `claude-opus-4-8` | Anthropic IDs |
98| `anthropic-beta` values sent | The subset Amazon Bedrock and Agent Platform accept | The full set described under [feature pass-through](#feature-pass-through), unless the developer sets [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS`](#disable-pre-release-capabilities) | The subset Amazon Bedrock and Agent Platform accept |
99| Request fields for a model ID Claude Code doesn't recognize, such as a gateway alias | Thinking with a fixed budget rather than adaptive reasoning, and no effort or context management fields | Everything current Claude models accept on the Claude API, including adaptive reasoning, effort, and context management, which an Amazon Bedrock or Agent Platform upstream can reject | Same as the Amazon Bedrock or Agent Platform format |
100| One-hour [prompt cache TTL](/docs/en/prompt-caching#choose-the-ttl-yourself) when a developer opts in | Requested through the `ttl` field in `cache_control`, with no beta value | Requested through the `ttl` field plus an `extended-cache-ttl` value in `anthropic-beta`, which you must forward | See the Claude apps gateway [availability and limitations](/docs/en/claude-apps-gateway#availability-and-limitations) table |
101| Model for [background tasks](/docs/en/costs#background-token-usage) unless `ANTHROPIC_DEFAULT_HAIKU_MODEL` pins one | The default Sonnet model, or the main model once one is selected, as the [Amazon Bedrock](/docs/en/amazon-bedrock#4-pin-model-versions) and [Agent Platform](/docs/en/google-vertex-ai#5-pin-model-versions) pages describe | The main model, or the default Haiku model when `ANTHROPIC_API_KEY` or `apiKeyHelper` supplies an Anthropic Console key and `ANTHROPIC_AUTH_TOKEN` is unset | The main model |
95| Behavior | Amazon Bedrock or Agent Platform format | Anthropic Messages format | Claude apps gateway sign-in |
96| :- | :- | :- | :- |
97| Model IDs in requests by default | The provider's form, such as `us.anthropic.claude-opus-4-8` on Amazon Bedrock | Anthropic IDs, such as `claude-opus-4-8` | Anthropic IDs |
98| `anthropic-beta` values sent | The subset Amazon Bedrock and Agent Platform accept | The full set described under [feature pass-through](#feature-pass-through), unless the developer sets [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS`](#disable-pre-release-capabilities) | The subset Amazon Bedrock and Agent Platform accept |
99| Request fields for a model ID Claude Code doesn't recognize, such as a gateway alias | Thinking with a fixed budget rather than adaptive reasoning, and no effort or context management fields | Everything current Claude models accept on the Claude API, including adaptive reasoning, effort, and context management, which an Amazon Bedrock or Agent Platform upstream can reject | Same as the Amazon Bedrock or Agent Platform format |
100| One-hour [prompt cache TTL](/docs/en/prompt-caching#choose-the-ttl-yourself) when a developer opts in | Requested through the `ttl` field in `cache_control`, with no beta value | Requested through the `ttl` field plus an `extended-cache-ttl` value in `anthropic-beta`, which you must forward | See the Claude apps gateway [availability and limitations](/docs/en/claude-apps-gateway#availability-and-limitations) table |
101| Model for [background tasks](/docs/en/costs#background-token-usage) unless `ANTHROPIC_DEFAULT_HAIKU_MODEL` pins one | The default Sonnet model, or the main model once one is selected, as the [Amazon Bedrock](/docs/en/amazon-bedrock#4-pin-model-versions) and [Agent Platform](/docs/en/google-vertex-ai#5-pin-model-versions) pages describe | The main model, or the default Haiku model when `ANTHROPIC_API_KEY` or `apiKeyHelper` supplies an Anthropic Console key and `ANTHROPIC_AUTH_TOKEN` is unset | The main model |
102102
103103For the features each connection supports and the telemetry it sends to Anthropic by default, see [Feature availability](/docs/en/feature-availability#availability-by-model-provider) and [Default behaviors by API provider](/docs/en/data-usage#default-behaviors-by-api-provider).
104104
from line 113
113113
114114Claude Code includes these headers on API requests. Header names are case-insensitive on the wire. Forward `anthropic-version` and `anthropic-beta` unchanged, plus `anthropic-workspace-id` when the upstream is the [Claude Platform on AWS](/docs/en/claude-platform-on-aws); the rest the gateway may consume for routing, attribution, and tracing, and need not forward.
115115
116| Header | Description |
117| :------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
118| `Authorization`, `x-api-key` | The developer's gateway credential, in one or both headers depending on which [credential variable](/docs/en/llm-gateway-connect#set-the-credential-variable) they set |
119| `anthropic-version` | API version, currently `2023-06-01`. Amazon Bedrock- and Google Cloud's Agent Platform-format requests also carry the `anthropic_version` body field, whose value is the provider dialect string, not this header's value |
120| `anthropic-beta` | Comma-separated capability values for the request. Forward the header verbatim; don't allowlist individual values, because the set changes with Claude Code releases. When the developer authenticates with a claude.ai login, which is possible when `ANTHROPIC_BASE_URL` is set without a gateway credential variable, this header also carries an OAuth capability that the upstream requires, and stripping it fails those requests with `401` |
121| `x-claude-code-session-id` | A unique identifier for the current Claude Code session. Use it to aggregate all requests from one session without parsing request bodies |
122| `x-claude-code-agent-id` | Identifier of the [subagent](/docs/en/sub-agents) that issued the request, present only on requests from an agent Claude Code spawned inside the session. Use it with the session ID to attribute cost to parallel agents |
123| `x-claude-code-parent-agent-id` | Identifier of the agent that spawned the requesting agent, present only for nested agents |
116| Header | Description |
117| :- | :- |
118| `Authorization`, `x-api-key` | The developer's gateway credential, in one or both headers depending on which [credential variable](/docs/en/llm-gateway-connect#set-the-credential-variable) they set |
119| `anthropic-version` | API version, currently `2023-06-01`. Amazon Bedrock- and Google Cloud's Agent Platform-format requests also carry the `anthropic_version` body field, whose value is the provider dialect string, not this header's value |
120| `anthropic-beta` | Comma-separated capability values for the request. Forward the header verbatim; don't allowlist individual values, because the set changes with Claude Code releases. When the developer authenticates with a claude.ai login, which is possible when `ANTHROPIC_BASE_URL` is set without a gateway credential variable, this header also carries an OAuth capability that the upstream requires, and stripping it fails those requests with `401` |
121| `x-claude-code-session-id` | A unique identifier for the current Claude Code session. Use it to aggregate all requests from one session without parsing request bodies |
122| `x-claude-code-agent-id` | Identifier of the [subagent](/docs/en/sub-agents) that issued the request, present only on requests from an agent Claude Code spawned inside the session. Use it with the session ID to attribute cost to parallel agents |
123| `x-claude-code-parent-agent-id` | Identifier of the agent that spawned the requesting agent, present only for nested agents |
124124
125125Subagent IDs are generated fresh each time Claude Code spawns a subagent. Teammate agents, the named members of an [agent team](/docs/en/agent-teams), reuse a stable name-based ID across reconnections. In both cases the ID identifies an agent, not a person or a device, so don't treat the agent ID header as a user identifier.
126126
from line 140
140140
141141The headers carry only what the rows below list: fixed vocabularies, tool names, durations, and a random prompt identifier, never prompt text or file contents. Every value is printable ASCII.
142142
143| Header | Description |
144| :---------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
145| `x-claude-code-request-class` | What kind of request this is: `main` for a turn of the main conversation, `subagent` for a turn of a [subagent](/docs/en/sub-agents), `workflow` for an agent running inside a workflow, `compaction` for the summarization request that compacts a conversation, or `auxiliary` for side requests such as session titles, classifiers, and summaries. Sent on every request |
146| `x-claude-code-agent-type` | The kind of subagent that issued the request: a built-in agent type name such as `Explore`, `Plan`, or `general-purpose`, or `custom` for a user-defined agent, `teammate` for an [agent team](/docs/en/agent-teams) member running in the lead's process, or `fork` for a [fork](/docs/en/sub-agents#fork-the-current-conversation). Present only on a subagent's own turns; a subagent's compaction or side requests keep the agent ID but carry no type. A user-chosen agent name is never sent |
147| `x-claude-code-compaction` | Present on the request that summarizes the conversation during a [compaction](/docs/en/prompt-caching#compacting-the-conversation). The value says what triggered it: `auto` when the context window approached capacity, `manual` for `/compact`, or `reactive` when the API rejected a request as too long. Absent on every other request |
148| `x-claude-code-context-compacted` | Present once, on the first main-conversation request after a compaction, with the same values as `x-claude-code-compaction`. The conversation prefix before this request is no longer used, so a cache keyed on it can be dropped |
149| `x-claude-code-prev-tool-durations` | Measured run time of the tool calls whose results this request carries, as `<name>=<ms>;<name>=<ms>`, for example `Bash=742;Read=9`. Sent on the next request of the same conversation after a batch of tool calls, from the main session or a subagent |
150| `x-claude-code-prompt-id` | Random UUID that identifies the user prompt a request serves. Requests serving one prompt share the value, including the turns of subagents that prompt started. Requests not attributed to a prompt omit it. Use it to group a session's requests by prompt. Requires Claude Code v2.1.283 or later |
143| Header | Description |
144| :- | :- |
145| `x-claude-code-request-class` | What kind of request this is: `main` for a turn of the main conversation, `subagent` for a turn of a [subagent](/docs/en/sub-agents), `workflow` for an agent running inside a workflow, `compaction` for the summarization request that compacts a conversation, or `auxiliary` for side requests such as session titles, classifiers, and summaries. Sent on every request |
146| `x-claude-code-agent-type` | The kind of subagent that issued the request: a built-in agent type name such as `Explore`, `Plan`, or `general-purpose`, or `custom` for a user-defined agent, `teammate` for an [agent team](/docs/en/agent-teams) member running in the lead's process, or `fork` for a [fork](/docs/en/sub-agents#fork-the-current-conversation). Present only on a subagent's own turns; a subagent's compaction or side requests keep the agent ID but carry no type. A user-chosen agent name is never sent |
147| `x-claude-code-compaction` | Present on the request that summarizes the conversation during a [compaction](/docs/en/prompt-caching#compacting-the-conversation). The value says what triggered it: `auto` when the context window approached capacity, `manual` for `/compact`, or `reactive` when the API rejected a request as too long. Absent on every other request |
148| `x-claude-code-context-compacted` | Present once, on the first main-conversation request after a compaction, with the same values as `x-claude-code-compaction`. The conversation prefix before this request is no longer used, so a cache keyed on it can be dropped |
149| `x-claude-code-prev-tool-durations` | Measured run time of the tool calls whose results this request carries, as `<name>=<ms>;<name>=<ms>`, for example `Bash=742;Read=9`. Sent on the next request of the same conversation after a batch of tool calls, from the main session or a subagent |
150| `x-claude-code-prompt-id` | Random UUID that identifies the user prompt a request serves. Requests serving one prompt share the value, including the turns of subagents that prompt started. Requests not attributed to a prompt omit it. Use it to group a session's requests by prompt. Requires Claude Code v2.1.283 or later |
151151
152152Before parsing `x-claude-code-prev-tool-durations`, check how Claude Code builds the value and what it leaves out:
153153
from line 170
170170
171171Claude Code reads these response headers to detect stalled streams, to decide whether and when to retry, and to show usage limits. The table lists what to return for each. Also forward error response bodies unmodified, so Claude Code's [capability-rejection recovery](#automatic-retry-and-error-forwarding) can match the upstream's error wording.
172172
173| Header | What to return and why |
174| :------------------------------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
175| `content-type` | Return `text/event-stream` on streamed Anthropic Messages-format responses, and `application/vnd.amazon.eventstream`, unmodified, on Amazon Bedrock-format responses, where [a different type fails the request](/docs/en/amazon-bedrock#streaming-errors-behind-a-gateway-or-proxy). [Streaming](#streaming) lists which connections run stall detection on these streams |
176| `retry-after` | Return integer seconds rather than an HTTP date. Claude Code waits at least that long before the next [automatic retry](/docs/en/errors#automatic-retries), and outside [`CLAUDE_CODE_RETRY_WATCHDOG`](/docs/en/env-vars) sessions a value above 60 stops the retries and shows the error at once |
177| `x-should-retry` | Pass the upstream's value through unchanged. Claude Code reads this header as one input when deciding whether to retry a failed request: `true` marks the response retryable and `false` marks it not retryable. For retry counts, backoff, and which failures Claude Code retries, see [automatic retries](/docs/en/errors#automatic-retries) |
178| `anthropic-ratelimit-unified-*` | Forward the upstream's values unchanged on every response. Claude Code reads them on successful responses to show usage against plan limits to developers signed in with claude.ai, and on a `429` to tell a plan limit or spend cap from a temporary throttle; see [usage limits](/docs/en/errors#usage-limits) |
173| Header | What to return and why |
174| :- | :- |
175| `content-type` | Return `text/event-stream` on streamed Anthropic Messages-format responses, and `application/vnd.amazon.eventstream`, unmodified, on Amazon Bedrock-format responses, where [a different type fails the request](/docs/en/amazon-bedrock#streaming-errors-behind-a-gateway-or-proxy). [Streaming](#streaming) lists which connections run stall detection on these streams |
176| `retry-after` | Return integer seconds rather than an HTTP date. Claude Code waits at least that long before the next [automatic retry](/docs/en/errors#automatic-retries), and outside [`CLAUDE_CODE_RETRY_WATCHDOG`](/docs/en/env-vars) sessions a value above 60 stops the retries and shows the error at once |
177| `x-should-retry` | Pass the upstream's value through unchanged. Claude Code reads this header as one input when deciding whether to retry a failed request: `true` marks the response retryable and `false` marks it not retryable. For retry counts, backoff, and which failures Claude Code retries, see [automatic retries](/docs/en/errors#automatic-retries) |
178| `anthropic-ratelimit-unified-*` | Forward the upstream's values unchanged on every response. Claude Code reads them on successful responses to show usage against plan limits to developers signed in with claude.ai, and on a `429` to tell a plan limit or spend cap from a temporary throttle; see [usage limits](/docs/en/errors#usage-limits) |
179179
180180## System prompt attribution block
181181
from line 207
207207
208208Fine-grained tool streaming is one of the direct-connection defaults: it is off by default whenever requests route through a custom base URL, and a gateway receives it when developers set [`CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING=1`](/docs/en/env-vars).
209209
210| Feature | Header and body pair | Symptom when broken | Remediation |
211| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------- |
212| [Adaptive reasoning](/docs/en/model-config#adjust-effort-level) | No beta header. Claude Code sends `thinking: {"type": "adaptive"}` for Claude 4.6 and later, and treats model names it doesn't recognize, such as gateway aliases, as current models that receive the field | `400` naming the `thinking` field or the `adaptive` tag when the upstream model build doesn't accept it | Upgrade the upstream. On Opus 4.6 and Sonnet 4.6, developers can set `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1` instead |
213| [Context management](https://platform.claude.com/docs/en/build-with-claude/context-editing) | Context management beta header pairs with the `context_management` body field | `400` with `Extra inputs are not permitted`. Common when a gateway accepts Anthropic-format requests but forwards them to Amazon Bedrock | Forward both, or [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`](/docs/en/env-vars) |
214| [Extended context](https://platform.claude.com/docs/en/build-with-claude/context-windows#context-window-sizes-by-model) and [interleaved thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking#interleaved-thinking) | Beta headers only, no body field | Silently unavailable when the header is stripped; the upstream never sees the capability request | Forward `anthropic-beta` verbatim |
215| Beta [tool fields](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview) | Tool-related beta headers pair with tool schema fields such as `strict` and `defer_loading` | `400` naming the unrecognized tool schema field when the body passes through without its header | Forward both, or [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`](#disable-pre-release-capabilities) |
216| [Effort](https://platform.claude.com/docs/en/build-with-claude/effort) and [structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs) | The `output_config` body field carries effort, structured-output format, and task budget settings; each pairs with its own beta header | `400` naming `output_config`, often `Extra inputs are not permitted`, on Amazon Bedrock and Google Cloud's Agent Platform upstreams | Forward the field and its headers together |
217| [Prompt caching](/docs/en/prompt-caching) | No beta pairing. Claude Code attaches `cache_control` markers to `system` blocks and to `messages` entries, including `role: "system"` entries appended mid-conversation | No error: the conversation bills as uncached input on every turn, visible as high `input_tokens` with little or no cache activity in `usage` | Forward `cache_control` unchanged wherever it appears, and don't convert block-form `system` or message content to plain strings |
218| [Token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting) | No beta pairing; uses the `count_tokens` endpoint | No error: Claude Code falls back to a character-based estimate, so `/context` shows approximate counts | Expose the endpoint for exact token counts |
210| Feature | Header and body pair | Symptom when broken | Remediation |
211| :- | :- | :- | :- |
212| [Adaptive reasoning](/docs/en/model-config#adjust-effort-level) | No beta header. Claude Code sends `thinking: {"type": "adaptive"}` for Claude 4.6 and later, and treats model names it doesn't recognize, such as gateway aliases, as current models that receive the field | `400` naming the `thinking` field or the `adaptive` tag when the upstream model build doesn't accept it | Upgrade the upstream. On Opus 4.6 and Sonnet 4.6, developers can set `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1` instead |
213| [Context management](https://platform.claude.com/docs/en/build-with-claude/context-editing) | Context management beta header pairs with the `context_management` body field | `400` with `Extra inputs are not permitted`. Common when a gateway accepts Anthropic-format requests but forwards them to Amazon Bedrock | Forward both, or [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`](/docs/en/env-vars) |
214| [Extended context](https://platform.claude.com/docs/en/build-with-claude/context-windows#context-window-sizes-by-model) and [interleaved thinking](https://platform.claude.com/docs/en/build-with-claude/extended-thinking#interleaved-thinking) | Beta headers only, no body field | Silently unavailable when the header is stripped; the upstream never sees the capability request | Forward `anthropic-beta` verbatim |
215| Beta [tool fields](https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview) | Tool-related beta headers pair with tool schema fields such as `strict` and `defer_loading` | `400` naming the unrecognized tool schema field when the body passes through without its header | Forward both, or [`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`](#disable-pre-release-capabilities) |
216| [Effort](https://platform.claude.com/docs/en/build-with-claude/effort) and [structured outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs) | The `output_config` body field carries effort, structured-output format, and task budget settings; each pairs with its own beta header | `400` naming `output_config`, often `Extra inputs are not permitted`, on Amazon Bedrock and Google Cloud's Agent Platform upstreams | Forward the field and its headers together |
217| [Prompt caching](/docs/en/prompt-caching) | No beta pairing. Claude Code attaches `cache_control` markers to `system` blocks and to `messages` entries, including `role: "system"` entries appended mid-conversation | No error: the conversation bills as uncached input on every turn, visible as high `input_tokens` with little or no cache activity in `usage` | Forward `cache_control` unchanged wherever it appears, and don't convert block-form `system` or message content to plain strings |
218| [Token counting](https://platform.claude.com/docs/en/build-with-claude/token-counting) | No beta pairing; uses the `count_tokens` endpoint | No error: Claude Code falls back to a character-based estimate, so `/context` shows approximate counts | Expose the endpoint for exact token counts |
219219
220220The `ANTHROPIC_DEFAULT_*_MODEL_SUPPORTED_CAPABILITIES` [variables](/docs/en/model-config) declare model capabilities only in the provider configurations: `CLAUDE_CODE_USE_BEDROCK`, `CLAUDE_CODE_USE_VERTEX`, `CLAUDE_CODE_USE_FOUNDRY`, and [`CLAUDE_CODE_USE_MANTLE`](/docs/en/amazon-bedrock#use-the-mantle-endpoint). They have no effect behind an `ANTHROPIC_BASE_URL` gateway.
221221
llm-gateway-rollout Changed · +25 / -25 lines
from line 45
4545
4646The steps involve three different credentials, and the checkpoints name them by placeholder so you can tell which one is at fault when something fails:
4747
48| Credential | Who holds it | Placeholder in checkpoints |
49| :-------------------------------- | :--------------------------------------------------------------------------------------------------- | :---------------------------------------------------------- |
50| Provider credential | The gateway, which forwards it to the upstream provider | Configured on the gateway; never appears in client commands |
51| Gateway administrative credential | You, if your gateway product issues one for its admin or test interface | `<gateway-key>` |
52| Developer key | Each developer, issued by the gateway in [Issue developer credentials](#issue-developer-credentials) | `<developer-key>` |
48| Credential | Who holds it | Placeholder in checkpoints |
49| :- | :- | :- |
50| Provider credential | The gateway, which forwards it to the upstream provider | Configured on the gateway; never appears in client commands |
51| Gateway administrative credential | You, if your gateway product issues one for its admin or test interface | `<gateway-key>` |
52| Developer key | Each developer, issued by the gateway in [Issue developer credentials](#issue-developer-credentials) | `<developer-key>` |
5353
5454### Confirm the gateway routes your models
5555
from line 159
159159
160160The same set of variables applies whichever path you choose. Most rollouts only need `ANTHROPIC_BASE_URL` and a credential; include the conditional rows when your gateway setup calls for them.
161161
162| Variable or setting | What it does | Include when |
163| :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
164| `ANTHROPIC_BASE_URL` | Sends Claude Code's API requests to the gateway instead of `api.anthropic.com` | Always |
165| `apiKeyHelper`, or a credential in `ANTHROPIC_AUTH_TOKEN` or `ANTHROPIC_API_KEY` | Authenticates each request to the gateway. The helper runs a command to fetch the key; the variables hold a static key, sent as `Authorization: Bearer` and `x-api-key` respectively | Always; one of the three |
166| `ANTHROPIC_CUSTOM_HEADERS` | Adds extra HTTP headers to every API request | Your gateway requires a tenant or routing header on every request |
167| `CLAUDE_CODE_GATEWAY_HINT_HEADERS` | Sends the [gateway hint headers](/docs/en/llm-gateway-protocol#gateway-hint-headers), which classify each request for routing and scheduling decisions at the gateway. Requires Claude Code v2.1.273 or later | Your gateway reads the hint headers |
168| `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY` | Queries the gateway's `/v1/models` at startup and adds the returned names to the `/model` picker | Your gateway serves `/v1/models` and you want developers' pickers populated from it |
169| `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS` | Stops Claude Code sending pre-release capability headers and body fields. [Disable pre-release capabilities](/docs/en/llm-gateway-protocol#disable-pre-release-capabilities) covers the exact scope | Your gateway forwards to an Amazon Bedrock or Google Cloud's Agent Platform upstream that rejects beta fields. See [Gateway requirements](#gateway-requirements) |
170| `CLAUDE_CODE_SKIP_FAST_MODE_NETWORK_ERRORS` or `CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK` | Restores [fast mode](/docs/en/fast-mode) when its availability check, which calls `api.anthropic.com` directly rather than following `ANTHROPIC_BASE_URL`, fails, is intercepted, or is skipped for lack of an Anthropic credential | Your organization uses fast mode, and developers authenticate with `ANTHROPIC_AUTH_TOKEN` alone, with a gateway-issued key in `ANTHROPIC_API_KEY` or from an `apiKeyHelper`, or your network blocks or intercepts direct requests to `api.anthropic.com`; [use fast mode behind proxies and LLM gateways](/docs/en/fast-mode#use-fast-mode-behind-proxies-and-llm-gateways) covers which of the two variables matches your configuration |
171| `ANTHROPIC_MODEL` or [`ANTHROPIC_DEFAULT_HAIKU_MODEL`](/docs/en/model-config) | Set which model name Claude Code requests for the main session and for background traffic | Your gateway routes model names that don't match Claude Code's defaults, or you route [background functionality](/docs/en/costs#background-token-usage) to a different model. Route both the override names and the built-in model IDs Claude Code requests when no override is set, since some background sub-calls request a built-in ID regardless of the override; [model configuration](/docs/en/model-config) covers which model each part of a session uses |
172| `ANTHROPIC_BEDROCK_BASE_URL`, `ANTHROPIC_VERTEX_BASE_URL`, `ANTHROPIC_FOUNDRY_BASE_URL`, or `ANTHROPIC_AWS_BASE_URL` with the [variables for that provider](/docs/en/llm-gateway-connect#route-to-a-cloud-provider-through-a-gateway) | Point Claude Code at the gateway through a provider-specific base URL. Amazon Bedrock and Google Cloud's Agent Platform also switch to those providers' native request format | Your gateway fronts Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, or the Claude Platform on AWS; see [API formats](/docs/en/llm-gateway-protocol#api-formats) |
162| Variable or setting | What it does | Include when |
163| :- | :- | :- |
164| `ANTHROPIC_BASE_URL` | Sends Claude Code's API requests to the gateway instead of `api.anthropic.com` | Always |
165| `apiKeyHelper`, or a credential in `ANTHROPIC_AUTH_TOKEN` or `ANTHROPIC_API_KEY` | Authenticates each request to the gateway. The helper runs a command to fetch the key; the variables hold a static key, sent as `Authorization: Bearer` and `x-api-key` respectively | Always; one of the three |
166| `ANTHROPIC_CUSTOM_HEADERS` | Adds extra HTTP headers to every API request | Your gateway requires a tenant or routing header on every request |
167| `CLAUDE_CODE_GATEWAY_HINT_HEADERS` | Sends the [gateway hint headers](/docs/en/llm-gateway-protocol#gateway-hint-headers), which classify each request for routing and scheduling decisions at the gateway. Requires Claude Code v2.1.273 or later | Your gateway reads the hint headers |
168| `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY` | Queries the gateway's `/v1/models` at startup and adds the returned names to the `/model` picker | Your gateway serves `/v1/models` and you want developers' pickers populated from it |
169| `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS` | Stops Claude Code sending pre-release capability headers and body fields. [Disable pre-release capabilities](/docs/en/llm-gateway-protocol#disable-pre-release-capabilities) covers the exact scope | Your gateway forwards to an Amazon Bedrock or Google Cloud's Agent Platform upstream that rejects beta fields. See [Gateway requirements](#gateway-requirements) |
170| `CLAUDE_CODE_SKIP_FAST_MODE_NETWORK_ERRORS` or `CLAUDE_CODE_SKIP_FAST_MODE_ORG_CHECK` | Restores [fast mode](/docs/en/fast-mode) when its availability check, which calls `api.anthropic.com` directly rather than following `ANTHROPIC_BASE_URL`, fails, is intercepted, or is skipped for lack of an Anthropic credential | Your organization uses fast mode, and developers authenticate with `ANTHROPIC_AUTH_TOKEN` alone, with a gateway-issued key in `ANTHROPIC_API_KEY` or from an `apiKeyHelper`, or your network blocks or intercepts direct requests to `api.anthropic.com`; [use fast mode behind proxies and LLM gateways](/docs/en/fast-mode#use-fast-mode-behind-proxies-and-llm-gateways) covers which of the two variables matches your configuration |
171| `ANTHROPIC_MODEL` or [`ANTHROPIC_DEFAULT_HAIKU_MODEL`](/docs/en/model-config) | Set which model name Claude Code requests for the main session and for background traffic | Your gateway routes model names that don't match Claude Code's defaults, or you route [background functionality](/docs/en/costs#background-token-usage) to a different model. Route both the override names and the built-in model IDs Claude Code requests when no override is set, since some background sub-calls request a built-in ID regardless of the override; [model configuration](/docs/en/model-config) covers which model each part of a session uses |
172| `ANTHROPIC_BEDROCK_BASE_URL`, `ANTHROPIC_VERTEX_BASE_URL`, `ANTHROPIC_FOUNDRY_BASE_URL`, or `ANTHROPIC_AWS_BASE_URL` with the [variables for that provider](/docs/en/llm-gateway-connect#route-to-a-cloud-provider-through-a-gateway) | Point Claude Code at the gateway through a provider-specific base URL. Amazon Bedrock and Google Cloud's Agent Platform also switch to those providers' native request format | Your gateway fronts Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, or the Claude Platform on AWS; see [API formats](/docs/en/llm-gateway-protocol#api-formats) |
173173
174174#### Distribute through managed settings
175175
from line 254
254254
255255After rollout, three kinds of change reach the gateway over time. Each has a symptom to watch for and an action to take.
256256
257| Change | Symptom when the gateway hasn't kept up | Action |
258| :--------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
257| Change | Symptom when the gateway hasn't kept up | Action |
258| :- | :- | :- |
259259| New Claude Code releases add `anthropic-beta` values and request body fields | Developers report `400` errors naming a new field after they update Claude Code; see [feature pass-through](/docs/en/llm-gateway-protocol#feature-pass-through) | Forward `anthropic-*` headers and request bodies verbatim rather than allowlisting; test new Claude Code releases against the gateway before they reach developers, checking the areas in [Plan Claude Code version upgrades](#plan-claude-code-version-upgrades) |
260| New Claude models become available | Developers selecting a new model name get `404`; the `/model` picker doesn't list it | Add the model name to the gateway's routing configuration, then re-run the [routing check](#confirm-the-gateway-routes-your-models). If you distribute `ANTHROPIC_MODEL` or the default-model variables, update the managed settings |
261| Credentials expire or need rotation | All developer requests start failing with `401` from the upstream | Rotate the gateway's provider credential on its own schedule; developer keys rotate at the gateway, and an [`apiKeyHelper`](/docs/en/llm-gateway-connect#rotate-credentials-with-apikeyhelper) handles per-developer rotation without redistributing settings |
260| New Claude models become available | Developers selecting a new model name get `404`; the `/model` picker doesn't list it | Add the model name to the gateway's routing configuration, then re-run the [routing check](#confirm-the-gateway-routes-your-models). If you distribute `ANTHROPIC_MODEL` or the default-model variables, update the managed settings |
261| Credentials expire or need rotation | All developer requests start failing with `401` from the upstream | Rotate the gateway's provider credential on its own schedule; developer keys rotate at the gateway, and an [`apiKeyHelper`](/docs/en/llm-gateway-connect#rotate-credentials-with-apikeyhelper) handles per-developer rotation without redistributing settings |
262262
263263When sizing per-key rate limits, account for the client [retrying transient failures](/docs/en/errors#automatic-retries), including `429` responses, up to 10 times with backoff, honoring `Retry-After`. Keep the [compatibility guide](/docs/en/llm-gateway-protocol) as the reference for what each Claude Code release sends.
264264
from line 268
268268
269269When you test a release, new headers or request fields that the gateway rejects appear as the `400` errors described in [Maintain the gateway](#maintain-the-gateway). The table below covers version-dependent changes that don't produce an error, with the setting that keeps each one constant across upgrades.
270270
271| Area | What can change when developers upgrade | Setting that keeps it constant |
272| :--------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
273| Feature-flag defaults | Sessions that [don't fetch feature flags from Anthropic](/docs/en/env-vars#features-that-need-feature-flag-fetching), such as sessions on a cloud provider or with telemetry turned off, use the flag defaults built into the installed version. When a release changes one of those defaults, the behavior changes for those developers as soon as they upgrade | The version pin itself, `requiredMaximumVersion` or `DISABLE_UPDATES` |
274| Model capability assumptions | A model ID that the installed version doesn't recognize, such as the gateway alias `prod-opus`, runs on default assumptions for [adaptive reasoning](/docs/en/model-config#adaptive-reasoning-and-fixed-thinking-budgets), the effort parameter, and the [context window](/docs/en/model-config#correct-the-window-for-a-gateway-or-custom-model-id) until a later version recognizes the ID or you map it | Route Anthropic model IDs at the gateway, or add a [`modelOverrides`](/docs/en/model-config#override-model-ids-per-version) entry that maps the Anthropic model ID to your alias. On a cloud provider connection, you can instead [declare a pinned model's capabilities](/docs/en/model-config#customize-pinned-model-display-and-capabilities) |
275| Default model and aliases | The model that new sessions start on by default, and the models that aliases such as `opus` and `sonnet` resolve to, are [built into each version](/docs/en/model-config#pin-models-for-third-party-deployments) and can change when developers upgrade | [`ANTHROPIC_DEFAULT_MODEL`](/docs/en/model-config#set-a-default-model-for-new-sessions) for the model new sessions start on, and the [`ANTHROPIC_DEFAULT_*_MODEL` variables](/docs/en/model-config#environment-variables), such as `ANTHROPIC_DEFAULT_OPUS_MODEL`, for what each alias resolves to. `ANTHROPIC_DEFAULT_MODEL` requires Claude Code v2.1.236 or later |
271| Area | What can change when developers upgrade | Setting that keeps it constant |
272| :- | :- | :- |
273| Feature-flag defaults | Sessions that [don't fetch feature flags from Anthropic](/docs/en/env-vars#features-that-need-feature-flag-fetching), such as sessions on a cloud provider or with telemetry turned off, use the flag defaults built into the installed version. When a release changes one of those defaults, the behavior changes for those developers as soon as they upgrade | The version pin itself, `requiredMaximumVersion` or `DISABLE_UPDATES` |
274| Model capability assumptions | A model ID that the installed version doesn't recognize, such as the gateway alias `prod-opus`, runs on default assumptions for [adaptive reasoning](/docs/en/model-config#adaptive-reasoning-and-fixed-thinking-budgets), the effort parameter, and the [context window](/docs/en/model-config#correct-the-window-for-a-gateway-or-custom-model-id) until a later version recognizes the ID or you map it | Route Anthropic model IDs at the gateway, or add a [`modelOverrides`](/docs/en/model-config#override-model-ids-per-version) entry that maps the Anthropic model ID to your alias. On a cloud provider connection, you can instead [declare a pinned model's capabilities](/docs/en/model-config#customize-pinned-model-display-and-capabilities) |
275| Default model and aliases | The model that new sessions start on by default, and the models that aliases such as `opus` and `sonnet` resolve to, are [built into each version](/docs/en/model-config#pin-models-for-third-party-deployments) and can change when developers upgrade | [`ANTHROPIC_DEFAULT_MODEL`](/docs/en/model-config#set-a-default-model-for-new-sessions) for the model new sessions start on, and the [`ANTHROPIC_DEFAULT_*_MODEL` variables](/docs/en/model-config#environment-variables), such as `ANTHROPIC_DEFAULT_OPUS_MODEL`, for what each alias resolves to. `ANTHROPIC_DEFAULT_MODEL` requires Claude Code v2.1.236 or later |
276276
277277## Related resources
278278
managed-mcp Changed · +81 / -81 lines
from line 23
2323
2424Claude Code supports a range of restriction levels. Each pattern uses one or more of the mechanisms covered below: `managed-mcp.json` for deploying a fixed set, the `managedMcpServers` managed setting for providing servers alongside the ones users add, and `allowedMcpServers`/`deniedMcpServers` for filtering what users configure.
2525
26| Pattern | What it does | Configure |
27| :---------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------- |
28| **Disable MCP** | No servers load, apart from [in-process servers the app that started the session registers](#exclusive-control-with-managed-mcp-json) and any you [provide through `managedMcpServers`](#provide-servers-through-managed-settings) | `managed-mcp.json` with an empty server map |
29| **Fixed deployment** | Every user gets the same servers and can't add others | `managed-mcp.json` with the servers you want |
30| **Provided servers** | Every user gets the remote servers you list and keeps their own | `managedMcpServers` in managed settings |
31| **Approved catalog** | Publish a list of approved servers; users add the ones they want, anything else is blocked | `allowedMcpServers` + `allowManagedMcpServersOnly: true` |
32| **Plugin servers only** | Users can't add servers through `~/.claude.json` or `.mcp.json`; plugin servers still load | [`strictPluginOnlyCustomization`](/docs/en/settings-reference#strictpluginonlycustomization) with `mcp` in the list |
33| **Soft allowlist** | Enforce an allowlist that users can broaden in their own settings | `allowedMcpServers` without `allowManagedMcpServersOnly` |
34| **Denylist only** | Block known-bad servers, allow everything else | `deniedMcpServers` |
35| **No restrictions** | Users add anything | Don't deploy any managed MCP configuration |
26| Pattern | What it does | Configure |
27| :- | :- | :- |
28| **Disable MCP** | No servers load, apart from [in-process servers the app that started the session registers](#exclusive-control-with-managed-mcp-json) and any you [provide through `managedMcpServers`](#provide-servers-through-managed-settings) | `managed-mcp.json` with an empty server map |
29| **Fixed deployment** | Every user gets the same servers and can't add others | `managed-mcp.json` with the servers you want |
30| **Provided servers** | Every user gets the remote servers you list and keeps their own | `managedMcpServers` in managed settings |
31| **Approved catalog** | Publish a list of approved servers; users add the ones they want, anything else is blocked | `allowedMcpServers` + `allowManagedMcpServersOnly: true` |
32| **Plugin servers only** | Users can't add servers through `~/.claude.json` or `.mcp.json`; plugin servers still load | [`strictPluginOnlyCustomization`](/docs/en/settings-reference#strictpluginonlycustomization) with `mcp` in the list |
33| **Soft allowlist** | Enforce an allowlist that users can broaden in their own settings | `allowedMcpServers` without `allowManagedMcpServersOnly` |
34| **Denylist only** | Block known-bad servers, allow everything else | `deniedMcpServers` |
35| **No restrictions** | Users add anything | Don't deploy any managed MCP configuration |
3636
3737<Note>
3838 Claude Code doesn't have a built-in MCP server registry that users can browse and install from. For the approved-catalog pattern, share the approved list and its `claude mcp add` commands somewhere your users will find them, such as an internal wiki, or distribute the servers as plugins through a [managed plugin marketplace](/docs/en/plugins/org#restrict-what-users-can-install) so users can browse and install them from `/plugin`.
from line 54
5454
5555Any process that can write to a system path with administrator privileges can deploy the file. Across a fleet, that's usually through device management tooling, such as Jamf or a configuration profile on macOS, Group Policy or Intune on Windows, or your fleet management of choice on Linux. Claude Code looks for the file at one of these paths:
5656
57| Platform | Path |
58| :------------ | :--------------------------------------------------------- |
59| macOS | `/Library/Application Support/ClaudeCode/managed-mcp.json` |
60| Linux and WSL | `/etc/claude-code/managed-mcp.json` |
61| Windows | `C:\Program Files\ClaudeCode\managed-mcp.json` |
57| Platform | Path |
58| :- | :- |
59| macOS | `/Library/Application Support/ClaudeCode/managed-mcp.json` |
60| Linux and WSL | `/etc/claude-code/managed-mcp.json` |
61| Windows | `C:\Program Files\ClaudeCode\managed-mcp.json` |
6262
6363The file uses the same format as a project [`.mcp.json`](/docs/en/mcp#project-scope) file:
6464
from line 255
255255
256256`allowedMcpServers` and `deniedMcpServers` are lists of entries. Each entry is an object with a single key that identifies servers by their URL, their command, or their name:
257257
258| Key | Matches | Use for |
259| :-------------- | :-------------------------------------------------------------------- | :------------------------------------- |
260| `serverUrl` | A remote server URL, exact or with `*` wildcards | HTTP and SSE servers |
261| `serverCommand` | The exact command and arguments that start a stdio server | Stdio servers |
262| `serverName` | The user-assigned label. Exact match only; wildcards are not expanded | Either type, but see the Warning below |
258| Key | Matches | Use for |
259| :- | :- | :- |
260| `serverUrl` | A remote server URL, exact or with `*` wildcards | HTTP and SSE servers |
261| `serverCommand` | The exact command and arguments that start a stdio server | Stdio servers |
262| `serverName` | The user-assigned label. Exact match only; wildcards are not expanded | Either type, but see the Warning below |
263263
264264Leaving `allowedMcpServers` unset is different from setting it to an empty array:
265265
266| Setting | Unset (default) | Empty array `[]` | Populated |
267| :------------------ | :------------------ | :---------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------- |
266| Setting | Unset (default) | Empty array `[]` | Populated |
267| :- | :- | :- | :- |
268268| `allowedMcpServers` | All servers allowed | No servers allowed, apart from [the organization's own](#how-a-server-is-evaluated) | Only matching servers allowed, apart from [the organization's own](#how-a-server-is-evaluated) |
269| `deniedMcpServers` | No servers blocked | No servers blocked | Matching servers blocked |
269| `deniedMcpServers` | No servers blocked | No servers blocked | Matching servers blocked |
270270
271271See [Invalid entries in managed settings](/docs/en/managed-settings#invalid-entries-in-managed-settings) for what happens when an entry fails schema validation.
272272
from line 293
293293
294294 A `managed-mcp.json` server that uses `${VAR}` expansion in its command, arguments, `env`, URL, or headers is still checked, as is every server a user, a plugin, `--mcp-config`, or claude.ai adds.
295295
296| Server type | Allowed when it matches |
297| :------------------- | :--------------------------------------------------------------------------------------------------------------- |
298| Remote (HTTP or SSE) | A `serverUrl` entry. A `serverName` match counts only when the allowlist contains no `serverUrl` entries |
299| Stdio | A `serverCommand` entry. A `serverName` match counts only when the allowlist contains no `serverCommand` entries |
296| Server type | Allowed when it matches |
297| :- | :- |
298| Remote (HTTP or SSE) | A `serverUrl` entry. A `serverName` match counts only when the allowlist contains no `serverUrl` entries |
299| Stdio | A `serverCommand` entry. A `serverName` match counts only when the allowlist contains no `serverCommand` entries |
300300
301301Three matching rules apply inside those checks:
302302
from line 304
304304* **`serverCommand` and `serverUrl` values expand before matching.** Both the policy entry and the server's configured value go through [`${VAR}` and `${VAR:-default}` expansion](/docs/en/mcp#environment-variable-expansion-in-mcp-json), so an entry written as `["${HOME}/bin/server"]` matches a server config that uses either the same reference or the expanded path. On Windows, reference an environment variable that is set there, such as `${USERPROFILE}` instead of `${HOME}`. `serverName` values match literally and never expand. The two sides read different environments; [How policy entries expand](#how-policy-entries-expand) covers which, and how allowlist and denylist entries differ.
305305* **URLs support `*` wildcards** anywhere in the pattern, including the scheme. Hostname matching is case-insensitive and ignores a trailing FQDN dot, so `https://Mcp.Example.com/*` matches `https://mcp.example.com/api`. Paths stay case-sensitive.
306306
307| Pattern | Allows |
308| :-------------------------- | :--------------------------------------------------------------------- |
309| `https://mcp.example.com/*` | All paths on a specific domain |
310| `https://mcp.example.com` | Also all paths on that domain. A pattern with no path matches any path |
311| `https://*.example.com/*` | Any subdomain of `example.com` |
312| `http://localhost:*/*` | Any port on localhost |
313| `*://mcp.example.com/*` | Any scheme to a specific domain |
307| Pattern | Allows |
308| :- | :- |
309| `https://mcp.example.com/*` | All paths on a specific domain |
310| `https://mcp.example.com` | Also all paths on that domain. A pattern with no path matches any path |
311| `https://*.example.com/*` | Any subdomain of `example.com` |
312| `http://localhost:*/*` | Any port on localhost |
313| `*://mcp.example.com/*` | Any scheme to a specific domain |
314314
315315#### How policy entries expand
316316
317317The server's configured value expands from the live process environment, like the rest of `.mcp.json`. A policy entry expands from a pinned environment instead, so a variable set by a project or user settings file can't change what an allowlist entry means. Because a policy entry still depends on the launching shell's value for any variable it references, use literal URLs and commands for entries you rely on for enforcement.
318318
319| Entry list | Expands from | Expansion that would change a URL entry's scheme, host, or path scope |
320| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
321| `allowedMcpServers` | The environment Claude Code started with, plus `env` values from managed settings | Claude Code ignores the entry |
322| `deniedMcpServers` | The same, and a variable with no startup value and no `:-default` fills from settings files outside the repository, such as user or managed settings, which only ever widens what the entry matches | The entry still matches |
319| Entry list | Expands from | Expansion that would change a URL entry's scheme, host, or path scope |
320| - | - | - |
321| `allowedMcpServers` | The environment Claude Code started with, plus `env` values from managed settings | Claude Code ignores the entry |
322| `deniedMcpServers` | The same, and a variable with no startup value and no `:-default` fills from settings files outside the repository, such as user or managed settings, which only ever widens what the entry matches | The entry still matches |
323323
324324Requires Claude Code v2.1.219 or later.
325325
from line 363
363363 }
364364 ```
365365
366 | Server | Result |
367 | :---------------------------------------------------- | :------------------------------------------- |
368 | HTTP server at `https://mcp.example.com/api` | Allowed: matches URL pattern |
369 | HTTP server at `https://api.internal.example.com/mcp` | Allowed: matches wildcard subdomain |
370 | HTTP server at `https://external.example.com/mcp` | Blocked: doesn't match any URL pattern |
371 | Stdio server with any command | Blocked: no name or command entries to match |
366 | Server | Result |
367 | :- | :- |
368 | HTTP server at `https://mcp.example.com/api` | Allowed: matches URL pattern |
369 | HTTP server at `https://api.internal.example.com/mcp` | Allowed: matches wildcard subdomain |
370 | HTTP server at `https://external.example.com/mcp` | Blocked: doesn't match any URL pattern |
371 | Stdio server with any command | Blocked: no name or command entries to match |
372372</Accordion>
373373
374374<Accordion title="Command-only allowlist">
from line 380
380380 }
381381 ```
382382
383 | Server | Result |
384 | :---------------------------------------------------- | :-------------------------------- |
385 | Stdio server with `["npx", "-y", "approved-package"]` | Allowed: matches command |
386 | Stdio server with `["node", "server.js"]` | Blocked: doesn't match command |
387 | HTTP server named `my-api` | Blocked: no name entries to match |
383 | Server | Result |
384 | :- | :- |
385 | Stdio server with `["npx", "-y", "approved-package"]` | Allowed: matches command |
386 | Stdio server with `["node", "server.js"]` | Blocked: doesn't match command |
387 | HTTP server named `my-api` | Blocked: no name entries to match |
388388</Accordion>
389389
390390<Accordion title="Mixed name and command allowlist">
from line 397
397397 }
398398 ```
399399
400 | Server | Result |
401 | :----------------------------------------------------------------------- | :-------------------------------------------------------------------- |
402 | Stdio server named `local-tool` with `["npx", "-y", "approved-package"]` | Allowed: matches command |
403 | Stdio server named `local-tool` with `["node", "server.js"]` | Blocked: command entries exist but doesn't match |
404 | Stdio server named `github` with `["node", "server.js"]` | Blocked: stdio servers must match commands when command entries exist |
405 | HTTP server named `github` | Allowed: matches name |
406 | HTTP server named `other-api` | Blocked: name doesn't match |
400 | Server | Result |
401 | :- | :- |
402 | Stdio server named `local-tool` with `["npx", "-y", "approved-package"]` | Allowed: matches command |
403 | Stdio server named `local-tool` with `["node", "server.js"]` | Blocked: command entries exist but doesn't match |
404 | Stdio server named `github` with `["node", "server.js"]` | Blocked: stdio servers must match commands when command entries exist |
405 | HTTP server named `github` | Allowed: matches name |
406 | HTTP server named `other-api` | Blocked: name doesn't match |
407407</Accordion>
408408
409409<Accordion title="Name-only allowlist">
from line 416
416416 }
417417 ```
418418
419 | Server | Result |
420 | :-------------------------------------------------- | :------------------------------- |
421 | Stdio server named `github` with any command | Allowed: no command restrictions |
419 | Server | Result |
420 | :- | :- |
421 | Stdio server named `github` with any command | Allowed: no command restrictions |
422422 | Stdio server named `internal-tool` with any command | Allowed: no command restrictions |
423 | HTTP server named `github` | Allowed: matches name |
424 | Any server named `other` | Blocked: name doesn't match |
423 | HTTP server named `github` | Allowed: matches name |
424 | Any server named `other` | Blocked: name doesn't match |
425425</Accordion>
426426
427427<Accordion title="Allowlist with denylist override">
from line 436
436436 }
437437 ```
438438
439 | Server | Result |
440 | :----------------------------------------------- | :-------------------------------------------------------- |
441 | HTTP server at `https://mcp.example.com/api` | Allowed: matches allowlist URL pattern, no denylist match |
442 | HTTP server at `https://staging.example.com/api` | Blocked: matches both, but the denylist takes precedence |
443 | HTTP server at `https://other.com/mcp` | Blocked: doesn't match the allowlist |
439 | Server | Result |
440 | :- | :- |
441 | HTTP server at `https://mcp.example.com/api` | Allowed: matches allowlist URL pattern, no denylist match |
442 | HTTP server at `https://staging.example.com/api` | Blocked: matches both, but the denylist takes precedence |
443 | HTTP server at `https://other.com/mcp` | Blocked: doesn't match the allowlist |
444444</Accordion>
445445
446446### Restrict the allowlist to managed settings only
from line 463
463463
464464For what users see at startup when `managed-mcp.json` is deployed and the session also has `--mcp-config` servers, see [Exclusive control with managed-mcp.json](#exclusive-control-with-managed-mcp-json). Use this table to recognize the other reports and to tell users what to expect before you roll out a change:
465465
466| Restriction | What the user sees |
467| :-------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------- |
468| `managed-mcp.json` is present and the user runs `claude mcp add` | `Cannot add MCP server: enterprise MCP configuration is active and has exclusive control over MCP servers` |
469| The server is on a denylist and the user runs `claude mcp add` | `Cannot add MCP server "<name>": server is explicitly blocked by enterprise policy` |
470| The server isn't on the allowlist and the user runs `claude mcp add` | `Cannot add MCP server "<name>": not allowed by enterprise policy` |
471| The user runs `claude mcp remove` on a server from `managedMcpServers` | `MCP server "<name>" is provided by your organization (managed settings) and cannot be removed locally.` |
472| A previously configured server is now blocked by policy | The server disappears from `/mcp` and `claude mcp list` |
466| Restriction | What the user sees |
467| :- | :- |
468| `managed-mcp.json` is present and the user runs `claude mcp add` | `Cannot add MCP server: enterprise MCP configuration is active and has exclusive control over MCP servers` |
469| The server is on a denylist and the user runs `claude mcp add` | `Cannot add MCP server "<name>": server is explicitly blocked by enterprise policy` |
470| The server isn't on the allowlist and the user runs `claude mcp add` | `Cannot add MCP server "<name>": not allowed by enterprise policy` |
471| The user runs `claude mcp remove` on a server from `managedMcpServers` | `MCP server "<name>" is provided by your organization (managed settings) and cannot be removed locally.` |
472| A previously configured server is now blocked by policy | The server disappears from `/mcp` and `claude mcp list` |
473473| A server becomes blocked while a session is running, and the user selects **Reconnect** or turns it back on in `/mcp` | [`MCP server <name> is blocked by enterprise managed policy`](/docs/en/errors#mcp-server-is-blocked-by-enterprise-managed-policy) |
474474
475475When a server silently disappears, the user gets no signal that policy is the reason, so tell affected users which servers are blocked when you roll out a new restriction.
from line 482
482482
483483Every file and setting this page covers, what it controls, and how to deliver it:
484484
485| Surface | What it controls | Where it lives | How to deliver |
486| :--------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
487| `managed-mcp.json` | Fixed server set, exclusive control | System path: `/Library/Application Support/ClaudeCode/`, `/etc/claude-code/`, or `C:\Program Files\ClaudeCode\` | MDM, GPO, fleet management, or any process with administrator privileges. Cannot be set through server-managed settings |
488| `managedMcpServers` | Remote servers provided to every user alongside their own | Managed settings sources only; the setting has no effect elsewhere | A [managed settings source](/docs/en/admin-setup#decide-how-settings-reach-devices): server-managed settings, a gateway policy, `managed-settings.json`, MDM profile, or HKLM registry |
489| `allowedMcpServers` | Allowlist of permitted servers | Any [settings scope](/docs/en/settings#where-settings-live); [How a server is evaluated](#how-a-server-is-evaluated) says how lists from several scopes and managed sources combine | For enforcement, a [managed settings source](/docs/en/admin-setup#decide-how-settings-reach-devices): server-managed settings, `managed-settings.json`, MDM profile, or registry |
490| `deniedMcpServers` | Denylist of blocked servers | Any settings scope; [How a server is evaluated](#how-a-server-is-evaluated) says how lists from several scopes and managed sources combine | Same as `allowedMcpServers` |
491| `allowManagedMcpServersOnly` | Locks the allowlist to managed sources only | Managed settings sources only; [Keys read from every admin source](/docs/en/managed-settings#keys-read-from-every-admin-source) says which managed sources can turn it on. The setting has no effect in other scopes | Same as `allowedMcpServers` |
492| `allowAllClaudeAiMcps` | Loads the claude.ai connectors Claude Code fetches itself alongside `managed-mcp.json`. [A `managed-mcp.json` on the host that runs a cloud session still suppresses that session's connectors](#allow-claude-ai-connectors-alongside-the-managed-set) | Managed settings sources only; the setting has no effect elsewhere | Same as `allowedMcpServers` |
485| Surface | What it controls | Where it lives | How to deliver |
486| :- | :- | :- | :- |
487| `managed-mcp.json` | Fixed server set, exclusive control | System path: `/Library/Application Support/ClaudeCode/`, `/etc/claude-code/`, or `C:\Program Files\ClaudeCode\` | MDM, GPO, fleet management, or any process with administrator privileges. Cannot be set through server-managed settings |
488| `managedMcpServers` | Remote servers provided to every user alongside their own | Managed settings sources only; the setting has no effect elsewhere | A [managed settings source](/docs/en/admin-setup#decide-how-settings-reach-devices): server-managed settings, a gateway policy, `managed-settings.json`, MDM profile, or HKLM registry |
489| `allowedMcpServers` | Allowlist of permitted servers | Any [settings scope](/docs/en/settings#where-settings-live); [How a server is evaluated](#how-a-server-is-evaluated) says how lists from several scopes and managed sources combine | For enforcement, a [managed settings source](/docs/en/admin-setup#decide-how-settings-reach-devices): server-managed settings, `managed-settings.json`, MDM profile, or registry |
490| `deniedMcpServers` | Denylist of blocked servers | Any settings scope; [How a server is evaluated](#how-a-server-is-evaluated) says how lists from several scopes and managed sources combine | Same as `allowedMcpServers` |
491| `allowManagedMcpServersOnly` | Locks the allowlist to managed sources only | Managed settings sources only; [Keys read from every admin source](/docs/en/managed-settings#keys-read-from-every-admin-source) says which managed sources can turn it on. The setting has no effect in other scopes | Same as `allowedMcpServers` |
492| `allowAllClaudeAiMcps` | Loads the claude.ai connectors Claude Code fetches itself alongside `managed-mcp.json`. [A `managed-mcp.json` on the host that runs a cloud session still suppresses that session's connectors](#allow-claude-ai-connectors-alongside-the-managed-set) | Managed settings sources only; the setting has no effect elsewhere | Same as `allowedMcpServers` |
493493
494494## Related resources
495495
managed-settings Changed · +62 / -62 lines
from line 62
6262
6363Pick a mechanism by how you already manage devices, using the table below.
6464
65| Mechanism | How you deliver it | When Claude Code reads it | Use it when |
66| :----------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------- |
67| [Server-managed settings](/docs/en/server-managed-settings) | In the claude.ai admin console, or on a self-hosted [Claude apps gateway](/docs/en/claude-apps-gateway) | Fetched at startup and polled hourly; see [changes that need approval](#where-and-when-a-policy-applies) | You want one place to change policy for a claude.ai organization without touching each machine |
68| MDM or OS-level policy | As a macOS configuration profile or a Windows `HKLM` registry value, through Jamf, Intune, Group Policy, or a similar tool; see [where each mechanism stores the policy](#where-each-mechanism-stores-the-policy) | Read at startup and checked for changes every 30 minutes | You already manage devices with MDM or Group Policy |
69| File-based | As `managed-settings.json` in a system directory on each machine; see [where each mechanism stores the policy](#where-each-mechanism-stores-the-policy) | Read at startup and reloaded when a file changes | Machines without MDM, Linux hosts, or images you build yourself |
70| HKCU registry, Windows and WSL | As a Windows `HKCU` registry value; see [where each mechanism stores the policy](#where-each-mechanism-stores-the-policy) | Read at startup and checked for changes every 30 minutes; Claude Code uses it only when no other managed source delivers a policy key and no [host-supplied parent settings](#let-an-embedding-host-add-policy) supply a restrictive key | You can't write the machine-level `HKLM` key |
65| Mechanism | How you deliver it | When Claude Code reads it | Use it when |
66| :- | :- | :- | :- |
67| [Server-managed settings](/docs/en/server-managed-settings) | In the claude.ai admin console, or on a self-hosted [Claude apps gateway](/docs/en/claude-apps-gateway) | Fetched at startup and polled hourly; see [changes that need approval](#where-and-when-a-policy-applies) | You want one place to change policy for a claude.ai organization without touching each machine |
68| MDM or OS-level policy | As a macOS configuration profile or a Windows `HKLM` registry value, through Jamf, Intune, Group Policy, or a similar tool; see [where each mechanism stores the policy](#where-each-mechanism-stores-the-policy) | Read at startup and checked for changes every 30 minutes | You already manage devices with MDM or Group Policy |
69| File-based | As `managed-settings.json` in a system directory on each machine; see [where each mechanism stores the policy](#where-each-mechanism-stores-the-policy) | Read at startup and reloaded when a file changes | Machines without MDM, Linux hosts, or images you build yourself |
70| HKCU registry, Windows and WSL | As a Windows `HKCU` registry value; see [where each mechanism stores the policy](#where-each-mechanism-stores-the-policy) | Read at startup and checked for changes every 30 minutes; Claude Code uses it only when no other managed source delivers a policy key and no [host-supplied parent settings](#let-an-embedding-host-add-policy) supply a restrictive key | You can't write the machine-level `HKLM` key |
7171
7272Starter templates for Jamf, Iru, Intune, and Group Policy are in the [MDM examples repository](https://github.com/anthropics/claude-code/tree/main/examples/mdm).
7373
from line 186
186186
187187This table shows how Claude Code combines each kind of key under `"merge"`. The [`managedSourcesBehavior` entry](/docs/en/settings-reference#managedsourcesbehavior) names every key in three of the rows: restriction allowlists, values taken whole, and keys read from the highest-ranked source only.
188188
189| Kind of key | How Claude Code combines it | Examples |
190| :-------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------- |
191| Lists | Combines the entries from every source | `permissions.allow`, `hooks`, `sandbox.network.allowedDomains`, `deniedMcpServers`, `deniedModels` |
192| Locks | Applies the strictest value any source sets; a looser value applies only from the highest-ranked source | `allowManagedHooksOnly`, `permissions.disableBypassPermissionsMode`, `crossSessionInbound`, `availableModelsMatch` |
193| Restriction allowlists | Takes the list whole from the highest-ranked source that sets it, without adding entries from lower sources | `availableModels`, `allowedMcpServers`, `strictKnownMarketplaces`, `allowedChannelPlugins`, and the `fallbackModel` chain |
194| Values taken whole | Takes the value whole from the highest-ranked source that sets it, without combining entries or fields from lower sources | `sandbox.credentials.awsPairs`, `sandbox.ripgrep` |
195| Provided MCP servers | Combines the server names from every source; when two sources set the same name, applies the higher-ranked source's whole entry | `managedMcpServers` |
196| Keys read from the highest-ranked source only | Ignores the key in every lower source, even when the highest-ranked source leaves it unset | Credential helpers such as `apiKeyHelper`, login pins such as `forceLoginOrgUUID`, `modelPicker`, `permissions.defaultMode` |
197| `env` | Merges per variable across admin sources under either setting, as [Keys read from every admin source](#keys-read-from-every-admin-source) describes | |
198| Every other key | Takes the value from the highest-ranked source that sets it | `model`, `cleanupPeriodDays` |
189| Kind of key | How Claude Code combines it | Examples |
190| :- | :- | :- |
191| Lists | Combines the entries from every source | `permissions.allow`, `hooks`, `sandbox.network.allowedDomains`, `deniedMcpServers`, `deniedModels` |
192| Locks | Applies the strictest value any source sets; a looser value applies only from the highest-ranked source | `allowManagedHooksOnly`, `permissions.disableBypassPermissionsMode`, `crossSessionInbound`, `availableModelsMatch` |
193| Restriction allowlists | Takes the list whole from the highest-ranked source that sets it, without adding entries from lower sources | `availableModels`, `allowedMcpServers`, `strictKnownMarketplaces`, `allowedChannelPlugins`, and the `fallbackModel` chain |
194| Values taken whole | Takes the value whole from the highest-ranked source that sets it, without combining entries or fields from lower sources | `sandbox.credentials.awsPairs`, `sandbox.ripgrep` |
195| Provided MCP servers | Combines the server names from every source; when two sources set the same name, applies the higher-ranked source's whole entry | `managedMcpServers` |
196| Keys read from the highest-ranked source only | Ignores the key in every lower source, even when the highest-ranked source leaves it unset | Credential helpers such as `apiKeyHelper`, login pins such as `forceLoginOrgUUID`, `modelPicker`, `permissions.defaultMode` |
197| `env` | Merges per variable across admin sources under either setting, as [Keys read from every admin source](#keys-read-from-every-admin-source) describes | |
198| Every other key | Takes the value from the highest-ranked source that sets it | `model`, `cleanupPeriodDays` |
199199
200200To confirm which sources combined on a machine, [read the `Setting sources` line in `/status`](#read-the-source-in-/status); that section says what each label means.
201201
from line 326
326326
327327A few enforcement keys aren't dropped when invalid. Claude Code enforces a stricter fallback until the value is fixed; the table shows what it enforces for each key:
328328
329| Field | Behavior when present but invalid |
330| :-------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
331| `allowedMcpServers` | Enforced as an empty allowlist until the value is fixed, so no MCP servers that users add are admitted. Servers your organization delivers through [`managedMcpServers`](/docs/en/settings-reference#managedmcpservers) still load, and `managed-mcp.json` servers load per [How a server is evaluated](/docs/en/managed-mcp#how-a-server-is-evaluated). An individual invalid entry is stripped and the valid subset is enforced. |
332| `allowedHttpHookUrls` | Claude Code enforces an empty managed [allowlist](/docs/en/settings-reference#allowedhttphookurls) until you fix the value, so an HTTP hook runs only if another settings file lists its URL. If only an individual entry is invalid, Claude Code strips that entry and enforces the rest. |
333| `httpHookAllowedEnvVars` | Claude Code enforces an empty managed [allowlist](/docs/en/settings-reference#httphookallowedenvvars) until you fix the value, so a header variable is interpolated only if another settings file names it. If only an individual entry is invalid, Claude Code strips that entry and enforces the rest. |
334| `allowedChannelPlugins` | Claude Code enforces an empty allowlist until you fix the value, so no channel plugin passed to `--channels` is admitted. If only an individual entry is invalid, it strips that entry and enforces the rest. |
335| `strictKnownMarketplaces` | Enforced as an empty allowlist until the value is fixed, so no [marketplace source](/docs/en/plugins/org#restrict-what-users-can-install) is admitted. An individual entry that is invalid or can't be enforced, such as a `hostPattern` regex that doesn't compile, is stripped and the valid subset is enforced. |
336| `allowManagedHooksOnly` | Treated as `true` until fixed: the [hook restrictions](/docs/en/settings-reference#allowmanagedhooksonly) apply and, unless `disableCommandPluginSources` is explicitly `false`, command-sourced plugins are disabled. |
337| `allowManagedMcpServersOnly` | Treated as `true`. |
338| `disableCommandPluginSources` | Treated as `true`, so command-sourced plugins stay disabled until the value is fixed. |
339| `disableSideloadFlags` | Treated as `true` until the value is fixed, with the effects listed for [`disableSideloadFlags`](/docs/en/settings-reference#disablesideloadflags). |
340| `availableModels` | Enforced as an empty allowlist until fixed, so only the Default model is available; a non-string entry is stripped and the valid subset enforced. |
341| `enforceAvailableModels` | Treated as `true`. |
342| [`availableModelsMatch`](/docs/en/settings-reference#availablemodelsmatch) | Treated as `exact` until the value is fixed. |
343| `syncClaudeAiPlugins` | Treated as `false`, so syncing of [claude.ai plugins](/docs/en/settings-reference#syncclaudeaiplugins) is off until the value is fixed. |
344| `forceLoginOrgUUID` | No organization is permitted to log in until the value is fixed. |
345| `gatewayInternalNetworks` | When the invalid value comes from the highest managed source on the machine, `/login` refuses every new [cloud gateway](/docs/en/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own) sign-in on that machine until the value is fixed. |
346| `crossSessionInbound` | Treated as `refuse`, the most restrictive value, so inbound [cross-session messages](/docs/en/cross-session-messaging#control-inbound-messages) are refused until the value is fixed. The developer sees [a warning](/docs/en/errors#crosssessioninbound-must-be-one-of-accept-hold-refuse). |
347| `deniedMcpServers` | An individual invalid entry is stripped and the valid subset is enforced. A wholly invalid value is dropped with a warning, since denying every server would block servers the policy never named. |
348| [`deniedModels`](/docs/en/settings-reference#deniedmodels) | A non-string entry is stripped and the rest of the list is enforced. A wholly invalid value is dropped with a warning and blocks no models until it is fixed. |
349| `blockedMarketplaces` | An individual invalid entry is stripped and the valid subset is enforced. An entry that parses but can never match, such as a `hostPattern` regex that doesn't compile, is kept with a warning. It blocks nothing until fixed, but [marketplace restrictions](/docs/en/plugins/org#restrict-what-users-can-install) stay active. A wholly invalid value is dropped with a warning, since blocking every marketplace would block sources the policy never named. |
350| `sandbox` | When one value inside the block is invalid, Claude Code doesn't drop the whole block. For what happens to each kind of invalid field, see [Invalid values inside `sandbox`](#invalid-values-inside-sandbox). |
351| `sandbox.credentials` | A recoverable invalid entry is degraded to `mode: "deny"` with a warning; an unrecoverable one is stripped; valid entries stay enforced. See [invalid credential entries](/docs/en/settings-reference#invalid-credential-entries-in-managed-settings) |
329| Field | Behavior when present but invalid |
330| :- | :- |
331| `allowedMcpServers` | Enforced as an empty allowlist until the value is fixed, so no MCP servers that users add are admitted. Servers your organization delivers through [`managedMcpServers`](/docs/en/settings-reference#managedmcpservers) still load, and `managed-mcp.json` servers load per [How a server is evaluated](/docs/en/managed-mcp#how-a-server-is-evaluated). An individual invalid entry is stripped and the valid subset is enforced. |
332| `allowedHttpHookUrls` | Claude Code enforces an empty managed [allowlist](/docs/en/settings-reference#allowedhttphookurls) until you fix the value, so an HTTP hook runs only if another settings file lists its URL. If only an individual entry is invalid, Claude Code strips that entry and enforces the rest. |
333| `httpHookAllowedEnvVars` | Claude Code enforces an empty managed [allowlist](/docs/en/settings-reference#httphookallowedenvvars) until you fix the value, so a header variable is interpolated only if another settings file names it. If only an individual entry is invalid, Claude Code strips that entry and enforces the rest. |
334| `allowedChannelPlugins` | Claude Code enforces an empty allowlist until you fix the value, so no channel plugin passed to `--channels` is admitted. If only an individual entry is invalid, it strips that entry and enforces the rest. |
335| `strictKnownMarketplaces` | Enforced as an empty allowlist until the value is fixed, so no [marketplace source](/docs/en/plugins/org#restrict-what-users-can-install) is admitted. An individual entry that is invalid or can't be enforced, such as a `hostPattern` regex that doesn't compile, is stripped and the valid subset is enforced. |
336| `allowManagedHooksOnly` | Treated as `true` until fixed: the [hook restrictions](/docs/en/settings-reference#allowmanagedhooksonly) apply and, unless `disableCommandPluginSources` is explicitly `false`, command-sourced plugins are disabled. |
337| `allowManagedMcpServersOnly` | Treated as `true`. |
338| `disableCommandPluginSources` | Treated as `true`, so command-sourced plugins stay disabled until the value is fixed. |
339| `disableSideloadFlags` | Treated as `true` until the value is fixed, with the effects listed for [`disableSideloadFlags`](/docs/en/settings-reference#disablesideloadflags). |
340| `availableModels` | Enforced as an empty allowlist until fixed, so only the Default model is available; a non-string entry is stripped and the valid subset enforced. |
341| `enforceAvailableModels` | Treated as `true`. |
342| [`availableModelsMatch`](/docs/en/settings-reference#availablemodelsmatch) | Treated as `exact` until the value is fixed. |
343| `syncClaudeAiPlugins` | Treated as `false`, so syncing of [claude.ai plugins](/docs/en/settings-reference#syncclaudeaiplugins) is off until the value is fixed. |
344| `forceLoginOrgUUID` | No organization is permitted to log in until the value is fixed. |
345| `gatewayInternalNetworks` | When the invalid value comes from the highest managed source on the machine, `/login` refuses every new [cloud gateway](/docs/en/claude-apps-gateway#allow-a-gateway-on-public-address-space-you-own) sign-in on that machine until the value is fixed. |
346| `crossSessionInbound` | Treated as `refuse`, the most restrictive value, so inbound [cross-session messages](/docs/en/cross-session-messaging#control-inbound-messages) are refused until the value is fixed. The developer sees [a warning](/docs/en/errors#crosssessioninbound-must-be-one-of-accept-hold-refuse). |
347| `deniedMcpServers` | An individual invalid entry is stripped and the valid subset is enforced. A wholly invalid value is dropped with a warning, since denying every server would block servers the policy never named. |
348| [`deniedModels`](/docs/en/settings-reference#deniedmodels) | A non-string entry is stripped and the rest of the list is enforced. A wholly invalid value is dropped with a warning and blocks no models until it is fixed. |
349| `blockedMarketplaces` | An individual invalid entry is stripped and the valid subset is enforced. An entry that parses but can never match, such as a `hostPattern` regex that doesn't compile, is kept with a warning. It blocks nothing until fixed, but [marketplace restrictions](/docs/en/plugins/org#restrict-what-users-can-install) stay active. A wholly invalid value is dropped with a warning, since blocking every marketplace would block sources the policy never named. |
350| `sandbox` | When one value inside the block is invalid, Claude Code doesn't drop the whole block. For what happens to each kind of invalid field, see [Invalid values inside `sandbox`](#invalid-values-inside-sandbox). |
351| `sandbox.credentials` | A recoverable invalid entry is degraded to `mode: "deny"` with a warning; an unrecoverable one is stripped; valid entries stay enforced. See [invalid credential entries](/docs/en/settings-reference#invalid-credential-entries-in-managed-settings) |
352352
353353`allowedHttpHookUrls` and `httpHookAllowedEnvVars` merge across settings files, so entries in your user, project, or local settings still apply while the managed list is empty.
354354
from line 381
381381
382382The table covers the permission, plugin, and delivery controls. For any key not listed here, the Scope column of the [settings reference](/docs/en/settings-reference#all-settings) index says whether it's managed-only; the remaining managed-only keys there include the gateway login URL, version, browser, mobile-simulator, SSH host, Desktop local-session, sandbox binary path, model pricing, model restriction, and CLAUDE.md controls.
383383
384| Setting | Description |
385| :-------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
386| [`allowAllClaudeAiMcps`](/docs/en/settings-reference#allowallclaudeaimcps) | Load the claude.ai connectors Claude Code fetches itself alongside a deployed `managed-mcp.json` instead of suppressing them |
387| [`allowedChannelPlugins`](/docs/en/settings-reference#allowedchannelplugins) | Allowlist of channel plugins that may push messages. Replaces the default Anthropic allowlist when set. Requires `channelsEnabled: true`. See [Restrict which channel plugins can run](/docs/en/channels#restrict-which-channel-plugins-can-run) |
388| [`allowManagedHooksOnly`](/docs/en/settings-reference#allowmanagedhooksonly) | When `true`, restricts which hooks run; see [what runs under `allowManagedHooksOnly`](/docs/en/settings-reference#what-runs-under-allowmanagedhooksonly) for the full effect list |
389| [`allowManagedMcpServersOnly`](/docs/en/settings-reference#allowmanagedmcpserversonly) | When `true`, only `allowedMcpServers` from managed settings are respected. `deniedMcpServers` still merges from all sources. See [Keys read from every admin source](#keys-read-from-every-admin-source) for which managed sources can set it, and [Managed MCP configuration](/docs/en/managed-mcp) |
390| [`allowManagedPermissionRulesOnly`](/docs/en/settings-reference#allowmanagedpermissionrulesonly) | Makes managed settings the only settings source of permission rules. The entry lists every source it ignores |
391| [`blockedMarketplaces`](/docs/en/settings-reference#blockedmarketplaces) | Blocklist of marketplace sources. Blocked sources are checked before downloading, so they never touch the filesystem. See [managed marketplace restrictions](/docs/en/plugins/org#restrict-what-users-can-install) |
392| [`channelsEnabled`](/docs/en/settings-reference#channelsenabled) | Allow [channels](/docs/en/channels) for the organization. See [enterprise controls](/docs/en/channels#enterprise-controls) for the default on each plan |
393| [`disableCommandPluginSources`](/docs/en/settings-reference#disablecommandpluginsources) | When `true`, blocks [`command` plugin sources](/docs/en/plugins/marketplace-reference#command-plugin-source) entirely, so the marketplace-declared command never runs. Also blocks marketplace [`headersHelper` commands](/docs/en/plugins/host-marketplace#authenticate-archive-downloads), except for a marketplace that managed settings themselves declare. When unset, follows `allowManagedHooksOnly`. Requires Claude Code v2.1.229 or later, and the `headersHelper` block requires v2.1.238 or later |
394| [`disableSideloadFlags`](/docs/en/settings-reference#disablesideloadflags) | Reject the `--plugin-dir`, `--plugin-url`, `--agents`, and `--mcp-config` flags at startup. In cloud sessions, Claude Code drops the MCP servers the server delivered through `--mcp-config`, other than in-process `type: "sdk"` entries, and starts the session. Requires Claude Code v2.1.193 or later |
395| [`forceRemoteSettingsRefresh`](/docs/en/settings-reference#forceremotesettingsrefresh) | When `true`, blocks CLI startup until remote managed settings are freshly fetched and exits if the fetch fails. See [fail-closed enforcement](/docs/en/server-managed-settings#enforce-fail-closed-startup) |
396| [`managedMcpServers`](/docs/en/settings-reference#managedmcpservers) | Remote MCP servers provided to every user alongside their own. It provides servers rather than locking anything down. See [Provide servers through managed settings](/docs/en/managed-mcp#provide-servers-through-managed-settings). Requires Claude Code v2.1.259 or later |
397| [`managedSourcesBehavior`](/docs/en/settings-reference#managedsourcesbehavior) | Whether Claude Code applies only the highest-priority managed source or [composes every one of them](#compose-every-managed-source) |
398| [`parentSettingsBehavior`](/docs/en/settings-reference#parentsettingsbehavior) | Whether host-supplied parent settings merge under the managed policy |
399| [`pluginSuggestionMarketplaces`](/docs/en/settings-reference#pluginsuggestionmarketplaces) | Marketplaces whose plugins Claude Code may suggest to users |
400| [`pluginTrustMessage`](/docs/en/settings-reference#plugintrustmessage) | Custom message appended to the plugin trust warning shown before installation |
401| [`policyHelper`](/docs/en/settings-reference#policyhelper) | Executable that computes managed settings at startup; see [Compute managed settings with a policy helper](/docs/en/settings-reference#policyhelper) |
402| [`sandbox.filesystem.allowManagedReadPathsOnly`](/docs/en/settings-reference#sandbox-filesystem-allowmanagedreadpathsonly) | When `true`, only `filesystem.allowRead` paths from managed settings are respected. `denyRead` still merges from all sources |
403| [`sandbox.network.allowManagedDomainsOnly`](/docs/en/settings-reference#sandbox-network-allowmanageddomainsonly) | Honor only managed `allowedDomains` and `WebFetch(domain:...)` allow rules; block other domains without prompting |
404| [`strictKnownMarketplaces`](/docs/en/settings-reference#strictknownmarketplaces) | Controls which plugin marketplace sources users can add and install plugins from. See [managed marketplace restrictions](/docs/en/plugins/org#restrict-what-users-can-install) |
405| [`strictPluginOnlyCustomization`](/docs/en/settings-reference#strictpluginonlycustomization) | Block skills, agents, hooks, and MCP servers from user and project sources; `true` locks all four, an array names which |
406| [`wslInheritsWindowsSettings`](/docs/en/settings-reference#wslinheritswindowssettings) | When set in the HKLM registry or a file under `C:\Program Files\ClaudeCode`, have WSL read the Windows policy chain, and read `/etc/claude-code` only when no managed settings file or drop-in under that directory delivers a [policy key](#how-claude-code-combines-managed-sources); the entry gives the order |
384| Setting | Description |
385| :- | :- |
386| [`allowAllClaudeAiMcps`](/docs/en/settings-reference#allowallclaudeaimcps) | Load the claude.ai connectors Claude Code fetches itself alongside a deployed `managed-mcp.json` instead of suppressing them |
387| [`allowedChannelPlugins`](/docs/en/settings-reference#allowedchannelplugins) | Allowlist of channel plugins that may push messages. Replaces the default Anthropic allowlist when set. Requires `channelsEnabled: true`. See [Restrict which channel plugins can run](/docs/en/channels#restrict-which-channel-plugins-can-run) |
388| [`allowManagedHooksOnly`](/docs/en/settings-reference#allowmanagedhooksonly) | When `true`, restricts which hooks run; see [what runs under `allowManagedHooksOnly`](/docs/en/settings-reference#what-runs-under-allowmanagedhooksonly) for the full effect list |
389| [`allowManagedMcpServersOnly`](/docs/en/settings-reference#allowmanagedmcpserversonly) | When `true`, only `allowedMcpServers` from managed settings are respected. `deniedMcpServers` still merges from all sources. See [Keys read from every admin source](#keys-read-from-every-admin-source) for which managed sources can set it, and [Managed MCP configuration](/docs/en/managed-mcp) |
390| [`allowManagedPermissionRulesOnly`](/docs/en/settings-reference#allowmanagedpermissionrulesonly) | Makes managed settings the only settings source of permission rules. The entry lists every source it ignores |
391| [`blockedMarketplaces`](/docs/en/settings-reference#blockedmarketplaces) | Blocklist of marketplace sources. Blocked sources are checked before downloading, so they never touch the filesystem. See [managed marketplace restrictions](/docs/en/plugins/org#restrict-what-users-can-install) |
392| [`channelsEnabled`](/docs/en/settings-reference#channelsenabled) | Allow [channels](/docs/en/channels) for the organization. See [enterprise controls](/docs/en/channels#enterprise-controls) for the default on each plan |
393| [`disableCommandPluginSources`](/docs/en/settings-reference#disablecommandpluginsources) | When `true`, blocks [`command` plugin sources](/docs/en/plugins/marketplace-reference#command-plugin-source) entirely, so the marketplace-declared command never runs. Also blocks marketplace [`headersHelper` commands](/docs/en/plugins/host-marketplace#authenticate-archive-downloads), except for a marketplace that managed settings themselves declare. When unset, follows `allowManagedHooksOnly`. Requires Claude Code v2.1.229 or later, and the `headersHelper` block requires v2.1.238 or later |
394| [`disableSideloadFlags`](/docs/en/settings-reference#disablesideloadflags) | Reject the `--plugin-dir`, `--plugin-url`, `--agents`, and `--mcp-config` flags at startup. In cloud sessions, Claude Code drops the MCP servers the server delivered through `--mcp-config`, other than in-process `type: "sdk"` entries, and starts the session. Requires Claude Code v2.1.193 or later |
395| [`forceRemoteSettingsRefresh`](/docs/en/settings-reference#forceremotesettingsrefresh) | When `true`, blocks CLI startup until remote managed settings are freshly fetched and exits if the fetch fails. See [fail-closed enforcement](/docs/en/server-managed-settings#enforce-fail-closed-startup) |
396| [`managedMcpServers`](/docs/en/settings-reference#managedmcpservers) | Remote MCP servers provided to every user alongside their own. It provides servers rather than locking anything down. See [Provide servers through managed settings](/docs/en/managed-mcp#provide-servers-through-managed-settings). Requires Claude Code v2.1.259 or later |
397| [`managedSourcesBehavior`](/docs/en/settings-reference#managedsourcesbehavior) | Whether Claude Code applies only the highest-priority managed source or [composes every one of them](#compose-every-managed-source) |
398| [`parentSettingsBehavior`](/docs/en/settings-reference#parentsettingsbehavior) | Whether host-supplied parent settings merge under the managed policy |
399| [`pluginSuggestionMarketplaces`](/docs/en/settings-reference#pluginsuggestionmarketplaces) | Marketplaces whose plugins Claude Code may suggest to users |
400| [`pluginTrustMessage`](/docs/en/settings-reference#plugintrustmessage) | Custom message appended to the plugin trust warning shown before installation |
401| [`policyHelper`](/docs/en/settings-reference#policyhelper) | Executable that computes managed settings at startup; see [Compute managed settings with a policy helper](/docs/en/settings-reference#policyhelper) |
402| [`sandbox.filesystem.allowManagedReadPathsOnly`](/docs/en/settings-reference#sandbox-filesystem-allowmanagedreadpathsonly) | When `true`, only `filesystem.allowRead` paths from managed settings are respected. `denyRead` still merges from all sources |
403| [`sandbox.network.allowManagedDomainsOnly`](/docs/en/settings-reference#sandbox-network-allowmanageddomainsonly) | Honor only managed `allowedDomains` and `WebFetch(domain:...)` allow rules; block other domains without prompting |
404| [`strictKnownMarketplaces`](/docs/en/settings-reference#strictknownmarketplaces) | Controls which plugin marketplace sources users can add and install plugins from. See [managed marketplace restrictions](/docs/en/plugins/org#restrict-what-users-can-install) |
405| [`strictPluginOnlyCustomization`](/docs/en/settings-reference#strictpluginonlycustomization) | Block skills, agents, hooks, and MCP servers from user and project sources; `true` locks all four, an array names which |
406| [`wslInheritsWindowsSettings`](/docs/en/settings-reference#wslinheritswindowssettings) | When set in the HKLM registry or a file under `C:\Program Files\ClaudeCode`, have WSL read the Windows policy chain, and read `/etc/claude-code` only when no managed settings file or drop-in under that directory delivers a [policy key](#how-claude-code-combines-managed-sources); the entry gives the order |
407407
408408<Note>
409409 On Team and Enterprise plans, an Owner enables or disables [Remote Control](/docs/en/remote-control) and [cloud sessions](/docs/en/claude-code-on-the-web) organization-wide in [Claude Code admin settings](https://claude.ai/admin-settings/claude-code). Remote Control can additionally be disabled per device with the [`disableRemoteControl`](/docs/en/settings-reference#disableremotecontrol) setting. Cloud sessions have no per-device managed settings key.
mcp Changed · +26 / -26 lines
from line 509
509509
510510MCP servers can be configured at three scopes. The scope you choose controls which projects the server loads in and whether the configuration is shared with your team. Administrators can also deploy or provide servers for every user via [managed configuration](#managed-mcp-configuration).
511511
512| Scope | Loads in | Shared with team | Stored in |
513| ------------------------- | -------------------- | ------------------------ | --------------------------- |
514| [Local](#local-scope) | Current project only | No | `~/.claude.json` |
512| Scope | Loads in | Shared with team | Stored in |
513| - | - | - | - |
514| [Local](#local-scope) | Current project only | No | `~/.claude.json` |
515515| [Project](#project-scope) | Current project only | Yes, via version control | `.mcp.json` in project root |
516| [User](#user-scope) | All your projects | No | `~/.claude.json` |
516| [User](#user-scope) | All your projects | No | `~/.claude.json` |
517517
518518### Local scope
519519
from line 982
982982
983983Claude Code sets these environment variables when executing the helper:
984984
985| Variable | Value |
986| :---------------------------- | :------------------------------------------------------------------------------------------------------------ |
987| `CLAUDE_CODE_MCP_SERVER_NAME` | the name of the MCP server |
988| `CLAUDE_CODE_MCP_SERVER_URL` | the URL of the MCP server |
989| `CLAUDE_PLUGIN_ROOT` | the plugin's root directory. Set only when a [plugin](/docs/en/plugins/components#mcp-servers) provides the server |
985| Variable | Value |
986| :- | :- |
987| `CLAUDE_CODE_MCP_SERVER_NAME` | the name of the MCP server |
988| `CLAUDE_CODE_MCP_SERVER_URL` | the URL of the MCP server |
989| `CLAUDE_PLUGIN_ROOT` | the plugin's root directory. Set only when a [plugin](/docs/en/plugins/components#mcp-servers) provides the server |
990990
991991Use these to write a single helper script that serves multiple MCP servers.
992992
from line 996
996996
997997Claude Code picks the `headersHelper` command's working directory from the configuration that declares the server. A `cd` that Claude runs in Bash doesn't move it, and [`/cd`](/docs/en/permissions#move-the-session-to-another-directory) moves it only for servers that run from the session's primary working directory. Each row below gives the directory that a relative path in your `headersHelper` command resolves against.
998998
999| Where you configured the server | Working directory |
1000| :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------- |
1001| A [plugin](/docs/en/plugins/components#mcp-servers) | The plugin's root directory. Requires Claude Code v2.1.195 or later |
1002| A project `.mcp.json` or a [local-scope](#local-scope) server | The project directory the server is declared in |
1003| An agent file in your project, a server from the SDK's `mcpServers` option or `setMcpServers()` method, or [`--mcp-config`](/docs/en/cli-reference) | The session's [primary working directory](/docs/en/permissions#working-directories) |
999| Where you configured the server | Working directory |
1000| :- | :- |
1001| A [plugin](/docs/en/plugins/components#mcp-servers) | The plugin's root directory. Requires Claude Code v2.1.195 or later |
1002| A project `.mcp.json` or a [local-scope](#local-scope) server | The project directory the server is declared in |
1003| An agent file in your project, a server from the SDK's `mcpServers` option or `setMcpServers()` method, or [`--mcp-config`](/docs/en/cli-reference) | The session's [primary working directory](/docs/en/permissions#working-directories) |
10041004| [User scope](#user-scope), [managed MCP](/docs/en/managed-mcp), a [claude.ai connector](#use-mcp-servers-from-claude-ai), or an agent file from outside your project, including one from an `--add-dir` directory | Your configuration directory, `~/.claude` unless you set [`CLAUDE_CONFIG_DIR`](/docs/en/env-vars) |
10051005
10061006Before v2.1.238, Claude Code also ran the helpers of user-scope, managed, and claude.ai connector servers, and of agent files from outside your project, from the directory you started it in.
from line 1155
11551155
11561156Which settings govern a claude.ai connector depends on where your session runs, because only some sessions fetch connectors from claude.ai themselves. Each row below names how connectors arrive in one kind of session and what controls them there. The desktop app's [WSL sessions](/docs/en/desktop-wsl#what-works-in-a-wsl-session) have no row because connectors aren't available in them yet.
11571157
1158| Where the session runs | How connectors arrive | What governs them |
1159| :------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1160| Terminal, [VS Code](/docs/en/vs-code), [JetBrains](/docs/en/jetbrains), and [Agent SDK](/docs/en/agent-sdk/claude-code-features) sessions | Claude Code fetches them from claude.ai | The settings in this section and [managed MCP configuration](/docs/en/managed-mcp) |
1161| [Cloud sessions](/docs/en/claude-code-on-the-web) | The cloud host passes them in | Your claude.ai organization settings, plus the [allowlist and denylist](/docs/en/managed-mcp#policy-based-control-with-allowlists-and-denylists) settings that reach the session and any `managed-mcp.json` on the host that runs it |
1162| The [desktop app](/docs/en/desktop)'s local and SSH sessions | The desktop app delivers them in-process | `blocked` entries in your organization's [connector tool controls](#organization-controls-on-connector-tools) |
1158| Where the session runs | How connectors arrive | What governs them |
1159| :- | :- | :- |
1160| Terminal, [VS Code](/docs/en/vs-code), [JetBrains](/docs/en/jetbrains), and [Agent SDK](/docs/en/agent-sdk/claude-code-features) sessions | Claude Code fetches them from claude.ai | The settings in this section and [managed MCP configuration](/docs/en/managed-mcp) |
1161| [Cloud sessions](/docs/en/claude-code-on-the-web) | The cloud host passes them in | Your claude.ai organization settings, plus the [allowlist and denylist](/docs/en/managed-mcp#policy-based-control-with-allowlists-and-denylists) settings that reach the session and any `managed-mcp.json` on the host that runs it |
1162| The [desktop app](/docs/en/desktop)'s local and SSH sessions | The desktop app delivers them in-process | `blocked` entries in your organization's [connector tool controls](#organization-controls-on-connector-tools) |
11631163
11641164[`disableClaudeAiConnectors`](#disable-claude-ai-connectors), `ENABLE_CLAUDEAI_MCP_SERVERS`, and [`allowAllClaudeAiMcps`](/docs/en/settings-reference#allowallclaudeaimcps) act only on the first row, the connectors Claude Code fetches itself. The other two rows differ from it in these ways:
11651165
from line 1455
14551455
14561456Control tool search behavior with the `ENABLE_TOOL_SEARCH` environment variable:
14571457
1458| Value | Behavior |
1459| :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1460| (unset) | All MCP tools deferred and loaded on demand. Falls back to loading upfront on Google Cloud's Agent Platform models earlier than the Claude 4.5 generation, when `ANTHROPIC_BASE_URL` is a non-first-party host, or on a Microsoft Foundry deployment hosted on Azure |
1461| `true` | All MCP tools deferred, except on a Microsoft Foundry deployment hosted on Azure, where the server-side rejection still forces upfront loading, and on Google Cloud's Agent Platform models earlier than the Claude 4.5 generation, where Claude Code keeps loading tools upfront. Claude Code sends the beta header through proxies, and requests fail on proxies that don't support `tool_reference` blocks |
1462| `auto` | Threshold mode: Claude Code loads the tools it would otherwise defer upfront while their definitions total less than 10% of the context window, and defers all of them once the definitions reach 10% |
1463| `auto:N` | Threshold mode with a custom percentage, where `N` is 0-100. For example, `auto:5` for 5% |
1464| `false` | All MCP tools loaded upfront, no deferral |
1458| Value | Behavior |
1459| :- | :- |
1460| (unset) | All MCP tools deferred and loaded on demand. Falls back to loading upfront on Google Cloud's Agent Platform models earlier than the Claude 4.5 generation, when `ANTHROPIC_BASE_URL` is a non-first-party host, or on a Microsoft Foundry deployment hosted on Azure |
1461| `true` | All MCP tools deferred, except on a Microsoft Foundry deployment hosted on Azure, where the server-side rejection still forces upfront loading, and on Google Cloud's Agent Platform models earlier than the Claude 4.5 generation, where Claude Code keeps loading tools upfront. Claude Code sends the beta header through proxies, and requests fail on proxies that don't support `tool_reference` blocks |
1462| `auto` | Threshold mode: Claude Code loads the tools it would otherwise defer upfront while their definitions total less than 10% of the context window, and defers all of them once the definitions reach 10% |
1463| `auto:N` | Threshold mode with a custom percentage, where `N` is 0-100. For example, `auto:5` for 5% |
1464| `false` | All MCP tools loaded upfront, no deferral |
14651465
14661466```bash theme={null}
14671467# Use a custom 5% threshold
mcp-quickstart Changed · +14 / -14 lines
from line 52
5252
5353 The server appears with a status indicator:
5454
55 | Status | Meaning |
56 | :------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
57 | `✔ Connected` | Ready to use. This is what you should see for `claude-code-docs` |
58 | `! Connected · tools fetch failed` | The server connected but couldn't list its tools. Run `claude mcp get <name>` for the error detail |
59 | `! Needs authentication` | The server is reachable but needs a browser sign-in, or a token passed with `--header`. See [Connect a server that requires sign-in](#connect-a-server-that-requires-sign-in) |
60 | `✘ Failed to connect` | Server didn't respond. See [Troubleshooting](#troubleshooting) |
61 | `✘ Connection error` | The connection attempt threw an error. See [Troubleshooting](#troubleshooting) |
62 | ``⏸ Pending approval (run `claude` to approve)`` | A project-scoped server you haven't approved yet. See [Edit .mcp.json directly](#edit-mcp-json-directly) |
63 | `⊘ Disabled for this project (re-enable via /mcp)` | A server turned off for this project by the project's `disabledMcpServers` list. See [Disable a server without removing it](/docs/en/mcp#disable-a-server-without-removing-it) |
55 | Status | Meaning |
56 | :- | :- |
57 | `✔ Connected` | Ready to use. This is what you should see for `claude-code-docs` |
58 | `! Connected · tools fetch failed` | The server connected but couldn't list its tools. Run `claude mcp get <name>` for the error detail |
59 | `! Needs authentication` | The server is reachable but needs a browser sign-in, or a token passed with `--header`. See [Connect a server that requires sign-in](#connect-a-server-that-requires-sign-in) |
60 | `✘ Failed to connect` | Server didn't respond. See [Troubleshooting](#troubleshooting) |
61 | `✘ Connection error` | The connection attempt threw an error. See [Troubleshooting](#troubleshooting) |
62 | ``⏸ Pending approval (run `claude` to approve)`` | A project-scoped server you haven't approved yet. See [Edit .mcp.json directly](#edit-mcp-json-directly) |
63 | `⊘ Disabled for this project (re-enable via /mcp)` | A server turned off for this project by the project's `disabledMcpServers` list. See [Disable a server without removing it](/docs/en/mcp#disable-a-server-without-removing-it) |
6464
6565 Some legacy Windows consoles, such as the default console on Windows 10, don't support these Unicode glyphs and show `√` and `×` in place of `✔` and `✘`.
6666 </Step>
from line 116
116116
117117The `claude mcp add` command writes the server to one of three scopes, stored across two files, depending on the `--scope` flag. You don't need to edit these files directly, but knowing where they are helps with debugging and version control.
118118
119| Scope | File | Available to |
120| :-------- | :----------------------------------------------------- | :--------------------------------------- |
121| `local` | `~/.claude.json`, under the entry for this project | Only you, only this project. The default |
122| `project` | `.mcp.json` in your project root | Everyone who clones the project |
123| `user` | `~/.claude.json`, under the top-level `mcpServers` key | Only you, all projects |
119| Scope | File | Available to |
120| :- | :- | :- |
121| `local` | `~/.claude.json`, under the entry for this project | Only you, only this project. The default |
122| `project` | `.mcp.json` in your project root | Everyone who clones the project |
123| `user` | `~/.claude.json`, under the top-level `mcpServers` key | Only you, all projects |
124124
125125On Windows, `~/.claude.json` resolves to `%USERPROFILE%\.claude.json`, typically `C:\Users\YourName\.claude.json`. If you've set [`CLAUDE_CONFIG_DIR`](/docs/en/env-vars), Claude Code reads `.claude.json` from inside that directory instead.
126126
memory Changed · +46 / -46 lines
from line 19
1919
2020Claude Code has two complementary memory systems. Both are loaded at the start of every conversation. Claude treats them as context, not enforced configuration. To block an action regardless of what Claude decides, use a [PreToolUse hook](/docs/en/hooks-guide) instead. The more specific and concise your instructions, the more consistently Claude follows them.
2121
22| | CLAUDE.md files | Auto memory |
23| :------------------- | :------------------------------------------------ | :----------------------------------------------------------------------------------------------- |
24| **Who writes it** | You | Claude |
25| **What it contains** | Instructions and rules | Learnings and patterns |
26| **Scope** | Project, user, or org | Per repository, shared across worktrees |
27| **Loaded into** | Every session | Every session (first 200 lines or 25KB) |
28| **Use for** | Coding standards, workflows, project architecture | Your preferences, corrections you give Claude, project context Claude can't derive from the code |
22| | CLAUDE.md files | Auto memory |
23| :- | :- | :- |
24| **Who writes it** | You | Claude |
25| **What it contains** | Instructions and rules | Learnings and patterns |
26| **Scope** | Project, user, or org | Per repository, shared across worktrees |
27| **Loaded into** | Every session | Every session (first 200 lines or 25KB) |
28| **Use for** | Coding standards, workflows, project architecture | Your preferences, corrections you give Claude, project context Claude can't derive from the code |
2929
3030Use CLAUDE.md files when you want to guide Claude's behavior. Auto memory lets Claude learn from your corrections without manual effort.
3131
from line 50
5050
5151CLAUDE.md files can live in several locations, each with a different scope. The table below lists them in load order, from broadest scope to most specific, so a project instruction appears in context after a user instruction.
5252
53| Scope | Location | Purpose | Use case examples | Shared with |
54| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------- |
55| **Managed policy** | • macOS: `/Library/Application Support/ClaudeCode/CLAUDE.md`<br />• Linux and WSL: `/etc/claude-code/CLAUDE.md`<br />• Windows: `C:\Program Files\ClaudeCode\CLAUDE.md` | Organization-wide instructions managed by IT/DevOps | Company coding standards, security policies, compliance requirements | All users in organization |
56| **User instructions** | `~/.claude/CLAUDE.md` | Personal preferences for all projects | Code styling preferences, personal tooling shortcuts | Just you (all projects) |
57| **Project instructions** | `./CLAUDE.md` or `./.claude/CLAUDE.md`. See [AGENTS.md](#agents-md) for when `./AGENTS.md` loads instead of or alongside them | Team-shared instructions for the project | Project architecture, coding standards, common workflows | Team members via source control |
58| **Local instructions** | `./CLAUDE.local.md` | Personal project-specific preferences; add to `.gitignore` | Your sandbox URLs, preferred test data | Just you (current project) |
53| Scope | Location | Purpose | Use case examples | Shared with |
54| - | - | - | - | - |
55| **Managed policy** | • macOS: `/Library/Application Support/ClaudeCode/CLAUDE.md`<br />• Linux and WSL: `/etc/claude-code/CLAUDE.md`<br />• Windows: `C:\Program Files\ClaudeCode\CLAUDE.md` | Organization-wide instructions managed by IT/DevOps | Company coding standards, security policies, compliance requirements | All users in organization |
56| **User instructions** | `~/.claude/CLAUDE.md` | Personal preferences for all projects | Code styling preferences, personal tooling shortcuts | Just you (all projects) |
57| **Project instructions** | `./CLAUDE.md` or `./.claude/CLAUDE.md`. See [AGENTS.md](#agents-md) for when `./AGENTS.md` loads instead of or alongside them | Team-shared instructions for the project | Project architecture, coding standards, common workflows | Team members via source control |
58| **Local instructions** | `./CLAUDE.local.md` | Personal project-specific preferences; add to `.gitignore` | Your sandbox URLs, preferred test data | Just you (current project) |
5959
6060CLAUDE.md and CLAUDE.local.md files in the directory hierarchy above the working directory are loaded at launch. Files in subdirectories load on demand when Claude reads files in those directories. See [How CLAUDE.md files load](#how-claude-md-files-load) for the full resolution order.
6161
from line 198
198198
199199Use glob patterns in the `paths` field to match files by extension, directory, or any combination:
200200
201| Pattern | Matches |
202| ---------------------- | ---------------------------------------- |
203| `**/*.ts` | All TypeScript files in any directory |
204| `src/**/*` | All files under `src/` directory |
205| `*.md` | Markdown files in the project root |
201| Pattern | Matches |
202| - | - |
203| `**/*.ts` | All TypeScript files in any directory |
204| `src/**/*` | All files under `src/` directory |
205| `*.md` | Markdown files in the project root |
206206| `src/components/*.tsx` | React components in a specific directory |
207207
208208You can specify multiple patterns and use brace expansion to match multiple extensions in one pattern:
from line 228
228228
229229Configure a rule with YAML [frontmatter](/docs/en/glossary#frontmatter) between `---` markers at the top of the file. `paths` is the only field Claude Code reads from a rule; any other field is ignored without an error. Claude Code removes the frontmatter before loading the rule into context.
230230
231| Field | Required | Description |
232| :------ | :------- | :--------------------------------------------------------------------------------------------------------------------------- |
233| `paths` | No | Glob patterns that [scope the rule to matching files](#path-specific-rules). Accepts a YAML list or a comma-separated string |
231| Field | Required | Description |
232| :- | :- | :- |
233| `paths` | No | Glob patterns that [scope the rule to matching files](#path-specific-rules). Accepts a YAML list or a comma-separated string |
234234
235235If the YAML between the markers doesn't parse, Claude Code ignores the frontmatter and loads the rule as if it had no `paths`. Run `claude --debug` to see the parse error.
236236
from line 299
299299
300300A managed CLAUDE.md and [managed settings](/docs/en/managed-settings) serve different purposes. Use settings for technical enforcement and CLAUDE.md for behavioral guidance:
301301
302| Concern | Configure in |
303| :--------------------------------------------- | :-------------------------------------------------------- |
304| Block specific tools, commands, or file paths | Managed settings: `permissions.deny` |
305| Enforce sandbox isolation | Managed settings: `sandbox.enabled` |
306| Environment variables and API provider routing | Managed settings: `env` |
307| Login method and organization restrictions | Managed settings: `forceLoginMethod`, `forceLoginOrgUUID` |
308| Code style and quality guidelines | Managed CLAUDE.md |
309| Data handling and compliance reminders | Managed CLAUDE.md |
310| Behavioral instructions for Claude | Managed CLAUDE.md |
302| Concern | Configure in |
303| :- | :- |
304| Block specific tools, commands, or file paths | Managed settings: `permissions.deny` |
305| Enforce sandbox isolation | Managed settings: `sandbox.enabled` |
306| Environment variables and API provider routing | Managed settings: `env` |
307| Login method and organization restrictions | Managed settings: `forceLoginMethod`, `forceLoginOrgUUID` |
308| Code style and quality guidelines | Managed CLAUDE.md |
309| Data handling and compliance reminders | Managed CLAUDE.md |
310| Behavioral instructions for Claude | Managed CLAUDE.md |
311311
312312Settings rules are enforced by the client regardless of what Claude decides to do. CLAUDE.md instructions shape Claude's behavior but are not a hard enforcement layer.
313313
from line 336
336336
337337Claude Code can read [`AGENTS.md`](/docs/en/glossary#agents-md) as your project instructions, so a repository already set up for other coding agents works without adding a `CLAUDE.md`, an import, or a setting. This table shows what Claude reads by default for each combination of instruction files in your repository:
338338
339| Your repository has | Claude reads |
340| :-------------------------------------------------------------------------------------------- | :------------------------------------------------------------- |
341| An `AGENTS.md`, and no `CLAUDE.md` or `CLAUDE.local.md` in your working directory or above it | Your `AGENTS.md` |
342| An `AGENTS.md` and a `CLAUDE.md` or `CLAUDE.local.md` in your working directory or above it | Your `CLAUDE.md` files only |
343| A `CLAUDE.md` that already [imports `AGENTS.md`](#share-one-file-with-other-coding-tools) | Your `CLAUDE.md`, with `AGENTS.md` included through the import |
339| Your repository has | Claude reads |
340| :- | :- |
341| An `AGENTS.md`, and no `CLAUDE.md` or `CLAUDE.local.md` in your working directory or above it | Your `AGENTS.md` |
342| An `AGENTS.md` and a `CLAUDE.md` or `CLAUDE.local.md` in your working directory or above it | Your `CLAUDE.md` files only |
343| A `CLAUDE.md` that already [imports `AGENTS.md`](#share-one-file-with-other-coding-tools) | Your `CLAUDE.md`, with `AGENTS.md` included through the import |
344344
345345To change the default, for example to have Claude always read both files, read only `CLAUDE.md`, or read only your organization's managed instructions, [change the **Project instructions** setting](#choose-which-instruction-files-load).
346346
from line 370
370370
371371To change which files Claude reads, type `/config` in a Claude Code session to open the settings panel, then set **Project instructions** to one of these values:
372372
373| Value | What Claude reads |
374| :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
375| `claude-md-or-agents-md` | Your `CLAUDE.md` files, or your `AGENTS.md` files when you have no `CLAUDE.md` or `CLAUDE.local.md` in your working directory or above it. This is the default |
376| `claude-md-and-agents-md` | Your `CLAUDE.md` and `AGENTS.md` files together, each directory's `CLAUDE.md` files first and its `AGENTS.md` after them. Claude Code skips an `AGENTS.md` it has already loaded, so one that your `CLAUDE.md` imports or symlinks to isn't read twice |
377| `claude-md` | Your `CLAUDE.md` files only |
378| `managed-only` | Only your organization's managed `CLAUDE.md` and [auto memory](#auto-memory) at launch. Your project, local, and user `CLAUDE.md` files, your `.claude/rules/` files, and every `AGENTS.md` are left out. A subdirectory's `CLAUDE.md` and `.claude/rules/` files, and [path-scoped rules](#path-specific-rules), still load when Claude reads a file there |
373| Value | What Claude reads |
374| :- | :- |
375| `claude-md-or-agents-md` | Your `CLAUDE.md` files, or your `AGENTS.md` files when you have no `CLAUDE.md` or `CLAUDE.local.md` in your working directory or above it. This is the default |
376| `claude-md-and-agents-md` | Your `CLAUDE.md` and `AGENTS.md` files together, each directory's `CLAUDE.md` files first and its `AGENTS.md` after them. Claude Code skips an `AGENTS.md` it has already loaded, so one that your `CLAUDE.md` imports or symlinks to isn't read twice |
377| `claude-md` | Your `CLAUDE.md` files only |
378| `managed-only` | Only your organization's managed `CLAUDE.md` and [auto memory](#auto-memory) at launch. Your project, local, and user `CLAUDE.md` files, your `.claude/rules/` files, and every `AGENTS.md` are left out. A subdirectory's `CLAUDE.md` and `.claude/rules/` files, and [path-scoped rules](#path-specific-rules), still load when Claude reads a file there |
379379
380380You can also set the value in a settings file instead of `/config`. Add it under the built-in `agents-md` plugin's ID in [`pluginConfigs`](/docs/en/settings-reference#pluginconfigs), in `~/.claude/settings.json`, a `--settings` file, or [managed settings](/docs/en/managed-settings). Claude Code ignores it in project and local settings files. This example has Claude read both files:
381381
from line 405
405405
406406An `AGENTS.md` that Claude reads through the **Project instructions** setting differs from a `CLAUDE.md` in these places:
407407
408| | `CLAUDE.md` | `AGENTS.md` read through the setting |
409| :------------------------------------------------------------------------------------------------------------------------------------ | :--------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------ |
410| [`InstructionsLoaded` hooks](/docs/en/hooks#instructionsloaded) | Fire | Don't fire. They fire as usual for an `AGENTS.md` that a `CLAUDE.md` imports or symlinks to |
411| Directories you add with `--add-dir` while [`CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD`](#load-from-additional-directories) is set | Their `CLAUDE.md` loads | Their `AGENTS.md` doesn't load |
412| An `@path` import of a file outside your working directory | Claude Code asks you to approve [external imports](#import-additional-files) | Loads only if you already approved external imports for this project, with no prompt |
408| | `CLAUDE.md` | `AGENTS.md` read through the setting |
409| :- | :- | :- |
410| [`InstructionsLoaded` hooks](/docs/en/hooks#instructionsloaded) | Fire | Don't fire. They fire as usual for an `AGENTS.md` that a `CLAUDE.md` imports or symlinks to |
411| Directories you add with `--add-dir` while [`CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD`](#load-from-additional-directories) is set | Their `CLAUDE.md` loads | Their `AGENTS.md` doesn't load |
412| An `@path` import of a file outside your working directory | Claude Code asks you to approve [external imports](#import-additional-files) | Loads only if you already approved external imports for this project, with no prompt |
413413
414414### Remove an earlier AGENTS.md workaround
415415
mobile Changed · +6 / -6 lines
from line 32
3232
3333From the app you can start cloud sessions, open a project, drive a Claude Code session running on your computer, or message Dispatch a task. The app is the same for each; they differ in where the work happens.
3434
35| Feature | What you connect to | When to use |
36| :--------------------------------------------- | :-------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------- |
37| [Cloud sessions](/docs/en/claude-code-on-the-web) | A session on cloud infrastructure, Anthropic-managed by default | Your repository is on GitHub and the task should keep running after you put your phone away. See the [cloud quickstart](/docs/en/web-quickstart) to set up. |
38| [Projects](/docs/en/claude-projects) | A conversation where Claude coordinates parallel threads of work and reports back | You have a stream of related work rather than one task and want to see which threads finished or need you. |
39| [Remote Control](/docs/en/remote-control) | A Claude Code session running on your computer | The work needs your local filesystem, tools, or MCP servers. |
40| [Dispatch](/docs/en/desktop#sessions-from-dispatch) | The Desktop app on your computer | You want to message a task and let Dispatch decide how to run it. Requires a Pro or Max plan. |
35| Feature | What you connect to | When to use |
36| :- | :- | :- |
37| [Cloud sessions](/docs/en/claude-code-on-the-web) | A session on cloud infrastructure, Anthropic-managed by default | Your repository is on GitHub and the task should keep running after you put your phone away. See the [cloud quickstart](/docs/en/web-quickstart) to set up. |
38| [Projects](/docs/en/claude-projects) | A conversation where Claude coordinates parallel threads of work and reports back | You have a stream of related work rather than one task and want to see which threads finished or need you. |
39| [Remote Control](/docs/en/remote-control) | A Claude Code session running on your computer | The work needs your local filesystem, tools, or MCP servers. |
40| [Dispatch](/docs/en/desktop#sessions-from-dispatch) | The Desktop app on your computer | You want to message a task and let Dispatch decide how to run it. Requires a Pro or Max plan. |
4141
4242If your computer will be off, use cloud sessions or a project, which run in the cloud and continue with your laptop closed. Remote Control and Dispatch drive your own machine, so it needs to stay on with Claude Code or the Desktop app running. If your machine sleeps during a Remote Control session, Claude Code reconnects when the machine comes back online.
4343
model-config Changed · +82 / -82 lines
from line 23
2323
2424Use a model alias to select model settings without remembering exact version numbers:
2525
26| Model alias | Behavior |
27| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
28| **`default`** | Special value that clears any model override and reverts to the [runtime default for your account](#default-model-setting). Not itself a model alias |
29| **`best`** | Uses the model the [`fable` alias resolves to](#fable-alias-resolution) where Fable is available to you, otherwise the same model as `opus` |
30| **`fable`** | Uses the [Fable model for your provider](#fable-alias-resolution) for your hardest and longest-running tasks |
31| **`sonnet`** | Uses the latest Sonnet model for daily coding tasks |
32| **`opus`** | Uses the latest Opus model for complex reasoning tasks |
33| **`haiku`** | Uses the fast and efficient Haiku model for simple tasks |
26| Model alias | Behavior |
27| - | - |
28| **`default`** | Special value that clears any model override and reverts to the [runtime default for your account](#default-model-setting). Not itself a model alias |
29| **`best`** | Uses the model the [`fable` alias resolves to](#fable-alias-resolution) where Fable is available to you, otherwise the same model as `opus` |
30| **`fable`** | Uses the [Fable model for your provider](#fable-alias-resolution) for your hardest and longest-running tasks |
31| **`sonnet`** | Uses the latest Sonnet model for daily coding tasks |
32| **`opus`** | Uses the latest Opus model for complex reasoning tasks |
33| **`haiku`** | Uses the fast and efficient Haiku model for simple tasks |
3434| **`sonnet[1m]`** | Uses Sonnet with a [1 million token context window](https://platform.claude.com/docs/en/build-with-claude/context-windows#context-window-sizes-by-model) for long sessions. No effect when `sonnet` already resolves to Sonnet 5.5 or Sonnet 5 with their native 1M window; behind an [LLM gateway](/docs/en/llm-gateway), selects the 1M window for that model |
35| **`opus[1m]`** | Uses Opus with a [1 million token context window](https://platform.claude.com/docs/en/build-with-claude/context-windows#context-window-sizes-by-model) for long sessions |
36| **`opusplan`** | Special mode that uses `opus` during plan mode, then switches to `sonnet` for execution |
35| **`opus[1m]`** | Uses Opus with a [1 million token context window](https://platform.claude.com/docs/en/build-with-claude/context-windows#context-window-sizes-by-model) for long sessions |
36| **`opusplan`** | Special mode that uses `opus` during plan mode, then switches to `sonnet` for execution |
3737
3838The version that the `opus` and `sonnet` aliases resolve to depends on the provider:
3939
40| Provider | `opus` | `sonnet` |
41| :--------------------------------------------------- | :------- | :--------- |
42| Anthropic API | Opus 5.5 | Sonnet 5.5 |
40| Provider | `opus` | `sonnet` |
41| :- | :- | :- |
42| Anthropic API | Opus 5.5 | Sonnet 5.5 |
4343| [Claude Platform on AWS](/docs/en/claude-platform-on-aws) | Opus 5.5 | Sonnet 4.6 |
44| Amazon Bedrock, Google Cloud's Agent Platform | Opus 5.5 | Sonnet 4.5 |
45| Microsoft Foundry | Opus 4.6 | Sonnet 4.5 |
44| Amazon Bedrock, Google Cloud's Agent Platform | Opus 5.5 | Sonnet 4.5 |
45| Microsoft Foundry | Opus 4.6 | Sonnet 4.5 |
4646
4747<span id="fable-alias-resolution" />
4848
from line 267
267267
268268Every surface enforces the allowlist it receives. Which delivery mechanism reaches each surface differs:
269269
270| Delivery mechanism | CLI and IDE | Desktop local sessions | Web, mobile, and cloud sessions | Agent SDK and non-interactive | Cowork |
271| :---------------------------------------------------------------------------- | :---------- | :--------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------- | :---------------------- |
272| [Server-managed settings](/docs/en/server-managed-settings) from the admin console | Enforced | Enforced | Enforced | Enforced | Not delivered |
273| [MDM or managed settings files](/docs/en/managed-settings#delivery-mechanisms) | Enforced | Enforced | Not delivered in Anthropic-hosted environments; in [self-hosted environments](/docs/en/self-hosted-environments), enforced from the runner image per [how Claude Code combines managed sources](/docs/en/managed-settings#how-claude-code-combines-managed-sources) | Enforced | Enforced where deployed |
270| Delivery mechanism | CLI and IDE | Desktop local sessions | Web, mobile, and cloud sessions | Agent SDK and non-interactive | Cowork |
271| :- | :- | :- | :- | :- | :- |
272| [Server-managed settings](/docs/en/server-managed-settings) from the admin console | Enforced | Enforced | Enforced | Enforced | Not delivered |
273| [MDM or managed settings files](/docs/en/managed-settings#delivery-mechanisms) | Enforced | Enforced | Not delivered in Anthropic-hosted environments; in [self-hosted environments](/docs/en/self-hosted-environments), enforced from the runner image per [how Claude Code combines managed sources](/docs/en/managed-settings#how-claude-code-combines-managed-sources) | Enforced | Enforced where deployed |
274274
275275* [Cloud sessions](/docs/en/claude-code-on-the-web), including those you start from the Desktop app, run on Anthropic-managed VMs by default: settings deployed to your device do not reach them, so deliver the allowlist through server-managed settings. Sessions your organization routes to a [self-hosted environment](/docs/en/self-hosted-environments) run on your own compute and also read the managed settings file in the runner image. [How Claude Code combines managed sources](/docs/en/managed-settings#how-claude-code-combines-managed-sources) says when that file applies. A mid-session model switch in a cloud session is rejected when the requested model is excluded by the allowlist. When the `availableModels` list in your server-managed settings is non-empty, the server rejects a user's request to start a cloud session on a model the list excludes.
276276* Cowork, the agentic-work tab in the Claude Desktop app, runs its sessions on Claude Code but, by design, does not receive server-managed settings from the claude.ai admin console. A managed settings file applies to Cowork sessions when it is present where the session runs; remote Cowork sessions run on Anthropic-managed VMs, where a device-deployed file is not present.
from line 557
557557
558558The available effort levels depend on the model. Models not listed here do not support effort:
559559
560| Model | Levels |
561| :------------------------------------------------------------- | :-------------------------------------- |
562| Fable 5.1 and Fable 5 | `low`, `medium`, `high`, `xhigh`, `max` |
560| Model | Levels |
561| :- | :- |
562| Fable 5.1 and Fable 5 | `low`, `medium`, `high`, `xhigh`, `max` |
563563| Opus 5.5, Sonnet 5.5, Opus 5, Sonnet 5, Opus 4.8, and Opus 4.7 | `low`, `medium`, `high`, `xhigh`, `max` |
564| Opus 4.6 and Sonnet 4.6 | `low`, `medium`, `high`, `max` |
564| Opus 4.6 and Sonnet 4.6 | `low`, `medium`, `high`, `max` |
565565
566566If you set a level the active model does not support, Claude Code falls back to the highest supported level at or below the one you set. For example, `xhigh` runs as `high` on Opus 4.6. Your organization or your own settings can also cap the levels a model offers; see [Organization effort limits](#organization-effort-limits).
567567
from line 617
617617
618618Each level trades token spend against capability. The default suits most coding tasks; adjust when you want a different balance.
619619
620| Level | When to use it |
621| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
622| `low` | Quick exchanges where you review each result, such as brainstorming, a first sketch, or a small change like a rename |
623| `medium` | The default on Opus 5.5 and Sonnet 5.5, where it fits day-to-day engineering work with a clear scope, such as implementing a new feature. On other models, reduces token usage for cost-sensitive work that can trade off some intelligence |
624| `high` | Work where verification matters or edge cases are likely, such as fixing a bug in an existing codebase. The default on every model except Opus 5.5, Sonnet 5.5, and Opus 4.7 |
625| `xhigh` | Deeper reasoning at higher token spend. The default on Opus 4.7 |
626| `max` | Hard problems you want Claude to work through without you, such as finding security vulnerabilities. `max` may show diminishing returns and is prone to overthinking, so test before adopting it broadly |
627| `ultracode` | A Claude Code setting that plans a [dynamic workflow](/docs/en/workflows) for each substantive task with `xhigh` per-message reasoning |
620| Level | When to use it |
621| :- | :- |
622| `low` | Quick exchanges where you review each result, such as brainstorming, a first sketch, or a small change like a rename |
623| `medium` | The default on Opus 5.5 and Sonnet 5.5, where it fits day-to-day engineering work with a clear scope, such as implementing a new feature. On other models, reduces token usage for cost-sensitive work that can trade off some intelligence |
624| `high` | Work where verification matters or edge cases are likely, such as fixing a bug in an existing codebase. The default on every model except Opus 5.5, Sonnet 5.5, and Opus 4.7 |
625| `xhigh` | Deeper reasoning at higher token spend. The default on Opus 4.7 |
626| `max` | Hard problems you want Claude to work through without you, such as finding security vulnerabilities. `max` may show diminishing returns and is prone to overthinking, so test before adopting it broadly |
627| `ultracode` | A Claude Code setting that plans a [dynamic workflow](/docs/en/workflows) for each substantive task with `xhigh` per-message reasoning |
628628
629629In tests on Opus 5.5 and Fable 5.1, Claude at a higher level tested more edge cases and verified more of its work before answering. It also made more choices on its own. At a lower level, Claude returned a starting point sooner, which fits work where you review each result and steer the next step. To see the same tasks run at each level, read [Using Claude Code: Spending your effort](https://claude.dev/blog/spending-your-effort/) on the blog.
630630
from line 666
666666
667667Extended thinking is the reasoning Claude emits before responding. On models that support [adaptive reasoning](#adjust-effort-level), the effort level is the primary control for how much thinking happens; the settings below turn thinking on or off and control how it displays. With thinking turned off on the Anthropic API, Claude Code sends effort `high` instead of a higher level to models it knows [don't accept that combination](/docs/en/errors#effort-isnt-available-with-thinking-turned-off), such as Opus 5.
668668
669| Control | How to set it |
670| :-------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
671| Toggle for the current session | Press `Option+T` on macOS or `Alt+T` on Windows and Linux |
672| Set the global default | Run `/config` and toggle thinking mode. Saved as `alwaysThinkingEnabled` in `~/.claude/settings.json` |
669| Control | How to set it |
670| :- | :- |
671| Toggle for the current session | Press `Option+T` on macOS or `Alt+T` on Windows and Linux |
672| Set the global default | Run `/config` and toggle thinking mode. Saved as `alwaysThinkingEnabled` in `~/.claude/settings.json` |
673673| Disable through an environment variable | Set [`MAX_THINKING_TOKENS=0`](/docs/en/env-vars), which turns thinking off on the Anthropic API except on Opus 5.5, Sonnet 5.5, and Fable models. On [third-party providers](/docs/en/third-party-integrations), Claude Code omits the `thinking` parameter instead, and adaptive-reasoning models may still think. Other values apply only with a [fixed thinking budget](#adaptive-reasoning-and-fixed-thinking-budgets) |
674674
675675You can't turn thinking off on Opus 5.5, Sonnet 5.5, or the Fable models. The session toggle, `alwaysThinkingEnabled`, and `MAX_THINKING_TOKENS=0` have no effect there, and the model decides per step how much to think based on the effort level.
from line 684
684684
685685Opus 4.6 and Sonnet 4.6 reach 1M only through their `[1m]` variant, and access to that variant depends on your plan. On Max, Team, and Enterprise plans, including both Team Standard and Team Premium seats, Opus 4.6 with 1M context is included with your subscription. Sonnet 4.6 with 1M context requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) on every subscription plan, including Max.
686686
687| Plan | Opus 4.6 with 1M context | Sonnet 4.6 with 1M context |
688| ------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
689| Max, Team, and Enterprise | Included with subscription | Requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |
690| Pro | Requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) | Requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |
691| API and pay-as-you-go | Full access | Full access |
687| Plan | Opus 4.6 with 1M context | Sonnet 4.6 with 1M context |
688| - | - | - |
689| Max, Team, and Enterprise | Included with subscription | Requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |
690| Pro | Requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) | Requires [usage credits](https://support.claude.com/en/articles/12429409-extra-usage-for-paid-claude-plans) |
691| API and pay-as-you-go | Full access | Full access |
692692
693693Claude Code checks these plan requirements only when it connects to the Anthropic API directly. If you point `ANTHROPIC_BASE_URL` at an [LLM gateway](/docs/en/llm-gateway#subscriptions-and-gateways) and your saved claude.ai login stays the active credential, Claude Code doesn't check your plan's usage credits. The `[1m]` options stay available in `/model`, and the gateway decides whether the request succeeds. Before v2.1.229, Claude Code rejected `/model sonnet[1m]` in that configuration when it couldn't confirm usage credits on the account.
694694
from line 809
809809
810810Use the following environment variables to control the model names that the aliases map to. Each value must be a full model name, or the equivalent identifier for your API provider. To choose the model your sessions start on, set [`ANTHROPIC_DEFAULT_MODEL`](#set-a-default-model-for-new-sessions), which this table omits.
811811
812| Environment variable | Description |
813| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
814| `ANTHROPIC_DEFAULT_FABLE_MODEL` | The model to use for `fable`, and the model ID Claude Code recognizes as a Fable model for [automatic model fallback](#automatic-model-fallback) on third-party providers |
815| `ANTHROPIC_DEFAULT_OPUS_MODEL` | The model to use for `opus`, or for `opusplan` when Plan Mode is active. |
816| `ANTHROPIC_DEFAULT_SONNET_MODEL` | The model to use for `sonnet`, or for `opusplan` when Plan Mode is not active. |
817| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | The model to use for `haiku`, or [background functionality](/docs/en/costs#background-token-usage) |
818| `CLAUDE_CODE_SUBAGENT_MODEL` | The default model for [subagents](/docs/en/sub-agents#choose-a-model), [agent team](/docs/en/agent-teams#specify-teammates-and-models) teammates, and [workflow](/docs/en/workflows) agents that aren't assigned a model another way. Accepts an alias such as `haiku` or a full model name. A per-invocation model or a definition's `model` field, including `inherit`, takes precedence. To change that, set [`CLAUDE_CODE_SUBAGENT_MODEL_FORCE`](/docs/en/sub-agents#run-every-subagent-on-one-model) |
812| Environment variable | Description |
813| - | - |
814| `ANTHROPIC_DEFAULT_FABLE_MODEL` | The model to use for `fable`, and the model ID Claude Code recognizes as a Fable model for [automatic model fallback](#automatic-model-fallback) on third-party providers |
815| `ANTHROPIC_DEFAULT_OPUS_MODEL` | The model to use for `opus`, or for `opusplan` when Plan Mode is active. |
816| `ANTHROPIC_DEFAULT_SONNET_MODEL` | The model to use for `sonnet`, or for `opusplan` when Plan Mode is not active. |
817| `ANTHROPIC_DEFAULT_HAIKU_MODEL` | The model to use for `haiku`, or [background functionality](/docs/en/costs#background-token-usage) |
818| `CLAUDE_CODE_SUBAGENT_MODEL` | The default model for [subagents](/docs/en/sub-agents#choose-a-model), [agent team](/docs/en/agent-teams#specify-teammates-and-models) teammates, and [workflow](/docs/en/workflows) agents that aren't assigned a model another way. Accepts an alias such as `haiku` or a full model name. A per-invocation model or a definition's `model` field, including `inherit`, takes precedence. To change that, set [`CLAUDE_CODE_SUBAGENT_MODEL_FORCE`](/docs/en/sub-agents#run-every-subagent-on-one-model) |
819819
820820On third-party providers, [Customize pinned model display and capabilities](#customize-pinned-model-display-and-capabilities) describes what a pinned model's row in the `/model` picker shows.
821821
from line 836
836836
837837Use the following environment variables with version-specific model IDs for your provider:
838838
839| Provider | Example |
840| :---------------------------- | :------------------------------------------------------------------- |
841| Amazon Bedrock | `export ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-4-8'` |
842| Google Cloud's Agent Platform | `export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-8'` |
843| Microsoft Foundry | `export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-8'` |
839| Provider | Example |
840| :- | :- |
841| Amazon Bedrock | `export ANTHROPIC_DEFAULT_OPUS_MODEL='us.anthropic.claude-opus-4-8'` |
842| Google Cloud's Agent Platform | `export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-8'` |
843| Microsoft Foundry | `export ANTHROPIC_DEFAULT_OPUS_MODEL='claude-opus-4-8'` |
844844
845845Apply the same pattern for `ANTHROPIC_DEFAULT_FABLE_MODEL`, `ANTHROPIC_DEFAULT_SONNET_MODEL`, and `ANTHROPIC_DEFAULT_HAIKU_MODEL`. For current and legacy model IDs across all providers, see [Models overview](https://platform.claude.com/docs/en/about-claude/models/overview). To upgrade users to a new model version, update these environment variables and redeploy.
846846
from line 875
875875
876876These variables take effect on third-party providers such as Amazon Bedrock, Google Cloud's Agent Platform, and Microsoft Foundry. The `_NAME` and `_DESCRIPTION` variables also take effect when `ANTHROPIC_BASE_URL` points to an [LLM gateway](/docs/en/llm-gateway). They have no effect when connecting directly to `api.anthropic.com`.
877877
878| Environment variable | Description |
879| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
880| `ANTHROPIC_DEFAULT_OPUS_MODEL_NAME` | Display name for the pinned Opus model in the `/model` picker. When not set, the row shows the model's name if Claude Code recognizes the pinned ID, and the pinned ID otherwise |
881| `ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION` | Display description for the pinned Opus model in the `/model` picker. When not set, the row shows a default description that begins `Custom Opus model` |
882| `ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES` | Comma-separated list of capabilities the pinned Opus model supports |
878| Environment variable | Description |
879| - | - |
880| `ANTHROPIC_DEFAULT_OPUS_MODEL_NAME` | Display name for the pinned Opus model in the `/model` picker. When not set, the row shows the model's name if Claude Code recognizes the pinned ID, and the pinned ID otherwise |
881| `ANTHROPIC_DEFAULT_OPUS_MODEL_DESCRIPTION` | Display description for the pinned Opus model in the `/model` picker. When not set, the row shows a default description that begins `Custom Opus model` |
882| `ANTHROPIC_DEFAULT_OPUS_MODEL_SUPPORTED_CAPABILITIES` | Comma-separated list of capabilities the pinned Opus model supports |
883883
884884The same `_NAME`, `_DESCRIPTION`, and `_SUPPORTED_CAPABILITIES` suffixes are available for `ANTHROPIC_DEFAULT_SONNET_MODEL`, `ANTHROPIC_DEFAULT_HAIKU_MODEL`, `ANTHROPIC_DEFAULT_FABLE_MODEL`, and `ANTHROPIC_CUSTOM_MODEL_OPTION`.
885885
886886Claude Code enables features like [effort levels](#adjust-effort-level) and [extended thinking](#extended-thinking) by matching the model ID against known patterns. Provider-specific IDs such as Amazon Bedrock ARNs or custom deployment names often don't match these patterns, leaving supported features disabled. Set `_SUPPORTED_CAPABILITIES` to tell Claude Code which features the model actually supports:
887887
888| Capability value | Enables |
889| ---------------------- | ------------------------------------------------------------------------------- |
890| `effort` | [Effort levels](#adjust-effort-level) and the `/effort` command |
891| `xhigh_effort` | The `xhigh` effort level |
892| `max_effort` | The `max` effort level |
893| `thinking` | [Extended thinking](#extended-thinking) |
894| `adaptive_thinking` | Adaptive reasoning that dynamically allocates thinking based on task complexity |
895| `interleaved_thinking` | Thinking between tool calls |
888| Capability value | Enables |
889| - | - |
890| `effort` | [Effort levels](#adjust-effort-level) and the `/effort` command |
891| `xhigh_effort` | The `xhigh` effort level |
892| `max_effort` | The `max` effort level |
893| `thinking` | [Extended thinking](#extended-thinking) |
894| `adaptive_thinking` | Adaptive reasoning that dynamically allocates thinking based on task complexity |
895| `interleaved_thinking` | Thinking between tool calls |
896896
897897When `_SUPPORTED_CAPABILITIES` is set, Claude Code enables the listed capabilities and disables the unlisted ones for the matching pinned model. When the variable is unset, Claude Code falls back to built-in detection based on the model ID.
898898
from line 943
943943
944944Claude Code automatically uses [prompt caching](/docs/en/prompt-caching) to optimize performance and reduce costs. You can disable prompt caching globally or for specific model tiers:
945945
946| Environment variable | Description |
947| ------------------------------- | ------------------------------------------------------------------------------------------------------------- |
948| `DISABLE_PROMPT_CACHING` | Set to `1` to disable prompt caching for all models. Takes precedence over the per-model settings |
949| `DISABLE_PROMPT_CACHING_HAIKU` | Set to `1` to disable prompt caching for the [default Haiku model](/docs/en/prompt-caching#disable-prompt-caching) |
950| `DISABLE_PROMPT_CACHING_SONNET` | Set to `1` to disable prompt caching for Sonnet models only |
951| `DISABLE_PROMPT_CACHING_OPUS` | Set to `1` to disable prompt caching for Opus models only |
952| `DISABLE_PROMPT_CACHING_FABLE` | Set to `1` to disable prompt caching for Fable models only |
946| Environment variable | Description |
947| - | - |
948| `DISABLE_PROMPT_CACHING` | Set to `1` to disable prompt caching for all models. Takes precedence over the per-model settings |
949| `DISABLE_PROMPT_CACHING_HAIKU` | Set to `1` to disable prompt caching for the [default Haiku model](/docs/en/prompt-caching#disable-prompt-caching) |
950| `DISABLE_PROMPT_CACHING_SONNET` | Set to `1` to disable prompt caching for Sonnet models only |
951| `DISABLE_PROMPT_CACHING_OPUS` | Set to `1` to disable prompt caching for Opus models only |
952| `DISABLE_PROMPT_CACHING_FABLE` | Set to `1` to disable prompt caching for Fable models only |
953953
954954To choose the cache TTL for the main conversation and for subagents separately, see [choose the TTL yourself](/docs/en/prompt-caching#choose-the-ttl-yourself). For what triggers a cache miss, see [How Claude Code uses prompt caching](/docs/en/prompt-caching).
955955
from line 957
957957
958958This table lists the Claude Code version at which each model alias changed the model it resolves to, newest first.
959959
960| Version | Change |
961| :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
962| v2.1.284 | `sonnet` resolves to Sonnet 5.5 on the Anthropic API |
963| v2.1.280 | `opus` resolves to Opus 5.5 on the Anthropic API, Claude Platform on AWS, Amazon Bedrock, and Google Cloud's Agent Platform |
964| v2.1.257 | `fable` resolves to Fable 5.1, except in Claude apps gateway sessions |
965| v2.1.219 | `opus` resolves to Opus 5 on the Anthropic API, Claude Platform on AWS, Amazon Bedrock, and Agent Platform |
966| v2.1.207 | `opus` resolves to Opus 4.8 on Claude Platform on AWS, Amazon Bedrock, and Agent Platform |
967| v2.1.197 | `sonnet` resolves to Sonnet 5 on the Anthropic API |
968| v2.1.154 | `opus` resolves to Opus 4.8 on the Anthropic API |
969| Earlier | `opus` resolves to Opus 4.7 on Claude Platform on AWS and to Opus 4.6 on Amazon Bedrock and Agent Platform. `fable` resolves to Fable 5 on every provider |
960| Version | Change |
961| :- | :- |
962| v2.1.284 | `sonnet` resolves to Sonnet 5.5 on the Anthropic API |
963| v2.1.280 | `opus` resolves to Opus 5.5 on the Anthropic API, Claude Platform on AWS, Amazon Bedrock, and Google Cloud's Agent Platform |
964| v2.1.257 | `fable` resolves to Fable 5.1, except in Claude apps gateway sessions |
965| v2.1.219 | `opus` resolves to Opus 5 on the Anthropic API, Claude Platform on AWS, Amazon Bedrock, and Agent Platform |
966| v2.1.207 | `opus` resolves to Opus 4.8 on Claude Platform on AWS, Amazon Bedrock, and Agent Platform |
967| v2.1.197 | `sonnet` resolves to Sonnet 5 on the Anthropic API |
968| v2.1.154 | `opus` resolves to Opus 4.8 on the Anthropic API |
969| Earlier | `opus` resolves to Opus 4.7 on Claude Platform on AWS and to Opus 4.6 on Amazon Bedrock and Agent Platform. `fable` resolves to Fable 5 on every provider |
970970
monitoring-usage Changed · +190 / -190 lines
from line 95
9595
9696On machines with managed settings, see [How managed settings lock the OTLP destination](#how-managed-settings-lock-the-otlp-destination) for what Claude Code removes.
9797
98| Environment Variable | Description | Example Values |
99| --------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
100| `CLAUDE_CODE_ENABLE_TELEMETRY` | Enables telemetry collection (required) | `1` |
101| `OTEL_METRICS_EXPORTER` | Metrics exporter types, comma-separated. Use `none` to disable | `console`, `otlp`, `prometheus`, `none` |
102| `OTEL_LOGS_EXPORTER` | Logs/events exporter types, comma-separated. Use `none` to disable | `console`, `otlp`, `none` |
103| `OTEL_EXPORTER_OTLP_PROTOCOL` | Protocol for OTLP exporter, applies to all signals. Claude Code has no default protocol, so set this or the signal-specific protocol variable for each `otlp` exporter you enable | `grpc`, `http/json`, `http/protobuf` |
104| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP collector endpoint for all signals | `http://localhost:4317` |
105| `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` | Protocol for metrics, overrides general setting | `grpc`, `http/json`, `http/protobuf` |
106| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | OTLP metrics endpoint, overrides general setting | `http://localhost:4318/v1/metrics` |
107| `OTEL_EXPORTER_OTLP_LOGS_PROTOCOL` | Protocol for logs, overrides general setting | `grpc`, `http/json`, `http/protobuf` |
108| `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | OTLP logs endpoint, overrides general setting | `http://localhost:4318/v1/logs` |
109| `OTEL_EXPORTER_OTLP_HEADERS` | Authentication headers for OTLP | `Authorization=Bearer token` |
110| `OTEL_EXPORTER_OTLP_METRICS_HEADERS` | Authentication headers for metrics, merged with the general headers | `Authorization=Bearer token` |
111| `OTEL_EXPORTER_OTLP_LOGS_HEADERS` | Authentication headers for logs, merged with the general headers | `Authorization=Bearer token` |
112| `OTEL_METRIC_EXPORT_INTERVAL` | Export interval in milliseconds (default: 60000) | `5000`, `60000` |
113| `OTEL_LOGS_EXPORT_INTERVAL` | Logs export interval in milliseconds (default: 5000) | `1000`, `10000` |
114| `OTEL_LOG_USER_PROMPTS` | Enable logging of user prompt content (default: disabled) | `1` to enable |
115| `OTEL_LOG_ASSISTANT_RESPONSES` | Enable logging of assistant response text on `assistant_response` events (default: disabled). When unset, falls back to the value of `OTEL_LOG_USER_PROMPTS`. Requires Claude Code v2.1.193 or later | `1` to enable, `0` to keep redacted |
116| `OTEL_LOG_TOOL_DETAILS` | Enable logging of tool parameters and input arguments in tool events and trace span attributes: Bash commands, MCP server and tool names, skill names, user-authored workflow names, and tool input. Also enables custom, plugin, and MCP command names on `user_prompt` events (default: disabled). For Claude Desktop's built-in servers, in sessions Claude Desktop owns, `mcp_server_name`/`mcp_tool_name` emit on `tool_decision`/`tool_result` even with the flag off. The exception requires Claude Code v2.1.214 or later | `1` to enable |
117| `OTEL_LOG_TOOL_CONTENT` | Enable logging of tool content in the [`tool.output` span event](#tool-output-span-event) (default: disabled). Span attributes carry tool content under [their own gates](#new-context-gates). Requires [tracing](#traces-beta). Content is truncated at the content limit (60 KB by default) | `1` to enable |
118| `OTEL_LOG_MANAGED_SETTINGS` | Add the redacted managed settings, and a SHA-256 digest of the settings before redaction, to [managed settings resolved](#managed-settings-resolved-event) events (default: disabled). A value in project or local settings doesn't turn it on. Requires Claude Code v2.1.274 or later | `1` to enable |
119| `OTEL_LOG_RAW_API_BODIES` | Emit the full Anthropic Messages API request and response JSON as `api_request_body` / `api_response_body` log events (default: disabled). Bodies include the entire conversation history. Enabling this implies consent to everything `OTEL_LOG_USER_PROMPTS`, `OTEL_LOG_TOOL_DETAILS`, and `OTEL_LOG_TOOL_CONTENT` would reveal | `1` for inline bodies truncated at the content limit (60 KB by default), or `file:<dir>` for untruncated bodies on disk with a `body_ref` pointer in the event |
120| `CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH` | Content limit: the maximum length of content-bearing attributes such as model responses, tool content, system prompts, and raw API bodies, truncation marker included, in UTF-16 code units (default: 61440, i.e. 60 KB). The default is sized for backends that cap attribute values at 64 KB; raise it only if your backend accepts larger values, or lower it to cut telemetry volume. When an OpenTelemetry SDK attribute limit, `OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT` or one of its logrecord and span variants, is set lower, Claude Code truncates at that smaller value so the `[TRUNCATED ...]` marker stays within the SDK limit. Requires Claude Code v2.1.214 or later | `262144` |
121| `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` | Metrics temporality preference (default: `delta`). Set to `cumulative` if your backend expects cumulative temporality | `delta`, `cumulative` |
122| `CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS` | Interval for refreshing dynamic headers (default: 1740000ms / 29 minutes) | `900000` |
98| Environment Variable | Description | Example Values |
99| - | - | - |
100| `CLAUDE_CODE_ENABLE_TELEMETRY` | Enables telemetry collection (required) | `1` |
101| `OTEL_METRICS_EXPORTER` | Metrics exporter types, comma-separated. Use `none` to disable | `console`, `otlp`, `prometheus`, `none` |
102| `OTEL_LOGS_EXPORTER` | Logs/events exporter types, comma-separated. Use `none` to disable | `console`, `otlp`, `none` |
103| `OTEL_EXPORTER_OTLP_PROTOCOL` | Protocol for OTLP exporter, applies to all signals. Claude Code has no default protocol, so set this or the signal-specific protocol variable for each `otlp` exporter you enable | `grpc`, `http/json`, `http/protobuf` |
104| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP collector endpoint for all signals | `http://localhost:4317` |
105| `OTEL_EXPORTER_OTLP_METRICS_PROTOCOL` | Protocol for metrics, overrides general setting | `grpc`, `http/json`, `http/protobuf` |
106| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | OTLP metrics endpoint, overrides general setting | `http://localhost:4318/v1/metrics` |
107| `OTEL_EXPORTER_OTLP_LOGS_PROTOCOL` | Protocol for logs, overrides general setting | `grpc`, `http/json`, `http/protobuf` |
108| `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | OTLP logs endpoint, overrides general setting | `http://localhost:4318/v1/logs` |
109| `OTEL_EXPORTER_OTLP_HEADERS` | Authentication headers for OTLP | `Authorization=Bearer token` |
110| `OTEL_EXPORTER_OTLP_METRICS_HEADERS` | Authentication headers for metrics, merged with the general headers | `Authorization=Bearer token` |
111| `OTEL_EXPORTER_OTLP_LOGS_HEADERS` | Authentication headers for logs, merged with the general headers | `Authorization=Bearer token` |
112| `OTEL_METRIC_EXPORT_INTERVAL` | Export interval in milliseconds (default: 60000) | `5000`, `60000` |
113| `OTEL_LOGS_EXPORT_INTERVAL` | Logs export interval in milliseconds (default: 5000) | `1000`, `10000` |
114| `OTEL_LOG_USER_PROMPTS` | Enable logging of user prompt content (default: disabled) | `1` to enable |
115| `OTEL_LOG_ASSISTANT_RESPONSES` | Enable logging of assistant response text on `assistant_response` events (default: disabled). When unset, falls back to the value of `OTEL_LOG_USER_PROMPTS`. Requires Claude Code v2.1.193 or later | `1` to enable, `0` to keep redacted |
116| `OTEL_LOG_TOOL_DETAILS` | Enable logging of tool parameters and input arguments in tool events and trace span attributes: Bash commands, MCP server and tool names, skill names, user-authored workflow names, and tool input. Also enables custom, plugin, and MCP command names on `user_prompt` events (default: disabled). For Claude Desktop's built-in servers, in sessions Claude Desktop owns, `mcp_server_name`/`mcp_tool_name` emit on `tool_decision`/`tool_result` even with the flag off. The exception requires Claude Code v2.1.214 or later | `1` to enable |
117| `OTEL_LOG_TOOL_CONTENT` | Enable logging of tool content in the [`tool.output` span event](#tool-output-span-event) (default: disabled). Span attributes carry tool content under [their own gates](#new-context-gates). Requires [tracing](#traces-beta). Content is truncated at the content limit (60 KB by default) | `1` to enable |
118| `OTEL_LOG_MANAGED_SETTINGS` | Add the redacted managed settings, and a SHA-256 digest of the settings before redaction, to [managed settings resolved](#managed-settings-resolved-event) events (default: disabled). A value in project or local settings doesn't turn it on. Requires Claude Code v2.1.274 or later | `1` to enable |
119| `OTEL_LOG_RAW_API_BODIES` | Emit the full Anthropic Messages API request and response JSON as `api_request_body` / `api_response_body` log events (default: disabled). Bodies include the entire conversation history. Enabling this implies consent to everything `OTEL_LOG_USER_PROMPTS`, `OTEL_LOG_TOOL_DETAILS`, and `OTEL_LOG_TOOL_CONTENT` would reveal | `1` for inline bodies truncated at the content limit (60 KB by default), or `file:<dir>` for untruncated bodies on disk with a `body_ref` pointer in the event |
120| `CLAUDE_CODE_OTEL_CONTENT_MAX_LENGTH` | Content limit: the maximum length of content-bearing attributes such as model responses, tool content, system prompts, and raw API bodies, truncation marker included, in UTF-16 code units (default: 61440, i.e. 60 KB). The default is sized for backends that cap attribute values at 64 KB; raise it only if your backend accepts larger values, or lower it to cut telemetry volume. When an OpenTelemetry SDK attribute limit, `OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT` or one of its logrecord and span variants, is set lower, Claude Code truncates at that smaller value so the `[TRUNCATED ...]` marker stays within the SDK limit. Requires Claude Code v2.1.214 or later | `262144` |
121| `OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE` | Metrics temporality preference (default: `delta`). Set to `cumulative` if your backend expects cumulative temporality | `delta`, `cumulative` |
122| `CLAUDE_CODE_OTEL_HEADERS_HELPER_DEBOUNCE_MS` | Interval for refreshing dynamic headers (default: 1740000ms / 29 minutes) | `900000` |
123123
124124For the `http/protobuf` and `http/json` protocols, Claude Code sends each export request with a `Content-Length` header. Before v2.1.212, Claude Code versions from v2.1.191 onward sent these requests with chunked transfer encoding; Azure Monitor and other endpoints that require a declared length rejected them with `411 Length Required` or `400` errors.
125125
from line 127
127127
128128How you configure client certificates for the OTLP exporter depends on the OTLP protocol in use for that signal, set via `OTEL_EXPORTER_OTLP_PROTOCOL` or the per-signal override. The same configuration applies to metrics, logs, and traces.
129129
130| Protocol | Client certificate variables | Trust the collector's CA with |
131| :--------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------- |
132| `http/protobuf`, `http/json` | `CLAUDE_CODE_CLIENT_CERT`, `CLAUDE_CODE_CLIENT_KEY`, and optionally `CLAUDE_CODE_CLIENT_KEY_PASSPHRASE`. See [Network configuration](/docs/en/network-config#mtls-authentication) | `NODE_EXTRA_CA_CERTS` |
133| `grpc` | `OTEL_EXPORTER_OTLP_CLIENT_KEY` and `OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE`, or the per-signal variants such as `OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY` to use a different certificate per signal | `OTEL_EXPORTER_OTLP_CERTIFICATE` |
130| Protocol | Client certificate variables | Trust the collector's CA with |
131| :- | :- | :- |
132| `http/protobuf`, `http/json` | `CLAUDE_CODE_CLIENT_CERT`, `CLAUDE_CODE_CLIENT_KEY`, and optionally `CLAUDE_CODE_CLIENT_KEY_PASSPHRASE`. See [Network configuration](/docs/en/network-config#mtls-authentication) | `NODE_EXTRA_CA_CERTS` |
133| `grpc` | `OTEL_EXPORTER_OTLP_CLIENT_KEY` and `OTEL_EXPORTER_OTLP_CLIENT_CERTIFICATE`, or the per-signal variants such as `OTEL_EXPORTER_OTLP_METRICS_CLIENT_KEY` to use a different certificate per signal | `OTEL_EXPORTER_OTLP_CERTIFICATE` |
134134
135135For `grpc`, the OpenTelemetry SDK reads the standard OTLP variables directly, so existing configurations that set the per-signal metrics variables continue to work. On machines with managed settings, Claude Code [may remove developer-set per-signal credentials and endpoints](#how-managed-settings-lock-the-otlp-destination) at startup.
136136
from line 138
138138
139139The following environment variables control which attributes are included in metrics to manage cardinality:
140140
141| Environment Variable | Description | Default Value | Example to Disable |
142| ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- | ------------- | ------------------ |
143| `OTEL_METRICS_INCLUDE_SESSION_ID` | Include session.id attribute in metrics | `true` | `false` |
144| `OTEL_METRICS_INCLUDE_VERSION` | Include app.version attribute in metrics | `false` | `true` |
145| `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` | Include user.account\_uuid and user.account\_id attributes in metrics | `true` | `false` |
146| `OTEL_METRICS_INCLUDE_ENTRYPOINT` | Include app.entrypoint attribute in metrics | `false` | `true` |
147| `OTEL_METRICS_INCLUDE_RESOURCE_ATTRIBUTES` | Include keys from `OTEL_RESOURCE_ATTRIBUTES` as attributes on metric datapoints | `true` | `false` |
148| `OTEL_METRICS_INCLUDE_REPOSITORY` | Include `vcs.*` [repository identity attributes](#repository-attributes) on metrics and events. Requires Claude Code v2.1.269 or later | `false` | `true` |
141| Environment Variable | Description | Default Value | Example to Disable |
142| - | - | - | - |
143| `OTEL_METRICS_INCLUDE_SESSION_ID` | Include session.id attribute in metrics | `true` | `false` |
144| `OTEL_METRICS_INCLUDE_VERSION` | Include app.version attribute in metrics | `false` | `true` |
145| `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` | Include user.account\_uuid and user.account\_id attributes in metrics | `true` | `false` |
146| `OTEL_METRICS_INCLUDE_ENTRYPOINT` | Include app.entrypoint attribute in metrics | `false` | `true` |
147| `OTEL_METRICS_INCLUDE_RESOURCE_ATTRIBUTES` | Include keys from `OTEL_RESOURCE_ATTRIBUTES` as attributes on metric datapoints | `true` | `false` |
148| `OTEL_METRICS_INCLUDE_REPOSITORY` | Include `vcs.*` [repository identity attributes](#repository-attributes) on metrics and events. Requires Claude Code v2.1.269 or later | `false` | `true` |
149149
150150Lower cardinality generally means better performance and lower storage costs but less granular data for analysis.
151151
from line 155
155155
156156Tracing is off by default. To enable it, set both `CLAUDE_CODE_ENABLE_TELEMETRY=1` and `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA=1`, then set `OTEL_TRACES_EXPORTER` to choose where spans are sent. Traces reuse the [common OTLP configuration](#common-configuration-variables) for endpoint, protocol, headers, and [mTLS](#mtls-authentication). On machines with managed settings, Claude Code [may remove developer-set per-signal credentials and endpoints](#how-managed-settings-lock-the-otlp-destination) at startup.
157157
158| Environment Variable | Description | Example Values |
159| ------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------ |
160| `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA` | Enable span tracing (required). `ENABLE_ENHANCED_TELEMETRY_BETA` is also accepted | `1` |
161| `OTEL_TRACES_EXPORTER` | Traces exporter types, comma-separated. Use `none` to disable | `console`, `otlp`, `none` |
162| `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` | Protocol for traces, overrides `OTEL_EXPORTER_OTLP_PROTOCOL` | `grpc`, `http/json`, `http/protobuf` |
163| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | OTLP traces endpoint, overrides `OTEL_EXPORTER_OTLP_ENDPOINT` | `http://localhost:4318/v1/traces` |
164| `OTEL_EXPORTER_OTLP_TRACES_HEADERS` | Authentication headers for traces, merged with `OTEL_EXPORTER_OTLP_HEADERS` | `Authorization=Bearer token` |
165| `OTEL_TRACES_EXPORT_INTERVAL` | Span batch export interval in milliseconds (default: 5000) | `1000`, `10000` |
158| Environment Variable | Description | Example Values |
159| - | - | - |
160| `CLAUDE_CODE_ENHANCED_TELEMETRY_BETA` | Enable span tracing (required). `ENABLE_ENHANCED_TELEMETRY_BETA` is also accepted | `1` |
161| `OTEL_TRACES_EXPORTER` | Traces exporter types, comma-separated. Use `none` to disable | `console`, `otlp`, `none` |
162| `OTEL_EXPORTER_OTLP_TRACES_PROTOCOL` | Protocol for traces, overrides `OTEL_EXPORTER_OTLP_PROTOCOL` | `grpc`, `http/json`, `http/protobuf` |
163| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | OTLP traces endpoint, overrides `OTEL_EXPORTER_OTLP_ENDPOINT` | `http://localhost:4318/v1/traces` |
164| `OTEL_EXPORTER_OTLP_TRACES_HEADERS` | Authentication headers for traces, merged with `OTEL_EXPORTER_OTLP_HEADERS` | `Authorization=Bearer token` |
165| `OTEL_TRACES_EXPORT_INTERVAL` | Span batch export interval in milliseconds (default: 5000) | `1000`, `10000` |
166166
167167Spans redact user prompt text, tool input details, and tool content by default. Set `OTEL_LOG_USER_PROMPTS=1`, `OTEL_LOG_TOOL_DETAILS=1`, and `OTEL_LOG_TOOL_CONTENT=1` to include them.
168168
from line 202
202202
203203**`claude_code.interaction`**
204204
205| Attribute | Description | Gated by |
206| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
207| `user_prompt` | Prompt text. Value is `<REDACTED>` unless the gate is set | `OTEL_LOG_USER_PROMPTS` |
208| `user_prompt_length` | Prompt length in characters | |
209| `interaction.sequence` | 1-based counter of interactions, counted per Claude Code process rather than per session, as described for [`event.sequence`](#event-correlation-attributes) | |
210| `parent.source` | How the span got its trace parent: `env` when it parented under an inbound `TRACEPARENT`, `none` when it started its own trace. Requires Claude Code v2.1.268 or later | |
211| `interaction.duration_ms` | Wall-clock duration of the turn | |
205| Attribute | Description | Gated by |
206| - | - | - |
207| `user_prompt` | Prompt text. Value is `<REDACTED>` unless the gate is set | `OTEL_LOG_USER_PROMPTS` |
208| `user_prompt_length` | Prompt length in characters | |
209| `interaction.sequence` | 1-based counter of interactions, counted per Claude Code process rather than per session, as described for [`event.sequence`](#event-correlation-attributes) | |
210| `parent.source` | How the span got its trace parent: `env` when it parented under an inbound `TRACEPARENT`, `none` when it started its own trace. Requires Claude Code v2.1.268 or later | |
211| `interaction.duration_ms` | Wall-clock duration of the turn | |
212212
213213**`claude_code.llm_request`**
214214
215| Attribute | Description | Gated by |
216| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
217| `model` | Model identifier | |
218| `gen_ai.system` | Always `anthropic`. OpenTelemetry GenAI semantic convention | |
219| `gen_ai.request.model` | Same value as `model`. OpenTelemetry GenAI semantic convention | |
220| `query_source` | Subsystem that issued the request, such as `repl_main_thread` or a subagent name | `ENABLE_BETA_TRACING_DETAILED` |
221| `query_source_safe` | Bounded form of `query_source`, emitted whether or not detailed beta tracing is active, with values such as `repl_main_thread` or `agent.builtin.general-purpose`. `:` becomes `.` and user-named agents appear as `agent.custom`. Requires Claude Code v2.1.268 or later | |
222| `agent_id` | Identifier of the subagent or teammate that issued the request. Absent on the main session | |
223| `parent_agent_id` | Identifier of the agent that spawned this one. Absent for the main session and for agents spawned directly from it | |
224| `workflow.run_id` | Run identifier of the [Workflow](/docs/en/workflows) tool run that spawned this agent, prefixed `wf_`. Absent for agents not spawned by a workflow | |
225| `workflow.name` | Name of the workflow that spawned this agent. User-authored names are replaced with `custom` unless the gate is set | `OTEL_LOG_TOOL_DETAILS` |
226| `speed` | `fast` or `normal` | |
227| `effort` | [Effort level](/docs/en/model-config#adjust-effort-level) applied to the request: `low`, `medium`, `high`, `xhigh`, or `max`. Absent when Claude Code sends no effort level, for example on a model that doesn't support effort. Requires Claude Code v2.1.274 or later | |
228| `llm_request.context` | `interaction`, `tool`, or `standalone` depending on the parent span | |
229| `duration_ms` | Wall-clock duration including retries | |
230| `ttft_ms` | Time to first token in milliseconds | |
231| `first_content_ms` | Time from request start to the first content block of the successful attempt, in milliseconds. Absent on requests that fell back to the non-streaming path. Requires Claude Code v2.1.268 or later | |
232| `input_tokens` | Input token count from the API usage block | |
233| `output_tokens` | Output token count | |
234| `cache_read_tokens` | Tokens read from prompt cache | |
235| `cache_creation_tokens` | Tokens written to prompt cache | |
236| `request_id` | API request ID. Same value as the `request_id` [event correlation attribute](#event-correlation-attributes) | |
237| `gen_ai.response.id` | Same value as `request_id`. OpenTelemetry GenAI semantic convention | |
238| `client_request_id` | Client-generated `x-client-request-id` of the final attempt | |
239| `attempt` | Total attempts made for this request | |
240| `success` | `true` or `false` | |
241| `status_code` | HTTP status code when the request failed | |
242| `error` | Error message when the request failed | |
243| `error_class` | Short error class token when the request failed, such as `api_timeout` or `server_overload`. Requires Claude Code v2.1.268 or later | |
244| `response.has_tool_call` | `true` when the response contained tool-use blocks | |
245| `stop_reason` | API response `stop_reason`, such as `end_turn`, `tool_use`, `max_tokens`, `stop_sequence`, `pause_turn`, or `refusal` | |
246| `gen_ai.response.finish_reasons` | Same value as `stop_reason`, wrapped in a string array. OpenTelemetry GenAI semantic convention | |
215| Attribute | Description | Gated by |
216| - | - | - |
217| `model` | Model identifier | |
218| `gen_ai.system` | Always `anthropic`. OpenTelemetry GenAI semantic convention | |
219| `gen_ai.request.model` | Same value as `model`. OpenTelemetry GenAI semantic convention | |
220| `query_source` | Subsystem that issued the request, such as `repl_main_thread` or a subagent name | `ENABLE_BETA_TRACING_DETAILED` |
221| `query_source_safe` | Bounded form of `query_source`, emitted whether or not detailed beta tracing is active, with values such as `repl_main_thread` or `agent.builtin.general-purpose`. `:` becomes `.` and user-named agents appear as `agent.custom`. Requires Claude Code v2.1.268 or later | |
222| `agent_id` | Identifier of the subagent or teammate that issued the request. Absent on the main session | |
223| `parent_agent_id` | Identifier of the agent that spawned this one. Absent for the main session and for agents spawned directly from it | |
224| `workflow.run_id` | Run identifier of the [Workflow](/docs/en/workflows) tool run that spawned this agent, prefixed `wf_`. Absent for agents not spawned by a workflow | |
225| `workflow.name` | Name of the workflow that spawned this agent. User-authored names are replaced with `custom` unless the gate is set | `OTEL_LOG_TOOL_DETAILS` |
226| `speed` | `fast` or `normal` | |
227| `effort` | [Effort level](/docs/en/model-config#adjust-effort-level) applied to the request: `low`, `medium`, `high`, `xhigh`, or `max`. Absent when Claude Code sends no effort level, for example on a model that doesn't support effort. Requires Claude Code v2.1.274 or later | |
228| `llm_request.context` | `interaction`, `tool`, or `standalone` depending on the parent span | |
229| `duration_ms` | Wall-clock duration including retries | |
230| `ttft_ms` | Time to first token in milliseconds | |
231| `first_content_ms` | Time from request start to the first content block of the successful attempt, in milliseconds. Absent on requests that fell back to the non-streaming path. Requires Claude Code v2.1.268 or later | |
232| `input_tokens` | Input token count from the API usage block | |
233| `output_tokens` | Output token count | |
234| `cache_read_tokens` | Tokens read from prompt cache | |
235| `cache_creation_tokens` | Tokens written to prompt cache | |
236| `request_id` | API request ID. Same value as the `request_id` [event correlation attribute](#event-correlation-attributes) | |
237| `gen_ai.response.id` | Same value as `request_id`. OpenTelemetry GenAI semantic convention | |
238| `client_request_id` | Client-generated `x-client-request-id` of the final attempt | |
239| `attempt` | Total attempts made for this request | |
240| `success` | `true` or `false` | |
241| `status_code` | HTTP status code when the request failed | |
242| `error` | Error message when the request failed | |
243| `error_class` | Short error class token when the request failed, such as `api_timeout` or `server_overload`. Requires Claude Code v2.1.268 or later | |
244| `response.has_tool_call` | `true` when the response contained tool-use blocks | |
245| `stop_reason` | API response `stop_reason`, such as `end_turn`, `tool_use`, `max_tokens`, `stop_sequence`, `pause_turn`, or `refusal` | |
246| `gen_ai.response.finish_reasons` | Same value as `stop_reason`, wrapped in a string array. OpenTelemetry GenAI semantic convention | |
247247
248248Each retry attempt is also recorded as a `gen_ai.request.attempt` span event with `attempt` and `client_request_id` attributes.
249249
250250**`claude_code.tool`**
251251
252| Attribute | Description | Gated by |
253| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
254| `tool_name` | Tool name | |
255| `tool_name_safe` | Form of `tool_name` that carries no user-chosen names. Built-in tool names pass verbatim. MCP tool names appear as `mcp_other`, except tool names matching a few fixed shapes, such as `playwright` tools named `browser_*`, which pass verbatim. Requires Claude Code v2.1.268 or later | |
256| `bash_command_class` | For the Bash tool: category of the command's first program from a fixed list, such as `vcs` or `package_manager`. `other` for a program outside the list, `unparsed` when the line can't be parsed. Requires Claude Code v2.1.268 or later | |
257| `bash_argv0` | For the Bash tool: the command's first program when it's on the same fixed list, such as `git` or `npm`. `other` for any program outside the list. Requires Claude Code v2.1.268 or later | |
258| `duration_ms` | Wall-clock duration including permission wait and execution | |
259| `result_tokens` | Approximate token size of the tool result | |
260| `agent_id` | Identifier of the subagent or teammate that ran the tool. Absent on the main session | |
261| `parent_agent_id` | Identifier of the agent that spawned this one. Absent for the main session and for agents spawned directly from it | |
262| `workflow.run_id` | Run identifier of the Workflow tool run that spawned this agent, prefixed `wf_`. Absent for agents not spawned by a workflow | |
263| `workflow.name` | Name of the workflow that spawned this agent. User-authored names are replaced with `custom` unless the gate is set | `OTEL_LOG_TOOL_DETAILS` |
264| `tool_use_id` | The model's `tool_use` block id for this call. Matches the `tool_use_id` on the [tool\_result](#tool-result-event) and [tool\_decision](#tool-decision-event) events and in hook payloads, so you can join the span to those records | |
265| `gen_ai.tool.call.id` | Same value as `tool_use_id`. OpenTelemetry GenAI semantic convention | |
266| `file_path` | Target file path for Read, Edit, and Write tools | `OTEL_LOG_TOOL_DETAILS` |
267| `full_command` | Command string for the Bash tool | `OTEL_LOG_TOOL_DETAILS` |
268| `skill_name` | Skill name for the Skill tool | `OTEL_LOG_TOOL_DETAILS` |
269| `subagent_type` | Subagent type for the Agent tool or legacy Task tool | `OTEL_LOG_TOOL_DETAILS` |
252| Attribute | Description | Gated by |
253| - | - | - |
254| `tool_name` | Tool name | |
255| `tool_name_safe` | Form of `tool_name` that carries no user-chosen names. Built-in tool names pass verbatim. MCP tool names appear as `mcp_other`, except tool names matching a few fixed shapes, such as `playwright` tools named `browser_*`, which pass verbatim. Requires Claude Code v2.1.268 or later | |
256| `bash_command_class` | For the Bash tool: category of the command's first program from a fixed list, such as `vcs` or `package_manager`. `other` for a program outside the list, `unparsed` when the line can't be parsed. Requires Claude Code v2.1.268 or later | |
257| `bash_argv0` | For the Bash tool: the command's first program when it's on the same fixed list, such as `git` or `npm`. `other` for any program outside the list. Requires Claude Code v2.1.268 or later | |
258| `duration_ms` | Wall-clock duration including permission wait and execution | |
259| `result_tokens` | Approximate token size of the tool result | |
260| `agent_id` | Identifier of the subagent or teammate that ran the tool. Absent on the main session | |
261| `parent_agent_id` | Identifier of the agent that spawned this one. Absent for the main session and for agents spawned directly from it | |
262| `workflow.run_id` | Run identifier of the Workflow tool run that spawned this agent, prefixed `wf_`. Absent for agents not spawned by a workflow | |
263| `workflow.name` | Name of the workflow that spawned this agent. User-authored names are replaced with `custom` unless the gate is set | `OTEL_LOG_TOOL_DETAILS` |
264| `tool_use_id` | The model's `tool_use` block id for this call. Matches the `tool_use_id` on the [tool\_result](#tool-result-event) and [tool\_decision](#tool-decision-event) events and in hook payloads, so you can join the span to those records | |
265| `gen_ai.tool.call.id` | Same value as `tool_use_id`. OpenTelemetry GenAI semantic convention | |
266| `file_path` | Target file path for Read, Edit, and Write tools | `OTEL_LOG_TOOL_DETAILS` |
267| `full_command` | Command string for the Bash tool | `OTEL_LOG_TOOL_DETAILS` |
268| `skill_name` | Skill name for the Skill tool | `OTEL_LOG_TOOL_DETAILS` |
269| `subagent_type` | Subagent type for the Agent tool or legacy Task tool | `OTEL_LOG_TOOL_DETAILS` |
270270
271271<span id="tool-output-span-event" />**`tool.output` span event on `claude_code.tool`**
272272
from line 283
283283
284284The event carries these attributes, each truncated at the content limit (60 KB by default). `Gated by` names the variable an attribute needs on top of `OTEL_LOG_TOOL_CONTENT=1`, and for Edit and Write that variable gates the event itself rather than the attribute.
285285
286| Attribute | Description | Gated by |
287| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
288| `content` | Text the Read tool returned, or the text a Write call was asked to write | `OTEL_LOG_TOOL_DETAILS` for the Write tool |
289| `output` | For the Bash tool, the command's combined output, with stderr interleaved into stdout. For an MCP tool, WebFetch, or WebSearch, the result the tool returned: text blocks joined by newlines, with an image or document replaced by a placeholder such as `[image]` | |
290| `diff` | Structured patch the Edit tool applied | `OTEL_LOG_TOOL_DETAILS` |
291| `file_path` | Target file path for the Read, Edit, and Write tools, repeating the span attribute of the same name | `OTEL_LOG_TOOL_DETAILS` |
292| `bash_command` | Command string for the Bash tool | `OTEL_LOG_TOOL_DETAILS` |
286| Attribute | Description | Gated by |
287| - | - | - |
288| `content` | Text the Read tool returned, or the text a Write call was asked to write | `OTEL_LOG_TOOL_DETAILS` for the Write tool |
289| `output` | For the Bash tool, the command's combined output, with stderr interleaved into stdout. For an MCP tool, WebFetch, or WebSearch, the result the tool returned: text blocks joined by newlines, with an image or document replaced by a placeholder such as `[image]` | |
290| `diff` | Structured patch the Edit tool applied | `OTEL_LOG_TOOL_DETAILS` |
291| `file_path` | Target file path for the Read, Edit, and Write tools, repeating the span attribute of the same name | `OTEL_LOG_TOOL_DETAILS` |
292| `bash_command` | Command string for the Bash tool | `OTEL_LOG_TOOL_DETAILS` |
293293
294294The parent span's `tool_name` attribute tells you which tool an event came from. An attribute cut at the content limit is accompanied by `<attribute>_truncated` and `<attribute>_original_length`.
295295
296296**`claude_code.tool.blocked_on_user`**
297297
298| Attribute | Description | Gated by |
299| ------------- | ------------------------------------------------------------------------- | -------- |
300| `duration_ms` | Time spent waiting for the permission decision | |
301| `decision` | `accept` or `reject` | |
302| `source` | Decision source, matching the [Tool decision event](#tool-decision-event) | |
298| Attribute | Description | Gated by |
299| - | - | - |
300| `duration_ms` | Time spent waiting for the permission decision | |
301| `decision` | `accept` or `reject` | |
302| `source` | Decision source, matching the [Tool decision event](#tool-decision-event) | |
303303
304304**`claude_code.tool.execution`**
305305
306| Attribute | Description | Gated by |
307| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
308| `duration_ms` | Time spent running the tool body | |
309| `tool_use_id` | Same value as on the parent `claude_code.tool` span | |
310| `gen_ai.tool.call.id` | Same value as `tool_use_id`. OpenTelemetry GenAI semantic convention | |
311| `success` | `true` or `false` | |
312| `error` | Error category string when execution failed, such as `Error:ENOENT` or `ShellError`. Contains the full error message instead when the gate is set | `OTEL_LOG_TOOL_DETAILS` |
313| `error_class` | The error category in identifier form, with characters outside letters, digits, and underscores replaced by `_`, such as `Error_ENOENT` or `ShellError`. Carries the category even when `error` carries the full message. Requires Claude Code v2.1.268 or later | |
306| Attribute | Description | Gated by |
307| - | - | - |
308| `duration_ms` | Time spent running the tool body | |
309| `tool_use_id` | Same value as on the parent `claude_code.tool` span | |
310| `gen_ai.tool.call.id` | Same value as `tool_use_id`. OpenTelemetry GenAI semantic convention | |
311| `success` | `true` or `false` | |
312| `error` | Error category string when execution failed, such as `Error:ENOENT` or `ShellError`. Contains the full error message instead when the gate is set | `OTEL_LOG_TOOL_DETAILS` |
313| `error_class` | The error category in identifier form, with characters outside letters, digits, and underscores replaced by `_`, such as `Error_ENOENT` or `ShellError`. Carries the category even when `error` carries the full message. Requires Claude Code v2.1.268 or later | |
314314
315315**`claude_code.hook`**
316316
from line 318
318318
319319In interactive CLI sessions, detailed beta tracing also requires your organization to be allowlisted for the feature. Agent SDK and non-interactive `-p` sessions don't require allowlisting.
320320
321| Attribute | Description | Gated by |
322| ------------------------ | ------------------------------------------------ | ----------------------- |
323| `hook_event` | Hook event type, such as `PreToolUse` | |
324| `hook_name` | Full hook name, such as `PreToolUse:Write` | |
325| `num_hooks` | Number of matching hook commands executed | |
326| `hook_definitions` | JSON-serialized hook configuration | `OTEL_LOG_TOOL_DETAILS` |
327| `duration_ms` | Wall-clock duration of all matching hooks | |
328| `num_success` | Count of hooks that completed successfully | |
329| `num_blocking` | Count of hooks that returned a blocking decision | |
330| `num_non_blocking_error` | Count of hooks that failed without blocking | |
331| `num_cancelled` | Count of hooks cancelled before completion | |
321| Attribute | Description | Gated by |
322| - | - | - |
323| `hook_event` | Hook event type, such as `PreToolUse` | |
324| `hook_name` | Full hook name, such as `PreToolUse:Write` | |
325| `num_hooks` | Number of matching hook commands executed | |
326| `hook_definitions` | JSON-serialized hook configuration | `OTEL_LOG_TOOL_DETAILS` |
327| `duration_ms` | Wall-clock duration of all matching hooks | |
328| `num_success` | Count of hooks that completed successfully | |
329| `num_blocking` | Count of hooks that returned a blocking decision | |
330| `num_non_blocking_error` | Count of hooks that failed without blocking | |
331| `num_cancelled` | Count of hooks cancelled before completion | |
332332
333333<span id="new-context-gates" />
334334
from line 495
495495
496496All metrics and events share these standard attributes:
497497
498| Attribute | Description | Controlled By |
499| --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ |
500| `session.id` | Unique session identifier | `OTEL_METRICS_INCLUDE_SESSION_ID` (default: true) |
501| `app.version` | Current Claude Code version | `OTEL_METRICS_INCLUDE_VERSION` (default: false) |
502| `app.entrypoint` | How the session was launched, such as `cli`, `sdk-cli`, `sdk-ts`, `sdk-py`, or `claude-vscode` | `OTEL_METRICS_INCLUDE_ENTRYPOINT` (default: false) |
503| `organization.id` | Organization UUID (when authenticated) | Always included when available |
504| `user.account_uuid` | Account UUID (when authenticated) | `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` (default: true) |
505| `user.account_id` | Account ID in tagged format matching Anthropic admin APIs (when authenticated), such as `user_01BWBeN28...` | `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` (default: true) |
506| `user.id` | Random anonymous identifier generated on first run and persisted in `~/.claude.json`. It contains no personal information and is not derived from your Claude account. Deleting the file produces a new unrelated value on next run. | Always included |
507| `user.email` | User email address, from your sign-in or, in a [cloud session](/docs/en/claude-code-on-the-web), from the session's own credentials | Always included when available |
508| `terminal.type` | Terminal type, such as `iTerm.app`, `vscode`, `cursor`, or `tmux` | Always included when detected |
509| Keys from `OTEL_RESOURCE_ATTRIBUTES` | Custom attributes you set, such as `department` or `team.id`. See [Multi-team organization support](#multi-team-organization-support) | `OTEL_METRICS_INCLUDE_RESOURCE_ATTRIBUTES` (default: true) |
510| `vcs.repository.url.full`, `vcs.owner.name`, `vcs.repository.name`, `vcs.provider.name` | The session repository's identity, derived from its `origin` remote. See [Repository attributes](#repository-attributes) | `OTEL_METRICS_INCLUDE_REPOSITORY` (default: false). Requires Claude Code v2.1.269 or later |
498| Attribute | Description | Controlled By |
499| - | - | - |
500| `session.id` | Unique session identifier | `OTEL_METRICS_INCLUDE_SESSION_ID` (default: true) |
501| `app.version` | Current Claude Code version | `OTEL_METRICS_INCLUDE_VERSION` (default: false) |
502| `app.entrypoint` | How the session was launched, such as `cli`, `sdk-cli`, `sdk-ts`, `sdk-py`, or `claude-vscode` | `OTEL_METRICS_INCLUDE_ENTRYPOINT` (default: false) |
503| `organization.id` | Organization UUID (when authenticated) | Always included when available |
504| `user.account_uuid` | Account UUID (when authenticated) | `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` (default: true) |
505| `user.account_id` | Account ID in tagged format matching Anthropic admin APIs (when authenticated), such as `user_01BWBeN28...` | `OTEL_METRICS_INCLUDE_ACCOUNT_UUID` (default: true) |
506| `user.id` | Random anonymous identifier generated on first run and persisted in `~/.claude.json`. It contains no personal information and is not derived from your Claude account. Deleting the file produces a new unrelated value on next run. | Always included |
507| `user.email` | User email address, from your sign-in or, in a [cloud session](/docs/en/claude-code-on-the-web), from the session's own credentials | Always included when available |
508| `terminal.type` | Terminal type, such as `iTerm.app`, `vscode`, `cursor`, or `tmux` | Always included when detected |
509| Keys from `OTEL_RESOURCE_ATTRIBUTES` | Custom attributes you set, such as `department` or `team.id`. See [Multi-team organization support](#multi-team-organization-support) | `OTEL_METRICS_INCLUDE_RESOURCE_ATTRIBUTES` (default: true) |
510| `vcs.repository.url.full`, `vcs.owner.name`, `vcs.repository.name`, `vcs.provider.name` | The session repository's identity, derived from its `origin` remote. See [Repository attributes](#repository-attributes) | `OTEL_METRICS_INCLUDE_REPOSITORY` (default: false). Requires Claude Code v2.1.269 or later |
511511
512512When Claude Code is signed in to a [Claude apps gateway](/docs/en/claude-apps-gateway), the CLI stamps exports with the authenticated identity from the gateway session: `user.id` is the IdP subject rather than an anonymous installation identifier, `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 gateway sessions.
513513
from line 524
524524
525525Claude Code derives these attributes once per session from the repository's `origin` remote. The HTTPS and SSH remotes of one repository produce identical values:
526526
527| Attribute | Value |
528| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
529| `vcs.repository.url.full` | The repository's browser URL without `.git`, such as `https://github.com/example-org/example-repo` |
530| `vcs.owner.name` | The owner or group path, such as `example-org`; omitted when the remote path has a single segment |
531| `vcs.repository.name` | The bare repository name, such as `example-repo` |
532| `vcs.provider.name` | `github`, `gitlab`, `bitbucket`, or `gitea` when Claude Code recognizes the remote's host or URL shape as one of those providers; omitted otherwise |
527| Attribute | Value |
528| - | - |
529| `vcs.repository.url.full` | The repository's browser URL without `.git`, such as `https://github.com/example-org/example-repo` |
530| `vcs.owner.name` | The owner or group path, such as `example-org`; omitted when the remote path has a single segment |
531| `vcs.repository.name` | The bare repository name, such as `example-repo` |
532| `vcs.provider.name` | `github`, `gitlab`, `bitbucket`, or `gitea` when Claude Code recognizes the remote's host or URL shape as one of those providers; omitted otherwise |
533533
534534Values are lowercased, and credentials, query strings, and fragments from the remote URL never appear in them. The attributes are omitted when the session has no `origin` remote, when the remote isn't URL-shaped, or when the only enclosing repository is your home directory.
535535
from line 541
541541
542542Claude Code exports the following metrics. The Unit column shows the OpenTelemetry unit string attached to each metric; count metrics carry none.
543543
544| Metric Name | Description | Unit |
545| ------------------------------------- | ----------------------------------------------- | ------ |
546| `claude_code.session.count` | Count of CLI sessions started | none |
547| `claude_code.lines_of_code.count` | Count of lines of code modified | none |
548| `claude_code.pull_request.count` | Number of pull requests created | none |
549| `claude_code.commit.count` | Number of git commits created | none |
550| `claude_code.cost.usage` | Cost of the Claude Code session | USD |
551| `claude_code.token.usage` | Number of tokens used | tokens |
552| `claude_code.code_edit_tool.decision` | Count of code editing tool permission decisions | none |
553| `claude_code.active_time.total` | Total active time | s |
544| Metric Name | Description | Unit |
545| - | - | - |
546| `claude_code.session.count` | Count of CLI sessions started | none |
547| `claude_code.lines_of_code.count` | Count of lines of code modified | none |
548| `claude_code.pull_request.count` | Number of pull requests created | none |
549| `claude_code.commit.count` | Number of git commits created | none |
550| `claude_code.cost.usage` | Cost of the Claude Code session | USD |
551| `claude_code.token.usage` | Number of tokens used | tokens |
552| `claude_code.code_edit_tool.decision` | Count of code editing tool permission decisions | none |
553| `claude_code.active_time.total` | Total active time | s |
554554
555555When `prometheus` is the only exporter listed in `OTEL_METRICS_EXPORTER`, Claude Code omits the `USD`, `tokens`, and `s` units from the exported metrics so the scrape stays valid Prometheus text format. Metric names don't change, and configurations that combine exporters, such as `otlp,prometheus`, keep the units. Before v2.1.216, the Prometheus scrape included OpenMetrics-only `# UNIT` lines that some scrapers rejected.
556556
from line 654
654654
655655When a user submits a prompt, Claude Code may make multiple API calls and run several tools. The `prompt.id` attribute lets you tie all of those events back to the single prompt that triggered them.
656656
657| Attribute | Description |
658| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
659| `prompt.id` | UUID v4 identifier linking all events produced while processing a single user prompt |
660| `event.sequence` | 0-based counter for ordering events, counted per Claude Code process rather than per session |
661| `message.uuid` | UUID of the message as persisted in the session transcript, the `~/.claude/projects/*/*.jsonl` files. Present on `assistant_response`, on `api_response_body`, and on `user_prompt` except for command dispatches, which can produce zero or many messages. On `assistant_response` and `api_response_body`, this is the response's final transcript entry, which the next turn's `parentUuid` chains from. Requires Claude Code v2.1.214 or later, or v2.1.274 or later on `api_response_body` |
662| `request_id` | Server-assigned ID of the API request, read from the `request-id` response header, such as `req_011...`. On a response with no `request-id` header, as on [Amazon Bedrock](/docs/en/amazon-bedrock), the value comes from the `x-amzn-requestid` header instead. Present on `api_request`, `api_error`, `api_refusal`, `assistant_response`, and `api_response_body` when the response carries either header. Matches the same attribute on the `llm_request` trace span. The `x-amzn-requestid` source requires Claude Code v2.1.282 or later |
663| `client_request_id` | Client-generated UUID sent as the `x-client-request-id` request header. Present on `api_request` and `api_error` on first-party API connections; absent on third-party provider backends and when the request was retried through the non-streaming fallback. Pairs a request with its response and remains available for failures such as timeouts that never produced a server `request_id`. Matches the same attribute on the `llm_request` trace span. Requires Claude Code v2.1.214 or later |
657| Attribute | Description |
658| - | - |
659| `prompt.id` | UUID v4 identifier linking all events produced while processing a single user prompt |
660| `event.sequence` | 0-based counter for ordering events, counted per Claude Code process rather than per session |
661| `message.uuid` | UUID of the message as persisted in the session transcript, the `~/.claude/projects/*/*.jsonl` files. Present on `assistant_response`, on `api_response_body`, and on `user_prompt` except for command dispatches, which can produce zero or many messages. On `assistant_response` and `api_response_body`, this is the response's final transcript entry, which the next turn's `parentUuid` chains from. Requires Claude Code v2.1.214 or later, or v2.1.274 or later on `api_response_body` |
662| `request_id` | Server-assigned ID of the API request, read from the `request-id` response header, such as `req_011...`. On a response with no `request-id` header, as on [Amazon Bedrock](/docs/en/amazon-bedrock), the value comes from the `x-amzn-requestid` header instead. Present on `api_request`, `api_error`, `api_refusal`, `assistant_response`, and `api_response_body` when the response carries either header. Matches the same attribute on the `llm_request` trace span. The `x-amzn-requestid` source requires Claude Code v2.1.282 or later |
663| `client_request_id` | Client-generated UUID sent as the `x-client-request-id` request header. Present on `api_request` and `api_error` on first-party API connections; absent on third-party provider backends and when the request was retried through the non-streaming fallback. Pairs a request with its response and remains available for failures such as timeouts that never produced a server `request_id`. Matches the same attribute on the `llm_request` trace span. Requires Claude Code v2.1.214 or later |
664664
665665To trace all activity triggered by a single prompt, filter your events by a specific `prompt.id` value. This returns the user\_prompt event, any api\_request events, and any tool\_result events that occurred while processing that prompt.
666666
from line 1303
13031303
13041304### Usage monitoring
13051305
1306| Metric | Analysis Opportunity |
1307| ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
1308| `claude_code.token.usage` | Break down by `type` (input/output), user, team, model, `skill.name`, `plugin.name`, or `agent.name` |
1309| `claude_code.session.count` | Track adoption and engagement over time |
1310| `claude_code.lines_of_code.count` | Measure productivity by tracking code additions and removals, broken down by model |
1311| `claude_code.commit.count` & `claude_code.pull_request.count` | Understand impact on development workflows |
1306| Metric | Analysis Opportunity |
1307| - | - |
1308| `claude_code.token.usage` | Break down by `type` (input/output), user, team, model, `skill.name`, `plugin.name`, or `agent.name` |
1309| `claude_code.session.count` | Track adoption and engagement over time |
1310| `claude_code.lines_of_code.count` | Measure productivity by tracking code additions and removals, broken down by model |
1311| `claude_code.commit.count` & `claude_code.pull_request.count` | Understand impact on development workflows |
13121312
13131313### Cost monitoring
13141314
from line 1379
13791379
13801380To capture MCP server activity with full call detail, enable the logs exporter and set `OTEL_LOG_TOOL_DETAILS=1`. Each MCP operation then produces structured events that carry the server name, tool name, and call arguments alongside the standard identity attributes:
13811381
1382| Event | What it records for MCP |
1383| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1384| `mcp_server_connection` | Server connect, disconnect, and connection failure with `server_name`, `transport_type`, `server_scope`, and error detail |
1385| `tool_result` | Each MCP tool call with `tool_name` and `mcp_server_scope`, a `tool_parameters` payload containing `mcp_server_name` and `mcp_tool_name`, and a `tool_input` payload containing the call arguments |
1386| `tool_decision` | Whether the call was allowed or denied, whether the decision came from config, a hook, or the user, and a `tool_parameters` payload containing `mcp_server_name` and `mcp_tool_name` |
1382| Event | What it records for MCP |
1383| - | - |
1384| `mcp_server_connection` | Server connect, disconnect, and connection failure with `server_name`, `transport_type`, `server_scope`, and error detail |
1385| `tool_result` | Each MCP tool call with `tool_name` and `mcp_server_scope`, a `tool_parameters` payload containing `mcp_server_name` and `mcp_tool_name`, and a `tool_input` payload containing the call arguments |
1386| `tool_decision` | Whether the call was allowed or denied, whether the decision came from config, a hook, or the user, and a `tool_parameters` payload containing `mcp_server_name` and `mcp_tool_name` |
13871387
13881388Without `OTEL_LOG_TOOL_DETAILS`, these events drop the identifying detail:
13891389
from line 1395
13951395
13961396When building detection rules, look up the signal you want to monitor and query your backend for the corresponding event and attributes:
13971397
1398| Signal | Event | Key attributes |
1399| -------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1400| Tool call allowed or denied, and by what | `tool_decision` | `decision`, `source`, `tool_name`, `tool_parameters` |
1401| Permission mode escalation | `permission_mode_changed` | `from_mode`, `to_mode`, `trigger` |
1402| Policy hook blocked an action | `hook_execution_complete` | `hook_event`, `num_blocking` |
1403| Login, logout, and authentication failure | `auth` | `action`, `success`, `error_category` |
1404| MCP server connect or failure | `mcp_server_connection` | `status`, `server_name`, `is_plugin`, `error_code` |
1405| Plugin installed and its source | `plugin_installed` | `plugin.name`, `marketplace.name`, `marketplace.is_official` |
1406| Commands run and files touched | `tool_result` (executed) or `tool_decision` (rejected) with `OTEL_LOG_TOOL_DETAILS=1` | `tool_parameters`; `tool_input` (`tool_result` only) |
1407| Which managed settings sources a machine runs on, whether its policy helper is healthy, and why a machine refused to start | `managed_settings_resolved` | `managed_settings.trigger`, `managed_settings.sources`, `managed_settings.source_behavior`, `managed_settings.helper.state`, `error.type`; `managed_settings.settings` and `managed_settings.resolved_sha256` with `OTEL_LOG_MANAGED_SETTINGS=1` |
1398| Signal | Event | Key attributes |
1399| - | - | - |
1400| Tool call allowed or denied, and by what | `tool_decision` | `decision`, `source`, `tool_name`, `tool_parameters` |
1401| Permission mode escalation | `permission_mode_changed` | `from_mode`, `to_mode`, `trigger` |
1402| Policy hook blocked an action | `hook_execution_complete` | `hook_event`, `num_blocking` |
1403| Login, logout, and authentication failure | `auth` | `action`, `success`, `error_category` |
1404| MCP server connect or failure | `mcp_server_connection` | `status`, `server_name`, `is_plugin`, `error_code` |
1405| Plugin installed and its source | `plugin_installed` | `plugin.name`, `marketplace.name`, `marketplace.is_official` |
1406| Commands run and files touched | `tool_result` (executed) or `tool_decision` (rejected) with `OTEL_LOG_TOOL_DETAILS=1` | `tool_parameters`; `tool_input` (`tool_result` only) |
1407| Which managed settings sources a machine runs on, whether its policy helper is healthy, and why a machine refused to start | `managed_settings_resolved` | `managed_settings.trigger`, `managed_settings.sources`, `managed_settings.source_behavior`, `managed_settings.helper.state`, `error.type`; `managed_settings.settings` and `managed_settings.resolved_sha256` with `OTEL_LOG_MANAGED_SETTINGS=1` |
14081408
14091409Claude Code emits the raw event stream only. Anomaly detection, baselining, correlation across sessions, and alerting are the responsibility of your SIEM or observability backend.
14101410
network-config Changed · +26 / -26 lines
from line 179
179179
180180Claude Code runs four independent timers that abort a streaming model response when it goes quiet, so a dead connection fails and retries instead of hanging. The first-byte deadline covers the wait for response headers, before any of the response has arrived. Each of the other three watches a live response for a different signal.
181181
182| Timer | Aborts when | Runs on | Default timeout |
183| :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------- |
184| First-byte deadline | No response headers arrive after Claude Code sends the request | Direct Anthropic API and [Claude Platform on AWS](/docs/en/claude-platform-on-aws), including through an HTTPS proxy, but not when `ANTHROPIC_BASE_URL` or `ANTHROPIC_AWS_BASE_URL` routes them through a [gateway](/docs/en/gateways). Opt-in on Amazon Bedrock with `CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK=1`; doesn't run on Google Cloud's Agent Platform or Microsoft Foundry | 180 seconds on the direct Anthropic API, 300 seconds elsewhere, plus one second per 32KB of request body |
185| Event-level watchdog | No response events parse. On connections where the byte-level watchdog runs, arriving bytes, including keep-alive pings, also reset this watchdog, for up to about five minutes without a parsed event | Every provider | 300 seconds |
186| Byte-level watchdog | No bytes arrive on the wire, including SSE keep-alive pings | Direct Anthropic API, [Claude Platform on AWS](/docs/en/claude-platform-on-aws), and [gateway](/docs/en/gateways) connections, including a custom `ANTHROPIC_BASE_URL`. Opt-in on Amazon Bedrock `vnd.amazon.eventstream` responses with `CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK=1`; doesn't run on Google Cloud's Agent Platform or Microsoft Foundry | 180 seconds on the direct Anthropic API, 300 seconds elsewhere |
187| Body idle timeout | No bytes arrive for 5 minutes | Providers other than the direct Anthropic API and Claude Platform on AWS, unless [`API_FORCE_IDLE_TIMEOUT`](/docs/en/env-vars) changes that | 5 minutes |
182| Timer | Aborts when | Runs on | Default timeout |
183| :- | :- | :- | :- |
184| First-byte deadline | No response headers arrive after Claude Code sends the request | Direct Anthropic API and [Claude Platform on AWS](/docs/en/claude-platform-on-aws), including through an HTTPS proxy, but not when `ANTHROPIC_BASE_URL` or `ANTHROPIC_AWS_BASE_URL` routes them through a [gateway](/docs/en/gateways). Opt-in on Amazon Bedrock with `CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK=1`; doesn't run on Google Cloud's Agent Platform or Microsoft Foundry | 180 seconds on the direct Anthropic API, 300 seconds elsewhere, plus one second per 32KB of request body |
185| Event-level watchdog | No response events parse. On connections where the byte-level watchdog runs, arriving bytes, including keep-alive pings, also reset this watchdog, for up to about five minutes without a parsed event | Every provider | 300 seconds |
186| Byte-level watchdog | No bytes arrive on the wire, including SSE keep-alive pings | Direct Anthropic API, [Claude Platform on AWS](/docs/en/claude-platform-on-aws), and [gateway](/docs/en/gateways) connections, including a custom `ANTHROPIC_BASE_URL`. Opt-in on Amazon Bedrock `vnd.amazon.eventstream` responses with `CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK=1`; doesn't run on Google Cloud's Agent Platform or Microsoft Foundry | 180 seconds on the direct Anthropic API, 300 seconds elsewhere |
187| Body idle timeout | No bytes arrive for 5 minutes | Providers other than the direct Anthropic API and Claude Platform on AWS, unless [`API_FORCE_IDLE_TIMEOUT`](/docs/en/env-vars) changes that | 5 minutes |
188188
189189Configure the timers with these variables, each detailed in the [environment variables reference](/docs/en/env-vars):
190190
from line 204
204204
205205Claude Code requires access to the following URLs. Allowlist these in your proxy configuration and firewall rules, especially in containerized or restricted network environments. The first-run setup connectivity check points here when it can't reach `api.anthropic.com` or `platform.claude.com`; see [Unable to connect to Anthropic services](/docs/en/errors#unable-to-connect-to-anthropic-services) for the check's messages and recovery steps.
206206
207| URL | Required for |
208| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
209| `api.anthropic.com` | Claude API requests, including the WebFetch [domain safety check](/docs/en/data-usage#webfetch-domain-safety-check), feature flag fetches, and telemetry event logging |
210| `claude.ai` | claude.ai account authentication |
211| `claude.com` | claude.ai account sign-in opens a `claude.com` page in the browser, which redirects to `claude.ai`; pre-approved WebFetch documentation lookups also reach this host from the CLI |
212| `platform.claude.com` | Anthropic Console account authentication. OAuth token exchange, refresh, and revocation also go to this host for claude.ai accounts, so both Console and claude.ai sign-ins require it |
213| `mcp-proxy.anthropic.com` | [MCP connectors from claude.ai](/docs/en/mcp#use-mcp-servers-from-claude-ai), including connectors an organization administrator configures. Connector traffic routes through this proxy; connectors are enabled by default for claude.ai-authenticated users. To stop Claude Code from fetching them, set [`ENABLE_CLAUDEAI_MCP_SERVERS=false`](/docs/en/env-vars) or the [`disableClaudeAiConnectors`](/docs/en/settings-reference#disableclaudeaiconnectors) setting |
214| `downloads.claude.ai` | Plugin executable downloads; native installer, native auto-updater, and update version checks |
215| `storage.googleapis.com` | Plugin install counts and metadata shown in `/plugin` |
216| `storage.googleapis.com` | Native installer and native auto-updater on versions prior to 2.1.116 |
217| `registry.npmjs.org` | Plugin installs (fetching npm-source plugin packages and installing plugins' Node.js package dependencies), `npx`-launched MCP servers, and the package registry for npm and bun installs of Claude Code itself |
218| `bridge.claudeusercontent.com` | [Claude in Chrome](/docs/en/chrome) extension WebSocket bridge |
219| `*.frame.claudeusercontent.com` | [Artifact](/docs/en/artifacts) content reads. The CLI fetches an artifact's files from this host when Claude opens one, and only when the Artifact tool is [available](/docs/en/artifacts#availability) for your account. To turn the tool off and drop this requirement, set [`"enableArtifact": false`](/docs/en/settings-reference#enableartifact) or [`CLAUDE_CODE_DISABLE_ARTIFACT=1`](/docs/en/env-vars); Claude Code also honors the deprecated [`disableArtifact`](/docs/en/settings-reference#disableartifact) setting. See [Disable artifacts](/docs/en/artifacts#disable-artifacts) for how these settings interact |
220| `github.com` | Cloning GitHub-hosted [plugin marketplaces](/docs/en/plugins/overview) and plugins, including the official Anthropic marketplace, over HTTPS or SSH. To clone GitHub `owner/repo` sources over HTTPS only, set [`CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1`](/docs/en/env-vars) |
221| `raw.githubusercontent.com` | Changelog feed for [`/release-notes`](/docs/en/commands). In interactive sessions, Claude Code also fetches it in the background at startup when its cached changelog doesn't yet cover the running version, such as the first start after an update; non-interactive and cloud sessions never fetch it |
222| `*-review.googlesource.com` | Gerrit change lookup on `googlesource.com` checkouts. When a Claude Desktop Code tab session starts or resumes on a [trusted](/docs/en/permissions#project-allow-rules-and-workspace-trust) checkout whose `origin` is a `googlesource.com` host, Claude Code asks that host's `-review` server anonymously for the open change matching HEAD's `Change-Id`, once per start or resume. Other session types skip the lookup, and no other Gerrit host is contacted. Optional: disable with [`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`](/docs/en/env-vars) |
223| `http-intake.logs.us5.datadoghq.com` | Operational telemetry events, sent only when the CLI uses the Anthropic API directly, never for Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry. Optional: disable with [`DISABLE_TELEMETRY`](/docs/en/data-usage#telemetry-services) or `DO_NOT_TRACK` |
224| `browser-intake-us5-datadoghq.com` | Operational error reports, sent when the CLI uses the Anthropic API directly and a server-side rollout gate enables them. Optional: disable with `DISABLE_ERROR_REPORTING` or `DISABLE_TELEMETRY`; see [Telemetry services](/docs/en/data-usage#telemetry-services) |
225| `formulae.brew.sh` | Update version checks on Homebrew installs. Other install methods don't contact this host |
226| `code.claude.com` | Claude Code documentation lookups by the built-in claude-code-guide agent and pre-approved WebFetch requests. Blocking this host only affects documentation lookups |
207| URL | Required for |
208| - | - |
209| `api.anthropic.com` | Claude API requests, including the WebFetch [domain safety check](/docs/en/data-usage#webfetch-domain-safety-check), feature flag fetches, and telemetry event logging |
210| `claude.ai` | claude.ai account authentication |
211| `claude.com` | claude.ai account sign-in opens a `claude.com` page in the browser, which redirects to `claude.ai`; pre-approved WebFetch documentation lookups also reach this host from the CLI |
212| `platform.claude.com` | Anthropic Console account authentication. OAuth token exchange, refresh, and revocation also go to this host for claude.ai accounts, so both Console and claude.ai sign-ins require it |
213| `mcp-proxy.anthropic.com` | [MCP connectors from claude.ai](/docs/en/mcp#use-mcp-servers-from-claude-ai), including connectors an organization administrator configures. Connector traffic routes through this proxy; connectors are enabled by default for claude.ai-authenticated users. To stop Claude Code from fetching them, set [`ENABLE_CLAUDEAI_MCP_SERVERS=false`](/docs/en/env-vars) or the [`disableClaudeAiConnectors`](/docs/en/settings-reference#disableclaudeaiconnectors) setting |
214| `downloads.claude.ai` | Plugin executable downloads; native installer, native auto-updater, and update version checks |
215| `storage.googleapis.com` | Plugin install counts and metadata shown in `/plugin` |
216| `storage.googleapis.com` | Native installer and native auto-updater on versions prior to 2.1.116 |
217| `registry.npmjs.org` | Plugin installs (fetching npm-source plugin packages and installing plugins' Node.js package dependencies), `npx`-launched MCP servers, and the package registry for npm and bun installs of Claude Code itself |
218| `bridge.claudeusercontent.com` | [Claude in Chrome](/docs/en/chrome) extension WebSocket bridge |
219| `*.frame.claudeusercontent.com` | [Artifact](/docs/en/artifacts) content reads. The CLI fetches an artifact's files from this host when Claude opens one, and only when the Artifact tool is [available](/docs/en/artifacts#availability) for your account. To turn the tool off and drop this requirement, set [`"enableArtifact": false`](/docs/en/settings-reference#enableartifact) or [`CLAUDE_CODE_DISABLE_ARTIFACT=1`](/docs/en/env-vars); Claude Code also honors the deprecated [`disableArtifact`](/docs/en/settings-reference#disableartifact) setting. See [Disable artifacts](/docs/en/artifacts#disable-artifacts) for how these settings interact |
220| `github.com` | Cloning GitHub-hosted [plugin marketplaces](/docs/en/plugins/overview) and plugins, including the official Anthropic marketplace, over HTTPS or SSH. To clone GitHub `owner/repo` sources over HTTPS only, set [`CLAUDE_CODE_PLUGIN_PREFER_HTTPS=1`](/docs/en/env-vars) |
221| `raw.githubusercontent.com` | Changelog feed for [`/release-notes`](/docs/en/commands). In interactive sessions, Claude Code also fetches it in the background at startup when its cached changelog doesn't yet cover the running version, such as the first start after an update; non-interactive and cloud sessions never fetch it |
222| `*-review.googlesource.com` | Gerrit change lookup on `googlesource.com` checkouts. When a Claude Desktop Code tab session starts or resumes on a [trusted](/docs/en/permissions#project-allow-rules-and-workspace-trust) checkout whose `origin` is a `googlesource.com` host, Claude Code asks that host's `-review` server anonymously for the open change matching HEAD's `Change-Id`, once per start or resume. Other session types skip the lookup, and no other Gerrit host is contacted. Optional: disable with [`CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`](/docs/en/env-vars) |
223| `http-intake.logs.us5.datadoghq.com` | Operational telemetry events, sent only when the CLI uses the Anthropic API directly, never for Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry. Optional: disable with [`DISABLE_TELEMETRY`](/docs/en/data-usage#telemetry-services) or `DO_NOT_TRACK` |
224| `browser-intake-us5-datadoghq.com` | Operational error reports, sent when the CLI uses the Anthropic API directly and a server-side rollout gate enables them. Optional: disable with `DISABLE_ERROR_REPORTING` or `DISABLE_TELEMETRY`; see [Telemetry services](/docs/en/data-usage#telemetry-services) |
225| `formulae.brew.sh` | Update version checks on Homebrew installs. Other install methods don't contact this host |
226| `code.claude.com` | Claude Code documentation lookups by the built-in claude-code-guide agent and pre-approved WebFetch requests. Blocking this host only affects documentation lookups |
227227
228228If you install Claude Code through npm or manage your own binary distribution, end users don't need the native installer and auto-updater uses of `downloads.claude.ai`, but npm and bun installs need their package registry, `registry.npmjs.org`, unless your organization mirrors it. The other uses in the table apply regardless of install method.
229229
output-styles Changed · +20 / -20 lines
from line 23
2323
2424This table shows what each style changes about a session and when it fits:
2525
26| Style | What changes | Use it when |
27| :-------------------------- | :-------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------- |
28| [Proactive](#proactive) | Claude starts work right away and makes reasonable assumptions rather than asking about routine decisions | You want Claude to keep working through routine decisions, and you'll correct course if an assumption is wrong |
29| [Concise](#concise) | Responses lead with the result and leave out preamble, narration, and recaps | Default responses are longer than you want |
30| [Explanatory](#explanatory) | Claude adds short `Insight` blocks that explain the choices behind the code it writes | You're getting to know a codebase or want the reasoning along with the change |
31| [Learning](#learning) | Claude explains its choices and leaves small pieces of code for you to write yourself | You want hands-on coding practice while the task still gets done |
26| Style | What changes | Use it when |
27| :- | :- | :- |
28| [Proactive](#proactive) | Claude starts work right away and makes reasonable assumptions rather than asking about routine decisions | You want Claude to keep working through routine decisions, and you'll correct course if an assumption is wrong |
29| [Concise](#concise) | Responses lead with the result and leave out preamble, narration, and recaps | Default responses are longer than you want |
30| [Explanatory](#explanatory) | Claude adds short `Insight` blocks that explain the choices behind the code it writes | You're getting to know a codebase or want the reasoning along with the change |
31| [Learning](#learning) | Claude explains its choices and leaves small pieces of code for you to write yourself | You want hands-on coding practice while the task still gets done |
3232
3333### Default
3434
from line 159
159159
160160Configure an output style with YAML [frontmatter](/docs/en/glossary#frontmatter) between `---` markers at the top of the file. All fields are optional, and field names use lowercase words separated by hyphens. A misspelled field is ignored without an error. If the YAML doesn't parse, the style still loads under its file name with no fields set; run `claude --debug` to see the parse error.
161161
162| Field | Required | Description |
163| :------------------------- | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
164| `name` | No | Name of the output style, shown in the `/config` picker. Default: the file name |
165| `description` | No | Description of the output style, shown in the `/config` picker |
166| `keep-coding-instructions` | No | Set to `true` to keep Claude Code's built-in software engineering instructions alongside your style. Default: `false` |
167| `force-for-plugin` | No | Plugin output styles only. Set to `true` to apply this style automatically whenever the plugin is enabled, without requiring users to select it. Overrides the user's `outputStyle` setting. If multiple enabled plugins set this, Claude Code uses the first one loaded. Default: `false` |
162| Field | Required | Description |
163| :- | :- | :- |
164| `name` | No | Name of the output style, shown in the `/config` picker. Default: the file name |
165| `description` | No | Description of the output style, shown in the `/config` picker |
166| `keep-coding-instructions` | No | Set to `true` to keep Claude Code's built-in software engineering instructions alongside your style. Default: `false` |
167| `force-for-plugin` | No | Plugin output styles only. Set to `true` to apply this style automatically whenever the plugin is enabled, without requiring users to select it. Overrides the user's `outputStyle` setting. If multiple enabled plugins set this, Claude Code uses the first one loaded. Default: `false` |
168168
169169<span id="comparisons-to-related-features" />
170170
from line 174
174174
175175This table matches what you want to the feature that does it:
176176
177| You want | Use | Why it fits |
178| :--------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------- |
179| Every response in a certain voice, length, or format, or Claude in a different role | An output style | It applies to the whole session, and you switch styles with one command |
180| Claude to know your project's conventions, commands, and structure | [CLAUDE.md](/docs/en/memory) | It holds what Claude should know about the codebase, and it stays loaded whichever style you pick |
181| Instructions for one kind of task, such as a release checklist or a review procedure | A [skill](/docs/en/skills) | Claude loads it only when you invoke it or the task matches, so it doesn't shape unrelated responses |
182| Something to happen every time without exception, such as formatting after each edit or blocking a command | A [hook](/docs/en/hooks-guide) | Claude Code runs a hook itself at a lifecycle event, so it doesn't depend on Claude following an instruction |
183| A helper with its own instructions, model, and tools for a focused task | A [subagent](/docs/en/sub-agents) | It runs in a separate context with its own system prompt and returns a summary to your conversation |
184| An addition to Claude's instructions that you pass when you start Claude Code | [`--append-system-prompt`](/docs/en/cli-reference#system-prompt-flags) | It appends to the system prompt without removing anything |
177| You want | Use | Why it fits |
178| :- | :- | :- |
179| Every response in a certain voice, length, or format, or Claude in a different role | An output style | It applies to the whole session, and you switch styles with one command |
180| Claude to know your project's conventions, commands, and structure | [CLAUDE.md](/docs/en/memory) | It holds what Claude should know about the codebase, and it stays loaded whichever style you pick |
181| Instructions for one kind of task, such as a release checklist or a review procedure | A [skill](/docs/en/skills) | Claude loads it only when you invoke it or the task matches, so it doesn't shape unrelated responses |
182| Something to happen every time without exception, such as formatting after each edit or blocking a command | A [hook](/docs/en/hooks-guide) | Claude Code runs a hook itself at a lifecycle event, so it doesn't depend on Claude following an instruction |
183| A helper with its own instructions, model, and tools for a focused task | A [subagent](/docs/en/sub-agents) | It runs in a separate context with its own system prompt and returns a summary to your conversation |
184| An addition to Claude's instructions that you pass when you start Claude Code | [`--append-system-prompt`](/docs/en/cli-reference#system-prompt-flags) | It appends to the system prompt without removing anything |
185185
186186These features combine. For example, you can use CLAUDE.md for what Claude should know, an output style for how it responds, and a hook for anything that has to be guaranteed. [Extend Claude Code](/docs/en/features-overview) compares the rest of the extension features.
187187
overview Changed · +11 / -11 lines
from line 218
218218
219219Beyond the [Terminal](/docs/en/quickstart), [VS Code](/docs/en/vs-code), [JetBrains](/docs/en/jetbrains), [Desktop](/docs/en/desktop), and [Web](/docs/en/claude-code-on-the-web) surfaces above, Claude Code integrates with CI/CD, chat, and browser workflows:
220220
221| What I want to do | Best option |
222| ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
223| Continue a local session from my phone or another device | [Remote Control](/docs/en/remote-control) |
224| Push events from Telegram, Discord, iMessage, or my own webhooks into a session | [Channels](/docs/en/channels) |
225| Start a task locally, continue on mobile | [`claude --cloud`](/docs/en/claude-code-on-the-web#from-terminal-to-cloud), then the [Claude mobile app](/docs/en/mobile) |
226| Run Claude on a recurring schedule | [Routines](/docs/en/routines) or [Desktop scheduled tasks](/docs/en/desktop-scheduled-tasks) |
227| Automate PR reviews and issue triage | [GitHub Actions](/docs/en/github-actions) or [GitLab CI/CD](/docs/en/gitlab-ci-cd) |
228| Get automatic code review on every PR | [GitHub Code Review](/docs/en/code-review) |
229| Route bug reports from Slack to pull requests | [Slack](/docs/en/slack) |
230| Debug live web applications | [Chrome](/docs/en/chrome) |
231| Build custom agents for your own workflows | [Agent SDK](/docs/en/agent-sdk/overview) |
221| What I want to do | Best option |
222| - | - |
223| Continue a local session from my phone or another device | [Remote Control](/docs/en/remote-control) |
224| Push events from Telegram, Discord, iMessage, or my own webhooks into a session | [Channels](/docs/en/channels) |
225| Start a task locally, continue on mobile | [`claude --cloud`](/docs/en/claude-code-on-the-web#from-terminal-to-cloud), then the [Claude mobile app](/docs/en/mobile) |
226| Run Claude on a recurring schedule | [Routines](/docs/en/routines) or [Desktop scheduled tasks](/docs/en/desktop-scheduled-tasks) |
227| Automate PR reviews and issue triage | [GitHub Actions](/docs/en/github-actions) or [GitLab CI/CD](/docs/en/gitlab-ci-cd) |
228| Get automatic code review on every PR | [GitHub Code Review](/docs/en/code-review) |
229| Route bug reports from Slack to pull requests | [Slack](/docs/en/slack) |
230| Debug live web applications | [Chrome](/docs/en/chrome) |
231| Build custom agents for your own workflows | [Agent SDK](/docs/en/agent-sdk/overview) |
232232
233233## Next steps
234234
permission-modes Changed · +51 / -50 lines
from line 10
1010
1111Each mode makes a different tradeoff between convenience and oversight. The table below shows what Claude can do without a permission prompt in each mode. Manual mode appears under its config value, `default`.
1212
13| Mode | What runs without asking | Best for |
14| :------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------- | :---------------------------------------------- |
15| `default` | Reads only | Reviewing every action yourself, sensitive work |
16| [`acceptEdits`](#auto-approve-file-edits-with-acceptedits-mode) | Reads, file edits, and common filesystem commands (`mkdir`, `touch`, `mv`, `cp`, etc.) | Iterating on code you're reviewing |
17| [`plan`](#analyze-before-you-edit-with-plan-mode) | Reads, plus classifier-approved commands when [auto mode](#eliminate-prompts-with-auto-mode) is available | Exploring a codebase before changing it |
18| [`auto`](#eliminate-prompts-with-auto-mode) | Everything, with background safety checks | Long tasks, reducing prompt fatigue |
19| [`dontAsk`](#allow-only-pre-approved-tools-with-dontask-mode) | Reads and pre-approved tools; anything that would prompt is denied | Locked-down CI and scripts |
20| [`bypassPermissions`](#skip-all-checks-with-bypasspermissions-mode) | Everything | Isolated containers and VMs only |
13| Mode | What runs without asking | Best for |
14| :- | :- | :- |
15| `default` | Reads only | Reviewing every action yourself, sensitive work |
16| [`acceptEdits`](#auto-approve-file-edits-with-acceptedits-mode) | Reads, file edits, and common filesystem commands (`mkdir`, `touch`, `mv`, `cp`, etc.) | Iterating on code you're reviewing |
17| [`plan`](#analyze-before-you-edit-with-plan-mode) | Reads, plus classifier-approved commands when [auto mode](#eliminate-prompts-with-auto-mode) is available | Exploring a codebase before changing it |
18| [`auto`](#eliminate-prompts-with-auto-mode) | Everything, with background safety checks | Long tasks, reducing prompt fatigue |
19| [`dontAsk`](#allow-only-pre-approved-tools-with-dontask-mode) | Reads and pre-approved tools; anything that would prompt is denied | Locked-down CI and scripts |
20| [`bypassPermissions`](#skip-all-checks-with-bypasspermissions-mode) | Everything | Isolated containers and VMs only |
2121
2222The mode that reviews every action is named **Manual** in the CLI, in `claude --help`, in the VS Code and JetBrains extensions, and in the desktop app. Its config value is `default`, which is what hooks and SDK integrations use. The CLI accepts `manual` as an alias wherever you type the value, for example `claude --permission-mode manual` or `"defaultMode": "manual"`. The Manual label and the `manual` alias require Claude Code v2.1.200 or later. The desktop app's label doesn't depend on your CLI version.
2323
from line 44
4444
4545Permission modes decide whether Claude asks before an action, and the [Bash sandbox](/docs/en/sandboxing) and outer [isolation boundaries](/docs/en/sandbox-environments) decide what an action can reach once it runs. Each row below pairs a goal with the flags or settings that get you there and the isolation it needs, as a starting point. [Available modes](#available-modes) lists what runs without a prompt in each mode.
4646
47| You want to | Start with | Isolation needed | Notes |
48| :------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
49| Review every action yourself | Manual mode: `claude --permission-mode default` | None | Sensitive work, unfamiliar code |
50| Iterate locally with fewer prompts, without a classifier | Manual mode plus the Bash sandbox in [auto-allow mode](/docs/en/sandboxing#sandbox-modes): `claude --permission-mode default`, then run `/sandbox` and select auto-allow | The built-in Bash sandbox, on macOS, Linux, and WSL2 | Deny rules still apply, and ask rules that name a command, such as `Bash(git push *)`, still prompt. To turn the sandbox on from a settings file instead, set [`sandbox.enabled`](/docs/en/settings-reference#sandbox-enabled) to `true` |
51| Explore before changing anything | `claude --permission-mode plan` | None | Claude Code blocks edits until you [approve a plan](#review-and-approve-a-plan) |
52| Work hands-off in auto mode | `claude --permission-mode auto`, the [built-in starting permission mode](#which-mode-a-session-starts-in) with v2.1.283 or later | None; a sandbox or container adds defense in depth | Requires a [supported model](#eliminate-prompts-with-auto-mode), and your organization can [turn auto mode off](#eliminate-prompts-with-auto-mode) |
53| Run in CI with an exact allowlist | `claude -p "run the test suite" --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read"` | None beyond what your CI runner provides | [Cloud sessions](/docs/en/claude-code-on-the-web) ignore `dontAsk` from settings files |
54| Run fully unattended inside a container | `claude -p "<prompt>" --dangerously-skip-permissions` | Required: a container, VM, or the [sandbox runtime](/docs/en/sandbox-environments#sandbox-runtime); on Linux and macOS, run it as a [non-root user](#skip-all-checks-with-bypasspermissions-mode) | Cloud sessions ignore this mode from settings files. In this `-p` run, the [few calls that would still prompt](#skip-all-checks-with-bypasspermissions-mode) are denied instead |
47| You want to | Start with | Isolation needed | Notes |
48| :- | :- | :- | :- |
49| Review every action yourself | Manual mode: `claude --permission-mode default` | None | Sensitive work, unfamiliar code |
50| Iterate locally with fewer prompts, without a classifier | Manual mode plus the Bash sandbox in [auto-allow mode](/docs/en/sandboxing#sandbox-modes): `claude --permission-mode default`, then run `/sandbox` and select auto-allow | The built-in Bash sandbox, on macOS, Linux, and WSL2 | Deny rules still apply, and ask rules that name a command, such as `Bash(git push *)`, still prompt. To turn the sandbox on from a settings file instead, set [`sandbox.enabled`](/docs/en/settings-reference#sandbox-enabled) to `true` |
51| Explore before changing anything | `claude --permission-mode plan` | None | Claude Code blocks edits until you [approve a plan](#review-and-approve-a-plan) |
52| Work hands-off in auto mode | `claude --permission-mode auto`, the [built-in starting permission mode](#which-mode-a-session-starts-in) with v2.1.283 or later | None; a sandbox or container adds defense in depth | Requires a [supported model](#eliminate-prompts-with-auto-mode), and your organization can [turn auto mode off](#eliminate-prompts-with-auto-mode) |
53| Run in CI with an exact allowlist | `claude -p "run the test suite" --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read"` | None beyond what your CI runner provides | [Cloud sessions](/docs/en/claude-code-on-the-web) ignore `dontAsk` from settings files |
54| Run fully unattended inside a container | `claude -p "<prompt>" --dangerously-skip-permissions` | Required: a container, VM, or the [sandbox runtime](/docs/en/sandbox-environments#sandbox-runtime); on Linux and macOS, run it as a [non-root user](#skip-all-checks-with-bypasspermissions-mode) | Cloud sessions ignore this mode from settings files. In this `-p` run, the [few calls that would still prompt](#skip-all-checks-with-bypasspermissions-mode) are denied instead |
5555
5656The Bash sandbox and auto mode work independently and combine, with the exceptions listed under [Sandbox modes](/docs/en/sandboxing#sandbox-modes). For the full interaction, see [How sandboxing relates to permissions and permission modes](/docs/en/sandboxing#how-sandboxing-relates-to-permissions-and-permission-modes) and [How isolation relates to permission modes](/docs/en/sandbox-environments#how-isolation-relates-to-permission-modes).
5757
from line 75
7575
7676The built-in default depends on how you run Claude Code. The first row that matches your session applies. The table covers sessions you start in a terminal or through the VS Code extension; for the desktop app and claude.ai, see the Desktop and Web tabs in [Switch permission modes](#switch-permission-modes).
7777
78| How you run Claude Code | Built-in starting permission mode |
79| :------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
80| Any settings file sets `disableAutoMode` to `"disable"` | `default` |
81| `claude -p` or the [Agent SDK](/docs/en/agent-sdk/permissions) | `default` |
78| How you run Claude Code | Built-in starting permission mode |
79| :- | :- |
80| Any settings file sets `disableAutoMode` to `"disable"` | `default` |
81| `claude -p` or the [Agent SDK](/docs/en/agent-sdk/permissions) | `default` |
8282| In a terminal or through the [VS Code extension](/docs/en/vs-code) | `auto` with Claude Code v2.1.283 or later; on earlier versions, `auto` on Pro, Max, or Team plans in sessions that [fetch feature flags](/docs/en/env-vars#features-that-need-feature-flag-fetching), and `default` otherwise |
8383
8484In your [first session after an install or upgrade](/docs/en/env-vars#first-session-after-an-install-or-upgrade), Claude Code can choose the starting permission mode before its feature flags arrive. That session can start in a different permission mode than the table gives, and your next session matches the table.
from line 98
9898
9999You can set the starting permission mode for one session, or as a default for every session on a machine, in a project, or in an organization. When more than one settings file sets `permissions.defaultMode`, [settings precedence](/docs/en/settings#settings-precedence) decides, so a project or managed value outranks `~/.claude/settings.json`. To change the permission mode of a session that's already running, see [Switch permission modes](#switch-permission-modes).
100100
101| To set the starting permission mode for | Do this |
102| :----------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
103| One session you're about to start | Pass the permission mode as a flag, for example `claude --permission-mode default` |
104| Every terminal session you start on this machine | Set `permissions.defaultMode` in `~/.claude/settings.json`. For what the VS Code extension reads, see [Switch permission modes](#switch-permission-modes) |
105| Every terminal session you start in one project | Set `permissions.defaultMode` in the project's `.claude/settings.json`. Sessions you start in a terminal honor every value except `auto` and `bypassPermissions`; sessions the VS Code extension starts don't read project settings for the starting permission mode |
106| Every terminal session in your organization | Set `permissions.defaultMode` in [managed settings](/docs/en/managed-settings). Terminal sessions start in that mode and people can still switch to auto mode; for what the VS Code extension reads, see [Switch permission modes](#switch-permission-modes). To remove auto mode so nobody can select it, set `permissions.disableAutoMode` to `"disable"` instead |
101| To set the starting permission mode for | Do this |
102| :- | :- |
103| One session you're about to start | Pass the permission mode as a flag, for example `claude --permission-mode default` |
104| Every terminal session you start on this machine | Set `permissions.defaultMode` in `~/.claude/settings.json`. For what the VS Code extension reads, see [Switch permission modes](#switch-permission-modes) |
105| Every terminal session you start in one project | Set `permissions.defaultMode` in the project's `.claude/settings.json`. Sessions you start in a terminal honor every value except `auto` and `bypassPermissions`; sessions the VS Code extension starts don't read project settings for the starting permission mode |
106| Every terminal session in your organization | Set `permissions.defaultMode` in [managed settings](/docs/en/managed-settings). Terminal sessions start in that mode and people can still switch to auto mode; for what the VS Code extension reads, see [Switch permission modes](#switch-permission-modes). To remove auto mode so nobody can select it, set `permissions.disableAutoMode` to `"disable"` instead |
107107
108108This example makes every terminal session on your machine start in Manual mode, whose config value is `default`. Save it in `~/.claude/settings.json`:
109109
from line 151
151151 <Tab title="VS Code">
152152 **During a session**: click the mode indicator at the bottom of the prompt box. It uses these labels for the modes on this page:
153153
154 | UI label | Mode |
155 | :----------------- | :------------------ |
156 | Manual | `default` |
157 | Edit automatically | `acceptEdits` |
158 | Plan | `plan` |
159 | Auto | `auto` |
154 | UI label | Mode |
155 | :- | :- |
156 | Manual | `default` |
157 | Edit automatically | `acceptEdits` |
158 | Plan | `plan` |
159 | Auto | `auto` |
160160 | Bypass permissions | `bypassPermissions` |
161161
162162 **As a default**: to pin the permission mode conversations start in, set `claudeCode.initialPermissionMode` in your VS Code user settings to `default`, `manual`, `acceptEdits`, `plan`, or `bypassPermissions`. The setting doesn't accept `auto`; to start in Auto, leave it unset and pick **Auto** from the mode indicator once, as item 2 below describes. The extension starts each new conversation in the first of these that applies:
from line 430
430430 The first read outside the working directories
431431</h3>
432432
433While [`permissions.blockReadsOutsideWorkingDirectories`](/docs/en/settings-reference#permissions-blockreadsoutsideworkingdirectories) is off, file reads run without a prompt in auto mode, including reads outside the [working directories](/docs/en/permissions#working-directories). The first time Claude uses the Read, Grep, or Glob tool on a path outside them, Claude Code asks you whether to keep allowing those reads.
433While [`permissions.blockReadsOutsideWorkingDirectories`](/docs/en/settings-reference#permissions-blockreadsoutsideworkingdirectories) is off, file reads run without a prompt in auto mode, including reads outside the [working directories](/docs/en/permissions#working-directories). The first time Claude uses the Read, Grep, or Glob tool on a path outside them, Claude Code asks whether to allow that read.
434434
435435The prompt doesn't appear in non-interactive `-p` runs or background sessions; reads there run as before.
436436
437437Whatever you answer, Claude keeps working:
438438
439* **Keep allowing**: the read runs, later reads outside the working directories run as before, and Claude Code records your answer so the prompt doesn't appear again
440* **Block from now on**: the read is refused, and Claude Code sets [`permissions.blockReadsOutsideWorkingDirectories`](/docs/en/settings-reference#permissions-blockreadsoutsideworkingdirectories) to `true` in your user settings, which makes the file tools refuse such reads in every later session and every permission mode. To let Claude read such a path later, add its directory with `/add-dir` or remove the setting.
441* **Ask again next time**: the read is refused, and the next read outside the working directories prompts again
439* **Yes, and keep allowing any reads outside the working directories**: the read runs, later reads outside the working directories run as before, and Claude Code records your answer so the prompt doesn't appear again
440* **No, and block reads outside the working directories from now on**: the read is refused, and Claude Code sets [`permissions.blockReadsOutsideWorkingDirectories`](/docs/en/settings-reference#permissions-blockreadsoutsideworkingdirectories) to `true` in your user settings, which makes the file tools refuse such reads in every later session and every permission mode. To let Claude read such a path later, add its directory with `/add-dir` or remove the setting.
441* **No, and ask again next time**: the read is refused, and the next read outside the working directories prompts again
442* **Yes, but ask again next time**: the read runs, nothing is saved, and the next read outside the working directories prompts again
442443
443444### Boundaries you state in conversation
444445
from line 589
588589
589590Writes to a small set of paths are never auto-approved, except in `bypassPermissions` mode and in interactive terminal sessions in plan mode with [bypass permissions](#skip-all-checks-with-bypasspermissions-mode) available. This prevents accidental corruption of repository state and Claude's own configuration.
590591
591| Mode | Protected-path writes |
592| :----------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
593| `default`, `acceptEdits` | Prompted |
594| `plan` | Allowed in interactive terminal sessions with [bypass permissions](#skip-all-checks-with-bypasspermissions-mode) available. Otherwise, routed to the classifier when [auto mode](#eliminate-prompts-with-auto-mode) is available during planning, and prompted when it isn't |
595| `auto` | Routed to the classifier |
596| `dontAsk` | Denied |
597| `bypassPermissions` | Allowed |
592| Mode | Protected-path writes |
593| :- | :- |
594| `default`, `acceptEdits` | Prompted |
595| `plan` | Allowed in interactive terminal sessions with [bypass permissions](#skip-all-checks-with-bypasspermissions-mode) available. Otherwise, routed to the classifier when [auto mode](#eliminate-prompts-with-auto-mode) is available during planning, and prompted when it isn't |
596| `auto` | Routed to the classifier |
597| `dontAsk` | Denied |
598| `bypassPermissions` | Allowed |
598599
599600In a session started with [`--restricted`](/docs/en/cli-reference#cli-flags), which requires Claude Code v2.1.248 or later, the classifier can't approve protected-path writes.
600601
from line 637
636637
637638What happens instead depends on your permission mode:
638639
639| Mode | What Claude Code does with a critical-path removal |
640| :----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
641| `default`, `acceptEdits` | Asks you to approve it |
642| `plan` | Asks you to approve it. When [the classifier reviews commands during planning](#analyze-before-you-edit-with-plan-mode) and no bypass permissions are available, handles it as in `auto` mode |
643| `auto` | Asks you to approve it in the terminal, with a time limit. Elsewhere, denies it |
644| `dontAsk` | Denies it |
645| `bypassPermissions` | Asks you to approve it, with a time limit in the terminal |
640| Mode | What Claude Code does with a critical-path removal |
641| :- | :- |
642| `default`, `acceptEdits` | Asks you to approve it |
643| `plan` | Asks you to approve it. When [the classifier reviews commands during planning](#analyze-before-you-edit-with-plan-mode) and no bypass permissions are available, handles it as in `auto` mode |
644| `auto` | Asks you to approve it in the terminal, with a time limit. Elsewhere, denies it |
645| `dontAsk` | Denies it |
646| `bypassPermissions` | Asks you to approve it, with a time limit in the terminal |
646647
647648If an explicit [ask rule](/docs/en/permissions#manage-permissions) matches the command, Claude Code asks you instead, even in `auto` mode and without a time limit. In modes that ask, a [`PermissionRequest` hook](/docs/en/hooks#permissionrequest) can answer the prompt.
648649