Initial commit to new repository
This commit is contained in:
935
docs/claude-code-docs-main/en/reference/sdk/hooks-reference.md
Normal file
935
docs/claude-code-docs-main/en/reference/sdk/hooks-reference.md
Normal file
@@ -0,0 +1,935 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://vineetagarwal-code-claude-code.mintlify.app/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Hooks reference
|
||||
|
||||
> Full reference for every hook event, its input payload, output schema, and the effect each exit code has on Claude's behavior.
|
||||
|
||||
Hooks are shell commands, HTTP endpoints, LLM prompts, or in-process callbacks that fire at defined points in Claude's agentic loop. They let you inject logic before or after tool calls, intercept permission requests, react to session lifecycle events, and more.
|
||||
|
||||
## Configuration
|
||||
|
||||
Hooks are configured in any Claude Code settings file. The top-level `hooks` key maps event names to an array of matcher objects.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "echo 'About to run bash command' >&2"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "/usr/local/bin/lint-changed-file '$TOOL_INPUT'"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "notify-send 'Claude finished'"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Settings file locations
|
||||
|
||||
| Scope | Path | Priority |
|
||||
| ------- | ----------------------------- | -------- |
|
||||
| User | `~/.claude/settings.json` | Low |
|
||||
| Project | `.claude/settings.json` | Medium |
|
||||
| Local | `.claude/settings.local.json` | High |
|
||||
|
||||
Higher-priority settings files take precedence. All hooks across all files run; they are not overridden.
|
||||
|
||||
### Matcher configuration
|
||||
|
||||
<ResponseField name="matcher" type="string">
|
||||
A string pattern that filters when these hooks run. The field matched depends on the event:
|
||||
|
||||
* `PreToolUse` / `PostToolUse` / `PostToolUseFailure` / `PermissionRequest` / `PermissionDenied` — matched against `tool_name`
|
||||
* `Notification` — matched against `notification_type`
|
||||
* `SessionStart` — matched against `source` (`startup`, `resume`, `clear`, `compact`)
|
||||
* `Setup` — matched against `trigger` (`init`, `maintenance`)
|
||||
* `SubagentStart` / `SubagentStop` — matched against `agent_type`
|
||||
* `PreCompact` / `PostCompact` — matched against `trigger` (`manual`, `auto`)
|
||||
* `StopFailure` — matched against `error`
|
||||
* `ConfigChange` — matched against `source`
|
||||
* `InstructionsLoaded` — matched against `load_reason`
|
||||
* `Elicitation` / `ElicitationResult` — matched against `mcp_server_name`
|
||||
* `FileChanged` — matched against filenames (e.g., `".envrc|.env"`)
|
||||
|
||||
Omit `matcher` to run the hook for all instances of the event.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="hooks" type="HookCommand[]" required>
|
||||
One or more hook definitions to execute when the matcher fires.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
## Hook types
|
||||
|
||||
### `command` — shell command
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "command",
|
||||
"command": "jq '.tool_name' && my-validator",
|
||||
"timeout": 30,
|
||||
"shell": "bash",
|
||||
"async": false,
|
||||
"once": false,
|
||||
"if": "Bash(git *)",
|
||||
"statusMessage": "Validating command..."
|
||||
}
|
||||
```
|
||||
|
||||
The hook input JSON is piped to the command's stdin. The `CLAUDE_ENV_FILE` environment variable is set for `CwdChanged` and `FileChanged` hooks — write `export KEY=value` lines there to inject environment variables into subsequent Bash tool calls.
|
||||
|
||||
<ResponseField name="command" type="string" required>
|
||||
Shell command to execute.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="timeout" type="number">
|
||||
Timeout in seconds. Defaults to the global hook timeout (60 s).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="shell" type="'bash' | 'powershell'">
|
||||
Shell interpreter. `bash` uses your `$SHELL` (bash/zsh/sh). Defaults to `bash`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="async" type="boolean">
|
||||
When `true`, the hook runs in the background without blocking Claude. Output is ignored.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="asyncRewake" type="boolean">
|
||||
When `true`, the hook runs in the background but wakes the model if it exits with code 2. Implies `async: true`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="once" type="boolean">
|
||||
When `true`, the hook runs once and is removed from the configuration after execution.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="if" type="string">
|
||||
Permission rule syntax (e.g., `"Bash(git *)"`) evaluated against the hook input. The hook is skipped if the condition does not match. Avoids spawning processes for non-matching tool calls.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="statusMessage" type="string">
|
||||
Custom message shown in the spinner while the hook runs.
|
||||
</ResponseField>
|
||||
|
||||
### `prompt` — LLM evaluation
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "prompt",
|
||||
"prompt": "Check whether this bash command is safe: $ARGUMENTS",
|
||||
"model": "claude-haiku-4-5",
|
||||
"timeout": 30
|
||||
}
|
||||
```
|
||||
|
||||
The `$ARGUMENTS` placeholder is replaced with the hook input JSON. The model's response is treated as the hook output.
|
||||
|
||||
<ResponseField name="prompt" type="string" required>
|
||||
Prompt sent to the model. Use `$ARGUMENTS` to embed the hook input.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="model" type="string">
|
||||
Model to use. Defaults to the small fast model.
|
||||
</ResponseField>
|
||||
|
||||
### `agent` — agentic verifier
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "agent",
|
||||
"prompt": "Verify that unit tests ran and passed.",
|
||||
"model": "claude-haiku-4-5",
|
||||
"timeout": 120
|
||||
}
|
||||
```
|
||||
|
||||
Runs a short agentic loop that can call tools to verify the action. Use for `PostToolUse` hooks where you want the verifier to read files or run commands.
|
||||
|
||||
<ResponseField name="prompt" type="string" required>
|
||||
Verification prompt. Use `$ARGUMENTS` to embed the hook input.
|
||||
</ResponseField>
|
||||
|
||||
### `http` — HTTP endpoint
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "http",
|
||||
"url": "https://my-server.example.com/hook",
|
||||
"headers": {
|
||||
"Authorization": "Bearer $MY_TOKEN"
|
||||
},
|
||||
"allowedEnvVars": ["MY_TOKEN"],
|
||||
"timeout": 10
|
||||
}
|
||||
```
|
||||
|
||||
POSTs the hook input JSON to the given URL. Header values can reference environment variables using `$VAR_NAME` syntax, but only variables listed in `allowedEnvVars` are interpolated.
|
||||
|
||||
<ResponseField name="url" type="string" required>
|
||||
URL to POST the hook input JSON to.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="headers" type="Record<string, string>">
|
||||
Additional request headers.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="allowedEnvVars" type="string[]">
|
||||
Environment variable names that may be interpolated in header values.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
## Base hook input
|
||||
|
||||
Every hook receives a JSON object on stdin with these fields present for all event types.
|
||||
|
||||
<ResponseField name="hook_event_name" type="string" required>
|
||||
The event that fired (e.g., `"PreToolUse"`).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="session_id" type="string" required>
|
||||
Current session identifier.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="transcript_path" type="string" required>
|
||||
Absolute path to the JSONL transcript file for this session.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="cwd" type="string" required>
|
||||
Current working directory at the time the hook fired.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="permission_mode" type="string">
|
||||
Active permission mode (`"default"`, `"acceptEdits"`, `"bypassPermissions"`, `"plan"`, `"dontAsk"`).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="agent_id" type="string">
|
||||
Subagent identifier. Present only when the hook fires from within a subagent. Use this field to distinguish subagent calls from main-thread calls.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="agent_type" type="string">
|
||||
Agent type name (e.g., `"general-purpose"`, `"code-reviewer"`). Present when the hook fires from a subagent, or on the main thread of a session started with `--agent`.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
## Sync hook output (JSON on stdout)
|
||||
|
||||
For blocking hooks, write a JSON object to stdout before exiting. The schema is the same for all events, with event-specific fields nested under `hookSpecificOutput`.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"continue": true,
|
||||
"suppressOutput": false,
|
||||
"decision": "approve",
|
||||
"reason": "Command looks safe",
|
||||
"systemMessage": "The hook approved this action.",
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PreToolUse",
|
||||
"permissionDecision": "allow",
|
||||
"additionalContext": "Verified by security scanner."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<ResponseField name="continue" type="boolean">
|
||||
When `false`, Claude stops the current turn immediately.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="suppressOutput" type="boolean">
|
||||
When `true`, the hook's stdout is not shown in transcript mode.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="decision" type="'approve' | 'block'">
|
||||
Explicit approve/block decision. Takes effect only when the CLI reads it.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="systemMessage" type="string">
|
||||
Message injected into Claude's context as a system turn.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="reason" type="string">
|
||||
Human-readable reason for the decision. Shown to the user when a hook blocks an action.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="hookSpecificOutput" type="object">
|
||||
Event-specific output. See each event section below for the allowed fields.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
## Hook events
|
||||
|
||||
### `PreToolUse`
|
||||
|
||||
Fires immediately before a tool executes. You can inspect the tool input, approve or block the call, or modify the input before it reaches the tool.
|
||||
|
||||
**When it fires:** Before every tool invocation.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="tool_name" type="string">
|
||||
Name of the tool about to run (e.g., `"Bash"`, `"Write"`, `"mcp__myserver__my_tool"`).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="tool_input" type="unknown">
|
||||
The raw tool input object as Claude submitted it.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="tool_use_id" type="string">
|
||||
Unique ID for this tool invocation.
|
||||
</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | ----------------------------------------------------------- |
|
||||
| `0` | Stdout/stderr not shown. Hook output JSON applied if valid. |
|
||||
| `2` | Stderr shown to Claude; tool call is **blocked**. |
|
||||
| Other | Stderr shown to user only; tool call continues. |
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="hookEventName" type="literal: 'PreToolUse'" required>
|
||||
Must be `"PreToolUse"`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="permissionDecision" type="'allow' | 'deny' | 'ask'">
|
||||
Override the permission decision for this tool call. `"allow"` approves the call; `"deny"` blocks it; `"ask"` forces the permission dialog.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="permissionDecisionReason" type="string">
|
||||
Reason string shown to the user when the decision is `"deny"` or `"ask"`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="updatedInput" type="Record<string, unknown>">
|
||||
Replacement tool input. When provided, the tool receives this object instead of Claude's original input.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="additionalContext" type="string">
|
||||
Text injected into Claude's context for this turn.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### `PostToolUse`
|
||||
|
||||
Fires after a tool completes successfully. You can observe the tool output or inject context for Claude to act on.
|
||||
|
||||
**When it fires:** After every successful tool execution.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="tool_name" type="string">Tool that ran.</ResponseField>
|
||||
<ResponseField name="tool_input" type="unknown">Input that was passed to the tool.</ResponseField>
|
||||
<ResponseField name="tool_response" type="unknown">The tool's output.</ResponseField>
|
||||
<ResponseField name="tool_use_id" type="string">Unique ID for this invocation.</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | ------------------------------------------------------- |
|
||||
| `0` | Stdout shown in transcript mode (Ctrl+O). |
|
||||
| `2` | Stderr shown to Claude immediately as a system message. |
|
||||
| Other | Stderr shown to user only. |
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="additionalContext" type="string">
|
||||
Context injected into Claude's conversation after the tool result.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="updatedMCPToolOutput" type="unknown">
|
||||
Replacement for the MCP tool's output. Only effective for MCP tool calls.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### `PostToolUseFailure`
|
||||
|
||||
Fires when a tool call ends in an error or is interrupted.
|
||||
|
||||
**When it fires:** When a tool throws or is aborted.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="tool_name" type="string">Tool that failed.</ResponseField>
|
||||
<ResponseField name="tool_input" type="unknown">Input that was passed to the tool.</ResponseField>
|
||||
<ResponseField name="tool_use_id" type="string">Unique ID for this invocation.</ResponseField>
|
||||
<ResponseField name="error" type="string">Error message from the tool.</ResponseField>
|
||||
<ResponseField name="is_interrupt" type="boolean">Whether the failure was caused by an interrupt signal.</ResponseField>
|
||||
|
||||
**Exit codes:** Same as `PostToolUse`. Hook output and exit codes are logged but do not affect the failed tool result.
|
||||
|
||||
***
|
||||
|
||||
### `PermissionRequest`
|
||||
|
||||
Fires when a permission dialog would be shown to the user. Hooks can programmatically approve or deny without showing any UI.
|
||||
|
||||
**When it fires:** When Claude requests permission for a tool call and the default behavior is to prompt.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="tool_name" type="string">Tool requesting permission.</ResponseField>
|
||||
<ResponseField name="tool_input" type="unknown">Input the tool would receive if approved.</ResponseField>
|
||||
<ResponseField name="permission_suggestions" type="PermissionUpdate[]">Suggested permission rules (allow/deny) that the UI would offer.</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| `0` | Hook decision applied if `hookSpecificOutput.decision` is set; otherwise falls through to normal dialog. |
|
||||
| Other | Stderr shown to user; falls through to normal dialog. |
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="hookEventName" type="literal: 'PermissionRequest'" required>
|
||||
Must be `"PermissionRequest"`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="decision" type="object">
|
||||
The approval or denial decision.
|
||||
|
||||
<Expandable title="Allow decision">
|
||||
```json theme={null}
|
||||
{
|
||||
"behavior": "allow",
|
||||
"updatedInput": { ... },
|
||||
"updatedPermissions": [...]
|
||||
}
|
||||
```
|
||||
</Expandable>
|
||||
|
||||
<Expandable title="Deny decision">
|
||||
```json theme={null}
|
||||
{
|
||||
"behavior": "deny",
|
||||
"message": "Blocked by security policy.",
|
||||
"interrupt": false
|
||||
}
|
||||
```
|
||||
|
||||
When `interrupt` is `true`, the current turn is aborted after denial.
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### `PermissionDenied`
|
||||
|
||||
Fires when a tool call is denied (by rules, mode, or classifier). You can instruct Claude to retry the action.
|
||||
|
||||
**When it fires:** After every permission denial.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="tool_name" type="string">Denied tool.</ResponseField>
|
||||
<ResponseField name="tool_input" type="unknown">Input that was denied.</ResponseField>
|
||||
<ResponseField name="tool_use_id" type="string">Unique ID for this invocation.</ResponseField>
|
||||
<ResponseField name="reason" type="string">Human-readable denial reason.</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | -------------------------------- |
|
||||
| `0` | Stdout shown in transcript mode. |
|
||||
| Other | Stderr shown to user only. |
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="retry" type="boolean">
|
||||
When `true`, Claude is told it may retry the denied action.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### `Stop`
|
||||
|
||||
Fires just before Claude concludes its response for the current turn.
|
||||
|
||||
**When it fires:** When the model is about to stop and return control to the user.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="stop_hook_active" type="boolean">
|
||||
Whether a Stop hook is currently running (prevents infinite loops if your Stop hook itself would trigger a Stop).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="last_assistant_message" type="string">
|
||||
Text content of the last assistant message before stopping. Saves you from parsing the transcript file.
|
||||
</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | --------------------------------------------------------------------------- |
|
||||
| `0` | Stdout/stderr not shown. |
|
||||
| `2` | Stderr injected as a system message; Claude **continues** the conversation. |
|
||||
| Other | Stderr shown to user only; Claude stops. |
|
||||
|
||||
<Tip>
|
||||
Use exit code 2 from a Stop hook to check Claude's output and keep the conversation going if a condition is unmet — for example, if tests are still failing.
|
||||
</Tip>
|
||||
|
||||
***
|
||||
|
||||
### `StopFailure`
|
||||
|
||||
Fires instead of `Stop` when the turn ends due to an API error.
|
||||
|
||||
**When it fires:** When a rate limit, authentication failure, or other API error ends the turn.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="error" type="'authentication_failed' | 'billing_error' | 'rate_limit' | 'invalid_request' | 'server_error' | 'unknown' | 'max_output_tokens'">
|
||||
The error category.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="error_details" type="string">
|
||||
Detailed error message.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="last_assistant_message" type="string">
|
||||
Last assistant message text, if any was produced before the error.
|
||||
</ResponseField>
|
||||
|
||||
**Behavior:** Fire-and-forget. Hook output and exit codes are ignored.
|
||||
|
||||
***
|
||||
|
||||
### `SubagentStart`
|
||||
|
||||
Fires when Claude spawns a subagent via the `Agent` tool.
|
||||
|
||||
**When it fires:** When an Agent tool call begins.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="agent_id" type="string">Unique ID for this subagent instance.</ResponseField>
|
||||
<ResponseField name="agent_type" type="string">Agent type name (e.g., `"general-purpose"`).</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | ---------------------------------------- |
|
||||
| `0` | Stdout shown to the subagent as context. |
|
||||
| Other | Stderr shown to user only. |
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="additionalContext" type="string">
|
||||
Context injected into the subagent's conversation at the start.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### `SubagentStop`
|
||||
|
||||
Fires just before a subagent concludes its response. Mirrors `Stop` but for subagents.
|
||||
|
||||
**When it fires:** When a subagent is about to return its result to the parent.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="agent_id" type="string">Subagent instance ID.</ResponseField>
|
||||
<ResponseField name="agent_type" type="string">Agent type name.</ResponseField>
|
||||
<ResponseField name="agent_transcript_path" type="string">Path to the subagent's JSONL transcript.</ResponseField>
|
||||
<ResponseField name="stop_hook_active" type="boolean">Whether a SubagentStop hook is already running.</ResponseField>
|
||||
<ResponseField name="last_assistant_message" type="string">Last message from the subagent.</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | --------------------------------------------------------- |
|
||||
| `0` | Stdout/stderr not shown. |
|
||||
| `2` | Stderr shown to subagent; subagent **continues** running. |
|
||||
| Other | Stderr shown to user only; subagent stops. |
|
||||
|
||||
***
|
||||
|
||||
### `SessionStart`
|
||||
|
||||
Fires when a session begins. Use this to inject initial context or set up the environment.
|
||||
|
||||
**When it fires:** On session startup, resume, clear (`/clear`), or after compaction.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="source" type="'startup' | 'resume' | 'clear' | 'compact'">
|
||||
What triggered the session start.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="model" type="string">Active model for the session.</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | ------------------------------------------ |
|
||||
| `0` | Stdout shown to Claude as initial context. |
|
||||
| Other | Stderr shown to user only. |
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="additionalContext" type="string">
|
||||
Context injected into Claude's system prompt for this session.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="initialUserMessage" type="string">
|
||||
Auto-submitted as the first user message of the session.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="watchPaths" type="string[]">
|
||||
Absolute file paths to register with the `FileChanged` watcher.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### `SessionEnd`
|
||||
|
||||
Fires when a session is about to end.
|
||||
|
||||
**When it fires:** On clear, logout, prompt-input exit, or other termination reasons.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="reason" type="'clear' | 'resume' | 'logout' | 'prompt_input_exit' | 'other' | 'bypass_permissions_disabled'">
|
||||
The reason the session is ending.
|
||||
</ResponseField>
|
||||
|
||||
**Exit codes:** Exit code 0 completes successfully. Other exit codes show stderr to the user.
|
||||
|
||||
***
|
||||
|
||||
### `Setup`
|
||||
|
||||
Fires during repository initialization and maintenance checks.
|
||||
|
||||
**When it fires:** On `init` (first time Claude Code runs in a directory) or `maintenance` (periodic checks).
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="trigger" type="'init' | 'maintenance'">
|
||||
What triggered the setup hook.
|
||||
</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | ------------------------------------------------------- |
|
||||
| `0` | Stdout shown to Claude. |
|
||||
| Other | Stderr shown to user only. Blocking errors are ignored. |
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="additionalContext" type="string">
|
||||
Context provided to Claude for the setup phase.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### `PreCompact`
|
||||
|
||||
Fires before context compaction begins.
|
||||
|
||||
**When it fires:** Before the compaction summary is generated, whether triggered manually (`/compact`) or automatically.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="trigger" type="'manual' | 'auto'">Whether compaction was requested by the user or triggered automatically.</ResponseField>
|
||||
<ResponseField name="custom_instructions" type="string | null">Any custom compaction instructions already configured.</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | -------------------------------------------------- |
|
||||
| `0` | Stdout appended as custom compaction instructions. |
|
||||
| `2` | Compaction is **blocked**. |
|
||||
| Other | Stderr shown to user; compaction continues. |
|
||||
|
||||
***
|
||||
|
||||
### `PostCompact`
|
||||
|
||||
Fires after compaction completes.
|
||||
|
||||
**When it fires:** After the compaction summary has been generated and applied.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="trigger" type="'manual' | 'auto'">How compaction was triggered.</ResponseField>
|
||||
<ResponseField name="compact_summary" type="string">The summary produced by compaction.</ResponseField>
|
||||
|
||||
**Exit codes:** Exit code 0 shows stdout to the user. Other exit codes show stderr to the user.
|
||||
|
||||
***
|
||||
|
||||
### `UserPromptSubmit`
|
||||
|
||||
Fires when the user submits a prompt, before Claude processes it.
|
||||
|
||||
**When it fires:** Each time you press Enter with a message in the terminal.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="prompt" type="string">The raw prompt text the user submitted.</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | --------------------------------------------------------------------- |
|
||||
| `0` | Stdout shown to Claude as additional context. |
|
||||
| `2` | Processing **blocked**; original prompt erased; stderr shown to user. |
|
||||
| Other | Stderr shown to user only. |
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="additionalContext" type="string">
|
||||
Context appended to Claude's view of the user message.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### `Notification`
|
||||
|
||||
Fires when Claude Code sends a notification (e.g., permission prompts, idle alerts).
|
||||
|
||||
**When it fires:** When a notification event is raised internally.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="message" type="string">Notification message text.</ResponseField>
|
||||
<ResponseField name="title" type="string">Notification title.</ResponseField>
|
||||
|
||||
<ResponseField name="notification_type" type="'permission_prompt' | 'idle_prompt' | 'auth_success' | 'elicitation_dialog' | 'elicitation_complete' | 'elicitation_response'">
|
||||
The type of notification.
|
||||
</ResponseField>
|
||||
|
||||
**Exit codes:** Exit code 0 produces no output. Other exit codes show stderr to the user.
|
||||
|
||||
***
|
||||
|
||||
### `Elicitation`
|
||||
|
||||
Fires when an MCP server requests user input. Hooks can auto-respond without showing the dialog.
|
||||
|
||||
**When it fires:** When an MCP server sends an elicitation request (a structured input form or URL).
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="mcp_server_name" type="string">Name of the MCP server requesting input.</ResponseField>
|
||||
<ResponseField name="message" type="string">The prompt message from the server.</ResponseField>
|
||||
<ResponseField name="mode" type="'form' | 'url'">Input mode.</ResponseField>
|
||||
<ResponseField name="elicitation_id" type="string">Request identifier.</ResponseField>
|
||||
<ResponseField name="requested_schema" type="Record<string, unknown>">JSON schema describing the expected input structure.</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | ----------------------------------------------------------------------------- |
|
||||
| `0` | Use hook response if `hookSpecificOutput` is provided; otherwise show dialog. |
|
||||
| `2` | Deny the elicitation. |
|
||||
| Other | Stderr shown to user only. |
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="action" type="'accept' | 'decline' | 'cancel'">
|
||||
The programmatic response to the elicitation.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="content" type="Record<string, unknown>">
|
||||
Form data to submit when `action` is `"accept"`.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### `ElicitationResult`
|
||||
|
||||
Fires after a user responds to an MCP elicitation. Hooks can observe or override the response.
|
||||
|
||||
**When it fires:** After the user (or an Elicitation hook) responds to the elicitation.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="mcp_server_name" type="string">Name of the MCP server.</ResponseField>
|
||||
<ResponseField name="elicitation_id" type="string">Request identifier.</ResponseField>
|
||||
<ResponseField name="action" type="'accept' | 'decline' | 'cancel'">How the user responded.</ResponseField>
|
||||
<ResponseField name="content" type="Record<string, unknown>">Submitted form data, if accepted.</ResponseField>
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="action" type="'accept' | 'decline' | 'cancel'">
|
||||
Override the user's action before it is sent to the server.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="content" type="Record<string, unknown>">
|
||||
Override the submitted content.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
### `ConfigChange`
|
||||
|
||||
Fires when a settings file changes during a session.
|
||||
|
||||
**When it fires:** When `user_settings`, `project_settings`, `local_settings`, `policy_settings`, or `skills` files are modified on disk.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="source" type="'user_settings' | 'project_settings' | 'local_settings' | 'policy_settings' | 'skills'">
|
||||
Which settings source changed.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="file_path" type="string">Absolute path to the changed file.</ResponseField>
|
||||
|
||||
**Exit codes:**
|
||||
|
||||
| Exit code | Effect |
|
||||
| --------- | ------------------------------------------------------- |
|
||||
| `0` | Allow the change to be applied. |
|
||||
| `2` | **Block** the change from being applied to the session. |
|
||||
| Other | Stderr shown to user only. |
|
||||
|
||||
***
|
||||
|
||||
### `InstructionsLoaded`
|
||||
|
||||
Fires when a CLAUDE.md or instruction rule file is loaded. This event is observability-only.
|
||||
|
||||
**When it fires:** When any instruction file is loaded into context.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="file_path" type="string">Path to the loaded file.</ResponseField>
|
||||
<ResponseField name="memory_type" type="'User' | 'Project' | 'Local' | 'Managed'">The memory scope of the file.</ResponseField>
|
||||
<ResponseField name="load_reason" type="'session_start' | 'nested_traversal' | 'path_glob_match' | 'include' | 'compact'">Why the file was loaded.</ResponseField>
|
||||
<ResponseField name="globs" type="string[]">The `paths:` frontmatter patterns that matched (if `load_reason` is `path_glob_match`).</ResponseField>
|
||||
<ResponseField name="trigger_file_path" type="string">The file Claude accessed that caused this load (for `path_glob_match`).</ResponseField>
|
||||
<ResponseField name="parent_file_path" type="string">The file that `@include`d this one (for `include`).</ResponseField>
|
||||
|
||||
**Behavior:** Blocking not supported. Exit code 0 completes normally. Other exit codes show stderr to the user.
|
||||
|
||||
***
|
||||
|
||||
### `WorktreeCreate`
|
||||
|
||||
Fires when Claude Code needs to create an isolated worktree. The hook is responsible for actually creating the worktree and reporting its path.
|
||||
|
||||
**When it fires:** When worktree isolation is requested for a task.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="name" type="string">Suggested slug for the worktree directory.</ResponseField>
|
||||
|
||||
**Behavior:** Write the absolute path of the created worktree directory to stdout and exit with code 0. Any other exit code signals a failure.
|
||||
|
||||
***
|
||||
|
||||
### `WorktreeRemove`
|
||||
|
||||
Fires when Claude Code needs to remove a previously created worktree.
|
||||
|
||||
**When it fires:** When a worktree task completes and the worktree should be cleaned up.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="worktree_path" type="string">Absolute path of the worktree to remove.</ResponseField>
|
||||
|
||||
**Behavior:** Exit code 0 means success. Other exit codes show stderr to the user.
|
||||
|
||||
***
|
||||
|
||||
### `CwdChanged`
|
||||
|
||||
Fires after the working directory changes.
|
||||
|
||||
**When it fires:** When Claude changes directories during a session.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="old_cwd" type="string">Previous working directory.</ResponseField>
|
||||
<ResponseField name="new_cwd" type="string">New working directory.</ResponseField>
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="watchPaths" type="string[]">
|
||||
Absolute paths to add to the `FileChanged` watcher. Return this to start watching files in the new directory.
|
||||
</ResponseField>
|
||||
|
||||
The `CLAUDE_ENV_FILE` environment variable is set — write `export KEY=value` lines to apply environment variables to subsequent Bash tool commands.
|
||||
|
||||
***
|
||||
|
||||
### `FileChanged`
|
||||
|
||||
Fires when a watched file is modified, added, or removed.
|
||||
|
||||
**When it fires:** When a file registered via `SessionStart.watchPaths` or `CwdChanged.watchPaths` changes on disk.
|
||||
|
||||
**Input fields:**
|
||||
|
||||
<ResponseField name="file_path" type="string">Absolute path of the changed file.</ResponseField>
|
||||
<ResponseField name="event" type="'change' | 'add' | 'unlink'">The type of filesystem event.</ResponseField>
|
||||
|
||||
**`hookSpecificOutput` fields:**
|
||||
|
||||
<ResponseField name="watchPaths" type="string[]">
|
||||
Update the watch list with these absolute paths.
|
||||
</ResponseField>
|
||||
|
||||
The `CLAUDE_ENV_FILE` environment variable is set for this hook as well.
|
||||
|
||||
***
|
||||
|
||||
## Async hooks
|
||||
|
||||
For hooks that need to run in the background without delaying Claude, output an async acknowledgment on stdout instead of the normal sync output:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"async": true,
|
||||
"asyncTimeout": 30
|
||||
}
|
||||
```
|
||||
|
||||
<ResponseField name="async" type="literal: true" required>
|
||||
Signals that this hook is running asynchronously.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="asyncTimeout" type="number">
|
||||
How long (in seconds) the async hook is allowed to run before it is cancelled.
|
||||
</ResponseField>
|
||||
|
||||
<Warning>
|
||||
Async hooks cannot block tool execution or inject context. Use them for side effects like notifications, logging, or metrics that must not slow down the agentic loop.
|
||||
</Warning>
|
||||
|
||||
|
||||
Built with [Mintlify](https://mintlify.com).
|
||||
517
docs/claude-code-docs-main/en/reference/sdk/overview.md
Normal file
517
docs/claude-code-docs-main/en/reference/sdk/overview.md
Normal file
@@ -0,0 +1,517 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://vineetagarwal-code-claude-code.mintlify.app/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# SDK overview
|
||||
|
||||
> Embed Claude Code in your own tools using the stdin/stdout control protocol. Reference for the SDK session API, message types, and output formats.
|
||||
|
||||
The Claude Code SDK is a control protocol for embedding Claude Code in other applications — IDEs, automation scripts, CI/CD pipelines, or any host that can spawn a subprocess and communicate over stdin/stdout.
|
||||
|
||||
Rather than exposing a library API directly, the SDK communicates with a running `claude` process over a structured JSON message stream. The host process sends user messages and control requests; the CLI process streams back assistant messages, tool progress events, and result payloads.
|
||||
|
||||
<Note>
|
||||
The TypeScript types described on this page are exported from `@anthropic-ai/claude-code` under the `agentSdkTypes` entry point. Control protocol types (prefixed `SDKControl`) are `@alpha` and subject to change.
|
||||
</Note>
|
||||
|
||||
## How it works
|
||||
|
||||
<Steps>
|
||||
<Step title="Spawn a Claude Code process">
|
||||
Start `claude` with `--output-format stream-json` and `--print` (non-interactive mode). Pipe its stdin and stdout into your host process.
|
||||
|
||||
```bash theme={null}
|
||||
claude --output-format stream-json --print --verbose
|
||||
```
|
||||
|
||||
For a persistent session that accepts multiple prompts over time, omit `--print` and instead send `SDKUserMessage` objects to stdin after the session initializes.
|
||||
</Step>
|
||||
|
||||
<Step title="Send an initialize request">
|
||||
Write a `control_request` with `subtype: "initialize"` to stdin. The CLI responds with an `SDKControlInitializeResponse` containing available commands, models, agents, and account information.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "control_request",
|
||||
"request_id": "init-1",
|
||||
"request": {
|
||||
"subtype": "initialize",
|
||||
"systemPrompt": "You are a code reviewer.",
|
||||
"appendSystemPrompt": "Always suggest tests."
|
||||
}
|
||||
}
|
||||
```
|
||||
</Step>
|
||||
|
||||
<Step title="Stream messages from stdout">
|
||||
Read newline-delimited JSON from stdout. Each line is one of the `SDKMessage` union types — assistant turns, tool progress, system events, and result summaries.
|
||||
</Step>
|
||||
|
||||
<Step title="Send user messages">
|
||||
Write `SDKUserMessage` objects to stdin to continue the conversation. Each message contains an Anthropic API-compatible `message` payload.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
## Output formats
|
||||
|
||||
Pass `--output-format` to control what Claude Code writes to stdout.
|
||||
|
||||
| Format | Description |
|
||||
| ------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| `text` | Plain text responses only. Default for interactive mode. |
|
||||
| `json` | Single JSON object written at completion. Suitable for one-shot scripts. |
|
||||
| `stream-json` | Newline-delimited JSON stream. One message per line, emitted as events occur. Required for SDK use. |
|
||||
|
||||
<Tip>
|
||||
Use `stream-json` when you need to render progress incrementally or handle tool events. Use `json` when you only care about the final result.
|
||||
</Tip>
|
||||
|
||||
## Control protocol messages
|
||||
|
||||
The control protocol uses two top-level envelope types that flow bidirectionally over stdin/stdout.
|
||||
|
||||
### `SDKControlRequest`
|
||||
|
||||
Sent **to** the CLI process to configure the session or issue commands.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "control_request",
|
||||
"request_id": "<unique-string>",
|
||||
"request": { "subtype": "...", ...payload }
|
||||
}
|
||||
```
|
||||
|
||||
<ResponseField name="type" type="literal: 'control_request'" required>
|
||||
Always `"control_request"`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="request_id" type="string" required>
|
||||
Unique identifier for this request. The CLI echoes it back in the corresponding `control_response`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="request" type="SDKControlRequestInner" required>
|
||||
The request payload. `subtype` identifies which operation to perform.
|
||||
</ResponseField>
|
||||
|
||||
### `SDKControlResponse`
|
||||
|
||||
Emitted **from** the CLI process in response to a `control_request`.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "control_response",
|
||||
"response": {
|
||||
"subtype": "success",
|
||||
"request_id": "<echoed-id>",
|
||||
"response": { ...payload }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
On error, `subtype` is `"error"` and the `error` field contains a human-readable message.
|
||||
|
||||
***
|
||||
|
||||
## Initialize request and response
|
||||
|
||||
The `initialize` request is the first control message you must send. It configures the session and returns available capabilities.
|
||||
|
||||
### `SDKControlInitializeRequest`
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "control_request",
|
||||
"request_id": "init-1",
|
||||
"request": {
|
||||
"subtype": "initialize",
|
||||
"systemPrompt": "You are a CI automation agent.",
|
||||
"appendSystemPrompt": "Always add test coverage.",
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hookCallbackIds": ["my-hook-id"]
|
||||
}
|
||||
]
|
||||
},
|
||||
"agents": {
|
||||
"CodeReviewer": {
|
||||
"description": "Reviews code for quality and security.",
|
||||
"prompt": "You are an expert code reviewer...",
|
||||
"model": "opus"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<ResponseField name="subtype" type="literal: 'initialize'" required>
|
||||
Identifies this as an initialize request.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="systemPrompt" type="string">
|
||||
Replaces the default system prompt for this session.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="appendSystemPrompt" type="string">
|
||||
Appended to the system prompt without replacing it. Use this to add context while keeping the default behavior.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="hooks" type="Record<HookEvent, SDKHookCallbackMatcher[]>">
|
||||
Registers SDK-side hook callbacks. The CLI calls back into the SDK process when hook events fire. See [Hooks reference](/reference/sdk/hooks-reference).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="sdkMcpServers" type="string[]">
|
||||
Names of in-process SDK MCP servers (created with `createSdkMcpServer`) to connect to this session.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="agents" type="Record<string, AgentDefinition>">
|
||||
Custom subagent definitions available to the `Agent` tool during this session.
|
||||
|
||||
<Expandable title="AgentDefinition fields">
|
||||
<ResponseField name="description" type="string" required>
|
||||
Natural language description of when Claude should invoke this agent.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="prompt" type="string" required>
|
||||
System prompt for this agent.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="model" type="string">
|
||||
Model alias (`"sonnet"`, `"opus"`, `"haiku"`) or full model ID. Defaults to inheriting the parent model.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="tools" type="string[]">
|
||||
Allow-list of tool names. When omitted, the agent inherits all tools.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="disallowedTools" type="string[]">
|
||||
Tools explicitly blocked for this agent.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="maxTurns" type="number">
|
||||
Maximum agentic turns before the agent stops.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="permissionMode" type="PermissionMode">
|
||||
Override permission mode for this agent. See [Permissions API](/reference/sdk/permissions-api).
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
### `SDKControlInitializeResponse`
|
||||
|
||||
The CLI responds with the session's current capabilities.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "control_response",
|
||||
"response": {
|
||||
"subtype": "success",
|
||||
"request_id": "init-1",
|
||||
"response": {
|
||||
"commands": [...],
|
||||
"agents": [...],
|
||||
"output_style": "stream-json",
|
||||
"available_output_styles": ["text", "json", "stream-json"],
|
||||
"models": [...],
|
||||
"account": {
|
||||
"email": "user@example.com",
|
||||
"organization": "Acme Corp",
|
||||
"apiProvider": "firstParty"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<ResponseField name="commands" type="SlashCommand[]">
|
||||
Available slash commands (e.g., `/compact`, `/cost`). Each entry has `name`, `description`, and `argumentHint`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="agents" type="AgentInfo[]">
|
||||
Available subagent types. Each has `name`, `description`, and an optional `model`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="output_style" type="string">
|
||||
The active output format (`"stream-json"`, `"json"`, `"text"`).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="models" type="ModelInfo[]">
|
||||
Available models for this account.
|
||||
|
||||
<Expandable title="ModelInfo fields">
|
||||
<ResponseField name="value" type="string">
|
||||
Model identifier for API calls (e.g., `"claude-sonnet-4-6"`).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="displayName" type="string">
|
||||
Human-readable name (e.g., `"Claude Sonnet 4.6"`).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="supportsEffort" type="boolean">
|
||||
Whether this model supports effort levels.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="supportsAdaptiveThinking" type="boolean">
|
||||
Whether this model supports adaptive thinking (Claude decides when and how much to think).
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="account" type="AccountInfo">
|
||||
Logged-in account details.
|
||||
|
||||
<Expandable title="AccountInfo fields">
|
||||
<ResponseField name="email" type="string">
|
||||
Account email address.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="organization" type="string">
|
||||
Organization name.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="subscriptionType" type="string">
|
||||
Subscription tier.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="apiProvider" type="'firstParty' | 'bedrock' | 'vertex' | 'foundry'">
|
||||
Active API backend. Anthropic OAuth only applies when `"firstParty"`.
|
||||
</ResponseField>
|
||||
</Expandable>
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
## User messages
|
||||
|
||||
Send user messages to stdin to drive the conversation forward.
|
||||
|
||||
### `SDKUserMessage`
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "user",
|
||||
"message": {
|
||||
"role": "user",
|
||||
"content": "Refactor this function to use async/await."
|
||||
},
|
||||
"parent_tool_use_id": null
|
||||
}
|
||||
```
|
||||
|
||||
<ResponseField name="type" type="literal: 'user'" required>
|
||||
Always `"user"`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="message" type="APIUserMessage" required>
|
||||
An Anthropic API-compatible user message. `content` can be a string or a content block array (for images and other media).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="parent_tool_use_id" type="string | null" required>
|
||||
Tool use ID this message is responding to, or `null` for top-level user messages.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="uuid" type="string">
|
||||
Optional UUID to track this message. Echoed back in related events.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="priority" type="'now' | 'next' | 'later'">
|
||||
Scheduling hint for async message queuing.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
## SDK message stream types
|
||||
|
||||
Claude Code emits a stream of JSON messages to stdout. The `type` field identifies each message.
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="system — session initialization">
|
||||
Emitted once at session start with `subtype: "init"`. Contains the active model, tool list, MCP server statuses, permission mode, and session ID.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "system",
|
||||
"subtype": "init",
|
||||
"model": "claude-sonnet-4-6",
|
||||
"tools": ["Bash", "Read", "Write", "Edit", "Glob", "Grep"],
|
||||
"mcp_servers": [],
|
||||
"permissionMode": "default",
|
||||
"session_id": "abc123",
|
||||
"uuid": "..."
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="assistant — model response">
|
||||
Emitted when the model produces a turn. Contains the full Anthropic API response object, including any `tool_use` blocks.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "assistant",
|
||||
"message": { "role": "assistant", "content": [...] },
|
||||
"parent_tool_use_id": null,
|
||||
"uuid": "...",
|
||||
"session_id": "abc123"
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="stream_event — partial streaming tokens">
|
||||
Emitted during streaming with `RawMessageStreamEvent` payloads. Use these to render incremental output.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="tool_progress — long-running tool status">
|
||||
Emitted periodically for tools that take more than a few seconds (e.g., Bash commands). Contains `tool_name`, `tool_use_id`, and elapsed time.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="result — final turn summary">
|
||||
Emitted at the end of each turn. `subtype` is `"success"` or one of the error subtypes.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "result",
|
||||
"subtype": "success",
|
||||
"result": "The function has been refactored.",
|
||||
"duration_ms": 4200,
|
||||
"total_cost_usd": 0.0042,
|
||||
"num_turns": 3,
|
||||
"is_error": false,
|
||||
"stop_reason": "end_turn",
|
||||
"session_id": "abc123",
|
||||
"uuid": "..."
|
||||
}
|
||||
```
|
||||
|
||||
Error subtypes: `"error_during_execution"`, `"error_max_turns"`, `"error_max_budget_usd"`, `"error_max_structured_output_retries"`.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="system — status updates">
|
||||
Emitted with `subtype: "status"` when the permission mode or session status changes (e.g., `"compacting"`).
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
***
|
||||
|
||||
## Other control requests
|
||||
|
||||
Beyond `initialize`, the control protocol exposes these operations.
|
||||
|
||||
| `subtype` | Direction | Description |
|
||||
| --------------------- | ---------- | --------------------------------------------------------------------- |
|
||||
| `interrupt` | host → CLI | Interrupt the current turn. |
|
||||
| `set_permission_mode` | host → CLI | Change the active permission mode. |
|
||||
| `set_model` | host → CLI | Switch to a different model mid-session. |
|
||||
| `can_use_tool` | CLI → host | Permission request for a tool call (requires SDK permission handler). |
|
||||
| `mcp_status` | host → CLI | Get MCP server connection statuses. |
|
||||
| `mcp_set_servers` | host → CLI | Replace dynamically managed MCP servers. |
|
||||
| `get_context_usage` | host → CLI | Get context window usage breakdown. |
|
||||
| `get_settings` | host → CLI | Read the effective merged settings. |
|
||||
| `apply_flag_settings` | host → CLI | Merge settings into the flag settings layer. |
|
||||
| `rewind_files` | host → CLI | Revert file changes made since a given message. |
|
||||
| `hook_callback` | CLI → host | Deliver a hook event for an SDK-registered hook callback. |
|
||||
| `reload_plugins` | host → CLI | Reload plugins from disk. |
|
||||
|
||||
***
|
||||
|
||||
## Session management API
|
||||
|
||||
For scripting scenarios, the SDK exports functions that operate on saved session transcripts stored in `~/.claude/`.
|
||||
|
||||
```typescript theme={null}
|
||||
import {
|
||||
query,
|
||||
listSessions,
|
||||
getSessionInfo,
|
||||
getSessionMessages,
|
||||
forkSession,
|
||||
renameSession,
|
||||
tagSession,
|
||||
} from '@anthropic-ai/claude-code'
|
||||
```
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="query — run a prompt">
|
||||
The primary SDK entry point. Accepts a `prompt` string or `AsyncIterable<SDKUserMessage>` and returns an async iterable of `SDKMessage`.
|
||||
|
||||
```typescript theme={null}
|
||||
for await (const message of query({
|
||||
prompt: 'What files are in this directory?',
|
||||
options: { cwd: '/my/project' }
|
||||
})) {
|
||||
if (message.type === 'result') {
|
||||
console.log(message.result)
|
||||
}
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="listSessions — list saved sessions">
|
||||
Returns session metadata for a project directory. Pass `dir` to scope to a specific project, or omit to list all sessions.
|
||||
|
||||
```typescript theme={null}
|
||||
const sessions = await listSessions({ dir: '/my/project', limit: 50 })
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="getSessionMessages — read a transcript">
|
||||
Parses the JSONL transcript file for a session and returns messages in chronological order.
|
||||
|
||||
```typescript theme={null}
|
||||
const messages = await getSessionMessages(sessionId, {
|
||||
dir: '/my/project',
|
||||
includeSystemMessages: false,
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="forkSession — branch a conversation">
|
||||
Copies a session's transcript into a new session with remapped UUIDs. Supports `upToMessageId` to fork from a specific point.
|
||||
|
||||
```typescript theme={null}
|
||||
const { sessionId: newId } = await forkSession(originalSessionId, {
|
||||
upToMessageId: 'msg-uuid',
|
||||
title: 'Experimental branch',
|
||||
})
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="renameSession and tagSession">
|
||||
```typescript theme={null}
|
||||
await renameSession(sessionId, 'My refactor session')
|
||||
await tagSession(sessionId, 'needs-review')
|
||||
await tagSession(sessionId, null) // clear tag
|
||||
```
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
***
|
||||
|
||||
## Use cases
|
||||
|
||||
<Tabs>
|
||||
<Tab title="IDE integration">
|
||||
IDEs can spawn a persistent Claude Code process and route messages through the control protocol. Send the `initialize` request with a custom `systemPrompt` that describes the IDE context, then forward user messages from the editor's chat panel. Use `PreToolUse` hook callbacks to intercept file edits and display diffs in the IDE's native UI before they are applied.
|
||||
</Tab>
|
||||
|
||||
<Tab title="CI/CD automation">
|
||||
In CI pipelines, use `--output-format json` and `--print` for one-shot tasks:
|
||||
|
||||
```bash theme={null}
|
||||
result=$(echo "Review the diff and output pass/fail" | \
|
||||
claude --output-format json --print \
|
||||
--permission-mode bypassPermissions)
|
||||
```
|
||||
|
||||
Parse the `result` field from the JSON output to extract the agent's response programmatically.
|
||||
</Tab>
|
||||
|
||||
<Tab title="Headless agents">
|
||||
For long-running background agents, use `query()` from the TypeScript SDK with a streaming output format. Combine with `watchScheduledTasks` (internal) to fire tasks on cron schedules while keeping a persistent daemon process that maintains the WebSocket connection to claude.ai.
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
|
||||
Built with [Mintlify](https://mintlify.com).
|
||||
473
docs/claude-code-docs-main/en/reference/sdk/permissions-api.md
Normal file
473
docs/claude-code-docs-main/en/reference/sdk/permissions-api.md
Normal file
@@ -0,0 +1,473 @@
|
||||
> ## Documentation Index
|
||||
> Fetch the complete documentation index at: https://vineetagarwal-code-claude-code.mintlify.app/llms.txt
|
||||
> Use this file to discover all available pages before exploring further.
|
||||
|
||||
# Permissions API
|
||||
|
||||
> Reference for permission modes, allow/deny rule syntax, and configuration methods for controlling which tools Claude Code can use without prompting.
|
||||
|
||||
The permissions system controls whether Claude Code runs a tool immediately, prompts you for confirmation, or blocks the call entirely. You configure it through permission modes and rule lists that can be set globally, per project, or per session.
|
||||
|
||||
## Permission modes
|
||||
|
||||
A permission mode sets the baseline behavior for all tool calls. Individual allow/deny rules can override this baseline for specific tools or commands.
|
||||
|
||||
| Mode | Description |
|
||||
| ------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `default` | Prompt for approval on potentially dangerous operations. Safe read-only tools run without prompting. |
|
||||
| `acceptEdits` | Auto-approve all file edit operations (`Write`, `Edit`, `MultiEdit`). Bash commands still prompt. |
|
||||
| `bypassPermissions` | Skip all permission checks. All tools run without prompting. Requires `allowDangerouslySkipPermissions: true` in settings. |
|
||||
| `plan` | Read-only planning mode. No tool execution; Claude can only read files and explain what it would do. |
|
||||
| `dontAsk` | Do not prompt the user. Deny any tool call that is not pre-approved by an explicit allow rule. |
|
||||
|
||||
<Warning>
|
||||
`bypassPermissions` mode disables all safeguards. Only use it in sandboxed environments or CI pipelines where you fully control the input. The mode requires `allowDangerouslySkipPermissions: true` in your settings file.
|
||||
</Warning>
|
||||
|
||||
### Setting the permission mode
|
||||
|
||||
<Tabs>
|
||||
<Tab title="CLI flag">
|
||||
Pass `--permission-mode` to set the mode for a single invocation:
|
||||
|
||||
```bash theme={null}
|
||||
claude --permission-mode acceptEdits
|
||||
claude --permission-mode bypassPermissions --dangerously-skip-permissions
|
||||
claude --permission-mode plan
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="Settings file">
|
||||
Set `defaultPermissionMode` in any Claude Code settings file to make it the default for all sessions in that scope:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"defaultPermissionMode": "acceptEdits"
|
||||
}
|
||||
```
|
||||
|
||||
Settings files load in this priority order (highest wins):
|
||||
|
||||
* `.claude/settings.local.json` — local overrides, not committed
|
||||
* `.claude/settings.json` — project-level defaults
|
||||
* `~/.claude/settings.json` — user-level defaults
|
||||
</Tab>
|
||||
|
||||
<Tab title="/permissions command">
|
||||
Run `/permissions` inside a session to open the interactive permissions panel where you can view and edit allow/deny rules. Session-level changes are not persisted to disk.
|
||||
|
||||
```
|
||||
/permissions
|
||||
```
|
||||
</Tab>
|
||||
|
||||
<Tab title="SDK control request">
|
||||
Change the permission mode programmatically via the control protocol:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "control_request",
|
||||
"request_id": "pm-1",
|
||||
"request": {
|
||||
"subtype": "set_permission_mode",
|
||||
"mode": "acceptEdits"
|
||||
}
|
||||
}
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
***
|
||||
|
||||
## Permission rules
|
||||
|
||||
Rules let you pre-approve or block specific tools and commands without changing the global permission mode. Rules are additive across settings scopes — allow rules from all files merge together.
|
||||
|
||||
### Configuration format
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(git *)",
|
||||
"Bash(npm run *)",
|
||||
"Read",
|
||||
"Write(src/**)",
|
||||
"mcp__myserver"
|
||||
],
|
||||
"deny": [
|
||||
"Bash(rm -rf *)",
|
||||
"Bash(curl * | bash)",
|
||||
"Write(/etc/**)"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<ResponseField name="allow" type="string[]">
|
||||
Rules that auto-approve matching tool calls without prompting.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="deny" type="string[]">
|
||||
Rules that unconditionally block matching tool calls.
|
||||
</ResponseField>
|
||||
|
||||
<Note>
|
||||
Deny rules always take precedence over allow rules. If both an allow rule and a deny rule match a tool call, the call is blocked.
|
||||
</Note>
|
||||
|
||||
### Rule syntax
|
||||
|
||||
A rule is a string that matches a tool name, optionally with a parenthesized content pattern.
|
||||
|
||||
**Tool name only** — matches every call to that tool:
|
||||
|
||||
```
|
||||
Read
|
||||
Write
|
||||
Edit
|
||||
Bash
|
||||
```
|
||||
|
||||
**Tool name with content pattern** — matches calls where the tool's primary input matches the glob:
|
||||
|
||||
```
|
||||
Bash(git *)
|
||||
Bash(npm run *)
|
||||
Write(src/*)
|
||||
Edit(*.ts)
|
||||
```
|
||||
|
||||
For `Bash`, the pattern is matched against the full command string. For file tools (`Write`, `Edit`, `Read`, `Glob`), the pattern is matched against the file path argument.
|
||||
|
||||
**MCP server** — matches all tools from a specific MCP server:
|
||||
|
||||
```
|
||||
mcp__myserver
|
||||
```
|
||||
|
||||
**MCP server wildcard** — same as above, explicit wildcard form:
|
||||
|
||||
```
|
||||
mcp__myserver__*
|
||||
```
|
||||
|
||||
**Specific MCP tool** — matches one tool from a server:
|
||||
|
||||
```
|
||||
mcp__myserver__query_database
|
||||
```
|
||||
|
||||
**Agent type** — blocks or allows a specific subagent:
|
||||
|
||||
```
|
||||
Agent(Explore)
|
||||
Agent(CodeReviewer)
|
||||
```
|
||||
|
||||
### Pattern matching for `Bash`
|
||||
|
||||
Bash rule patterns use shell-style glob matching on the full command string.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(git status)",
|
||||
"Bash(git log *)",
|
||||
"Bash(git diff *)",
|
||||
"Bash(npm run test*)",
|
||||
"Bash(make *)"
|
||||
],
|
||||
"deny": [
|
||||
"Bash(rm *)",
|
||||
"Bash(sudo *)",
|
||||
"Bash(* | bash)",
|
||||
"Bash(* | sh)"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<Warning>
|
||||
Bash patterns match prefix-first. A rule like `Bash(git *)` matches `git status`, `git log --oneline`, and `git push --force`. Be specific when writing deny rules.
|
||||
</Warning>
|
||||
|
||||
### Pattern matching for file tools
|
||||
|
||||
File path patterns are matched against the absolute path of the file being read, written, or edited.
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Write(src/**)",
|
||||
"Write(tests/**)",
|
||||
"Edit(*.md)",
|
||||
"Read"
|
||||
],
|
||||
"deny": [
|
||||
"Write(/etc/**)",
|
||||
"Write(~/.ssh/**)",
|
||||
"Edit(.env*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Permission rule sources and priority
|
||||
|
||||
Rules are collected from multiple sources and evaluated in a defined order. When the same tool call matches rules from different sources, deny takes precedence over allow, and the most restrictive result wins.
|
||||
|
||||
| Source | Where configured | Editable |
|
||||
| ----------------- | -------------------------------------------- | -------------- |
|
||||
| `policySettings` | Managed policy layer | No |
|
||||
| `flagSettings` | CLI flags and SDK control requests | Per-session |
|
||||
| `userSettings` | `~/.claude/settings.json` | Yes |
|
||||
| `projectSettings` | `.claude/settings.json` | Yes |
|
||||
| `localSettings` | `.claude/settings.local.json` | Yes |
|
||||
| `cliArg` | `--allowedTools` / `--disallowedTools` flags | Per-invocation |
|
||||
| `session` | `/permissions` command, SDK updates | Per-session |
|
||||
|
||||
### `--allowedTools` and `--disallowedTools` CLI flags
|
||||
|
||||
Pass comma-separated rule strings directly on the command line:
|
||||
|
||||
```bash theme={null}
|
||||
claude --allowedTools "Bash(git *),Read,Write" --print "Run the tests"
|
||||
claude --disallowedTools "Bash,Write" --print "Summarize this project"
|
||||
```
|
||||
|
||||
These map to the `cliArg` source and apply for the duration of the invocation.
|
||||
|
||||
***
|
||||
|
||||
## Permission decisions
|
||||
|
||||
The permission engine evaluates each tool call through a pipeline and returns one of three outcomes.
|
||||
|
||||
| Decision | Meaning |
|
||||
| -------- | ------------------------------------------------------ |
|
||||
| `allow` | Tool runs immediately. |
|
||||
| `ask` | User is prompted for confirmation. |
|
||||
| `deny` | Tool call is blocked; Claude receives an error result. |
|
||||
|
||||
### Decision pipeline
|
||||
|
||||
Claude Code evaluates tool calls in this order:
|
||||
|
||||
1. **Deny rules** — if any deny rule matches, the call is blocked immediately.
|
||||
2. **Ask rules** — if any ask rule matches, the permission dialog is shown.
|
||||
3. **Tool's own permission check** — the tool's `checkPermissions` method runs (e.g., Bash checks individual subcommands).
|
||||
4. **Safety checks** — paths inside `.git/`, `.claude/`, `.vscode/`, and shell config files always prompt, even in `bypassPermissions` mode.
|
||||
5. **Mode check** — `bypassPermissions` and plan mode apply here.
|
||||
6. **Allow rules** — if an allow rule matches, the call is approved.
|
||||
7. **Default behavior** — if no rule matched, prompt the user.
|
||||
|
||||
<Note>
|
||||
Safety checks (step 4) are bypass-immune. Even with `bypassPermissions` mode, Claude Code will prompt before modifying files in `.git/` or shell configuration files like `~/.bashrc`.
|
||||
</Note>
|
||||
|
||||
***
|
||||
|
||||
## Working directories
|
||||
|
||||
By default, Claude Code restricts file operations to the current working directory and its subdirectories. You can grant access to additional directories.
|
||||
|
||||
### Via CLI flag
|
||||
|
||||
```bash theme={null}
|
||||
claude --add-dir /path/to/extra/dir
|
||||
```
|
||||
|
||||
### Via settings
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"permissions": {
|
||||
"additionalDirectories": [
|
||||
"/shared/data",
|
||||
"/home/user/configs"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Via SDK control request
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "control_request",
|
||||
"request_id": "dirs-1",
|
||||
"request": {
|
||||
"subtype": "apply_flag_settings",
|
||||
"settings": {
|
||||
"permissions": {
|
||||
"additionalDirectories": ["/shared/data"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## Permission updates via the SDK
|
||||
|
||||
SDK hosts (IDEs, desktop apps) can respond to `can_use_tool` control requests and include permission updates to persist rule changes alongside their decisions.
|
||||
|
||||
### `PermissionUpdate` object
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "addRules",
|
||||
"rules": [
|
||||
{ "toolName": "Bash", "ruleContent": "git *" }
|
||||
],
|
||||
"behavior": "allow",
|
||||
"destination": "userSettings"
|
||||
}
|
||||
```
|
||||
|
||||
<ResponseField name="type" type="'addRules' | 'replaceRules' | 'removeRules' | 'setMode' | 'addDirectories' | 'removeDirectories'" required>
|
||||
The update operation.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="rules" type="PermissionRuleValue[]">
|
||||
Rules to add, replace, or remove. Each rule has `toolName` and an optional `ruleContent` (the parenthesized pattern).
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="behavior" type="'allow' | 'deny' | 'ask'" required>
|
||||
Which rule list to modify.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="destination" type="'userSettings' | 'projectSettings' | 'localSettings' | 'session' | 'cliArg'" required>
|
||||
Where to persist the update. `session` applies only to the current session; `userSettings`, `projectSettings`, and `localSettings` write to the corresponding settings files on disk.
|
||||
</ResponseField>
|
||||
|
||||
### Permission decision response
|
||||
|
||||
When responding to a `can_use_tool` request, include `updatedPermissions` to persist rule changes:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"type": "control_response",
|
||||
"response": {
|
||||
"subtype": "success",
|
||||
"request_id": "<request_id>",
|
||||
"response": {
|
||||
"behavior": "allow",
|
||||
"updatedPermissions": [
|
||||
{
|
||||
"type": "addRules",
|
||||
"rules": [{ "toolName": "Bash", "ruleContent": "git *" }],
|
||||
"behavior": "allow",
|
||||
"destination": "userSettings"
|
||||
}
|
||||
],
|
||||
"decisionClassification": "user_permanent"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<ResponseField name="behavior" type="'allow' | 'deny'" required>
|
||||
The permission decision.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="updatedInput" type="Record<string, unknown>">
|
||||
Modified tool input to use instead of the original. Only valid when `behavior` is `"allow"`.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="updatedPermissions" type="PermissionUpdate[]">
|
||||
Permission rule updates to apply and persist alongside this decision.
|
||||
</ResponseField>
|
||||
|
||||
<ResponseField name="decisionClassification" type="'user_temporary' | 'user_permanent' | 'user_reject'">
|
||||
How the user responded, for telemetry. `user_temporary` for allow-once; `user_permanent` for always-allow; `user_reject` for deny.
|
||||
</ResponseField>
|
||||
|
||||
***
|
||||
|
||||
## Hooks and permissions
|
||||
|
||||
`PreToolUse` and `PermissionRequest` hooks can inject permission decisions programmatically. See [Hooks reference](/reference/sdk/hooks-reference) for details on `permissionDecision` output and `hookSpecificOutput.decision`.
|
||||
|
||||
The hook-based permission flow is especially useful for headless agents that cannot show interactive prompts. When `shouldAvoidPermissionPrompts` is true (background agent mode), Claude Code runs `PermissionRequest` hooks before falling back to auto-deny.
|
||||
|
||||
***
|
||||
|
||||
## Safety recommendations
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="CI/CD pipelines">
|
||||
Use `bypassPermissions` only in isolated, short-lived environments where you control all inputs. Set explicit deny rules for destructive operations as a defense-in-depth measure:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"defaultPermissionMode": "bypassPermissions",
|
||||
"allowDangerouslySkipPermissions": true,
|
||||
"permissions": {
|
||||
"deny": [
|
||||
"Bash(rm -rf *)",
|
||||
"Bash(sudo *)",
|
||||
"Bash(curl * | bash)"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="IDE and interactive use">
|
||||
Use `default` mode with allow rules for common safe operations. This minimizes interruptions while keeping you in control of destructive actions:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"defaultPermissionMode": "default",
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Read",
|
||||
"Glob",
|
||||
"Grep",
|
||||
"Bash(git status)",
|
||||
"Bash(git log *)",
|
||||
"Bash(git diff *)",
|
||||
"Bash(npm run *)",
|
||||
"Bash(make *)"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Code review and read-only analysis">
|
||||
Use `plan` mode when you want Claude to reason about code without making any changes. Claude can read files and explain what it would do, but cannot write, edit, or run commands:
|
||||
|
||||
```bash theme={null}
|
||||
claude --permission-mode plan "Explain the architecture of this codebase"
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Automated agents with human approval">
|
||||
Use `dontAsk` mode combined with an SDK `PermissionRequest` hook to replace the interactive dialog with your own approval UI. The hook receives every tool call that would have prompted and can allow, deny, or forward it to a human reviewer:
|
||||
|
||||
```json theme={null}
|
||||
{
|
||||
"defaultPermissionMode": "dontAsk",
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Read",
|
||||
"Bash(git *)"
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Any tool call not matching an allow rule is sent to your `PermissionRequest` hook handler instead of being auto-denied.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
|
||||
Built with [Mintlify](https://mintlify.com).
|
||||
Reference in New Issue
Block a user