Run Claude Code programmatically changedheadless
Nearest release: v2.1.310, published 4 hours after upstream edited the page. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Upstream edited this page at 23 Oct 2026 16:44 UTC, give or take a minute or two: the time comes from Anthropic’s own sitemap rather than from a commit. This site recorded the change at 23 Oct 2026 19:07 UTC.
Upstream edited
Recorded here
Lines+67added
Lines−67removed
From line
2
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits45to this page, all time
The whole hunk
from line 2, old and new numbered
/
from line 2
22
33> Use the Agent SDK to run Claude Code programmatically from the CLI, Python, or TypeScript.
44
5The [Agent SDK](/docs/en/agent-sdk/overview.md) gives you the same tools, agent loop, and context management that power Claude Code. It's available as a CLI for scripts and CI/CD, or as [Python](/docs/en/agent-sdk/python.md) and [TypeScript](/docs/en/agent-sdk/typescript.md) packages for full programmatic control.
5The [Agent SDK](https://code.claude.com/docs/en/agent-sdk/overview.md) gives you the same tools, agent loop, and context management that power Claude Code. It's available as a CLI for scripts and CI/CD, or as [Python](https://code.claude.com/docs/en/agent-sdk/python.md) and [TypeScript](https://code.claude.com/docs/en/agent-sdk/typescript.md) packages for full programmatic control.
66
7To run Claude Code in non-interactive mode, pass `-p` with your prompt and the [CLI options](/docs/en/cli-reference.md) you need:
7To run Claude Code in non-interactive mode, pass `-p` with your prompt and the [CLI options](https://code.claude.com/docs/en/cli-reference.md) you need:
88
99```bash theme={null}
1010claude -p "Find and fix the bug in auth.py" --allowedTools "Read,Edit,Bash"
1111```
1212
13This page covers using the Agent SDK via the CLI (`claude -p`). For the Python and TypeScript SDK packages with structured outputs, tool approval callbacks, and native message objects, see the [full Agent SDK documentation](/docs/en/agent-sdk/overview.md).
13This page covers using the Agent SDK via the CLI (`claude -p`). For the Python and TypeScript SDK packages with structured outputs, tool approval callbacks, and native message objects, see the [full Agent SDK documentation](https://code.claude.com/docs/en/agent-sdk/overview.md).
1414
1515## Basic usage
1616
17Add the `-p` (or `--print`) flag to any `claude` command to run it non-interactively. Not every [CLI option](/docs/en/cli-reference.md) combines with `-p`. Claude Code rejects `--bg`, and rejects `--cloud` with a task description, with an error naming the conflict; `--cloud` with a session ID and `-p` instead [queues a message into that cloud session](/docs/en/claude-code-on-the-web.md#send-follow-ups-from-the-cli) and exits. Options you'll combine with `-p` often include:
17Add the `-p` (or `--print`) flag to any `claude` command to run it non-interactively. Not every [CLI option](https://code.claude.com/docs/en/cli-reference.md) combines with `-p`. Claude Code rejects `--bg`, and rejects `--cloud` with a task description, with an error naming the conflict; `--cloud` with a session ID and `-p` instead [queues a message into that cloud session](https://code.claude.com/docs/en/claude-code-on-the-web.md#send-follow-ups-from-the-cli) and exits. Options you'll combine with `-p` often include:
1818
1919* `--continue` for [continuing conversations](#continue-conversations)
2020* `--allowedTools` for [auto-approving tools](#auto-approve-tools)
from line 30
3030
3131### Start faster with bare mode
3232
33Add `--bare` to reduce startup time by skipping auto-discovery of hooks, skills, custom commands, [subagents](/docs/en/sub-agents.md), installed plugins, MCP servers, auto memory, and CLAUDE.md. Without it, `claude -p` discovers and loads them as an interactive session would, including anything configured in the working directory or `~/.claude`.
33Add `--bare` to reduce startup time by skipping auto-discovery of hooks, skills, custom commands, [subagents](https://code.claude.com/docs/en/sub-agents.md), installed plugins, MCP servers, auto memory, and CLAUDE.md. Without it, `claude -p` discovers and loads them as an interactive session would, including anything configured in the working directory or `~/.claude`.
3434
35Bare mode is useful for CI and scripts where you need the same result on every machine. A hook in a teammate's `~/.claude` or an MCP server in the project's `.mcp.json` won't run, because bare mode never reads them. A directory you name with `--add-dir` is a partial exception: bare mode loads skills from its `.claude/skills/` folder, but still skips its `.claude/commands/` and `.claude/agents/` folders. [Skills from additional directories](/docs/en/skills.md#skills-from-additional-directories) covers what does and doesn't load.
35Bare mode is useful for CI and scripts where you need the same result on every machine. A hook in a teammate's `~/.claude` or an MCP server in the project's `.mcp.json` won't run, because bare mode never reads them. A directory you name with `--add-dir` is a partial exception: bare mode loads skills from its `.claude/skills/` folder, but still skips its `.claude/commands/` and `.claude/agents/` folders. [Skills from additional directories](https://code.claude.com/docs/en/skills.md#skills-from-additional-directories) covers what does and doesn't load.
3636
37Without `--bare`, a `-p` session runs the hooks in a project's `.claude/settings.json` and connects the servers in its `.mcp.json`, even in a folder you've never trusted. A `-p` session shows no workspace trust dialog and no per-server approval prompt. [What runs before you trust a folder](/docs/en/permissions.md#what-runs-before-you-trust-a-folder) covers each kind of repository content under `-p` and how to keep it out.
37Without `--bare`, a `-p` session runs the hooks in a project's `.claude/settings.json` and connects the servers in its `.mcp.json`, even in a folder you've never trusted. A `-p` session shows no workspace trust dialog and no per-server approval prompt. [What runs before you trust a folder](https://code.claude.com/docs/en/permissions.md#what-runs-before-you-trust-a-folder) covers each kind of repository content under `-p` and how to keep it out.
3838
3939This example runs a one-off summarize task in bare mode and pre-approves the Read tool so the call completes without a permission prompt. Set `ANTHROPIC_API_KEY` before running it, because bare mode doesn't use your subscription login:
4040
from line 51
5151| System prompt additions | `--append-system-prompt`, `--append-system-prompt-file` |
5252| Settings | `--settings <file-or-json>` |
5353| MCP servers | `--mcp-config <file-or-json>` |
54| [Custom agents](/docs/en/sub-agents.md#choose-the-subagent-scope) | `--agents <file-or-json>` |
54| [Custom agents](https://code.claude.com/docs/en/sub-agents.md#choose-the-subagent-scope) | `--agents <file-or-json>` |
5555| A plugin | `--plugin-dir <path>`, `--plugin-url <url>` |
5656
5757Bare mode also limits what happens while the session runs:
5858
5959* **MCP servers**: only servers supplied on the command line connect, for example with `--mcp-config`. In an interactive session, Claude Code also skips the automatic IDE connection unless you pass `--ide`.
60* **System reminders**: Claude gets your prompts and the tool results without the [system reminders](/docs/en/glossary.md#system-reminder) Claude Code would add alongside them. For example, Claude isn't told when a file it read earlier changes on disk, and it doesn't get the list of available skills, including skills from an `--add-dir` folder.
61* **Background tasks**: Claude can't run background commands or background subagents, and the other features that [`CLAUDE_CODE_DISABLE_BACKGROUND_TASKS`](/docs/en/env-vars) turns off are off too. A command that reaches its [timeout](/docs/en/tools-reference.md#timeout-and-output-limits) stops instead of [moving to the background](/docs/en/tools-reference.md#background-commands).
60* **System reminders**: Claude gets your prompts and the tool results without the [system reminders](https://code.claude.com/docs/en/glossary.md#system-reminder) Claude Code would add alongside them. For example, Claude isn't told when a file it read earlier changes on disk, and it doesn't get the list of available skills, including skills from an `--add-dir` folder.
61* **Background tasks**: Claude can't run background commands or background subagents, and the other features that [`CLAUDE_CODE_DISABLE_BACKGROUND_TASKS`](https://code.claude.com/docs/en/env-vars) turns off are off too. A command that reaches its [timeout](https://code.claude.com/docs/en/tools-reference.md#timeout-and-output-limits) stops instead of [moving to the background](https://code.claude.com/docs/en/tools-reference.md#background-commands).
6262
6363Before v2.1.286, these limits held only partly: an interactive `--bare` session connected the MCP servers that a normal session would, every `--bare` session sent system reminders, and background tasks stayed available.
6464
from line 70
7070
7171After Claude finishes its turn and stdin has closed, a `claude -p` run can stay open to wait for background work that Claude started.
7272
73Unless a background command that the main conversation started is still running, Claude Code stops whatever is still running after 10 minutes of continuous idle waiting by default and drops its partial result. To change the 10-minute cap, set [`CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS`](/docs/en/env-vars), or set it to `0` to wait without one.
73Unless a background command that the main conversation started is still running, Claude Code stops whatever is still running after 10 minutes of continuous idle waiting by default and drops its partial result. To change the 10-minute cap, set [`CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS`](https://code.claude.com/docs/en/env-vars), or set it to `0` to wait without one.
7474
7575The run waits for background work such as background commands, subagents and workflows, Monitor watches, and pending `/loop` wakeups:
7676
77* **[Background commands](/docs/en/tools-reference.md#background-commands)**: for a command that the main conversation started, for example a dev server or a watch build, the run waits until the command exits or reaches its [time limit](/docs/en/tools-reference.md#time-limit-for-background-commands). Claude then takes one more turn with the outcome. While the command runs, the 10-minute cap doesn't end the wait.
78* **Background [subagents](/docs/en/sub-agents.md) and workflows**: the run stays open until that work completes, because its result is part of the final output.
79* **[Monitor](/docs/en/tools-reference.md#monitor-tool) watches**: the run waits until the watch times out or the 10-minute cap ends the wait, whichever comes first. While it waits, Claude keeps responding to what the watch reports. By default, a watch times out five minutes after Claude starts it.
80* **Pending wakeups**: in a run whose prompt you passed as text rather than with `--input-format stream-json`, when Claude has scheduled a [self-paced `/loop` wakeup](/docs/en/scheduled-tasks#let-claude-choose-the-interval), the run waits for each wakeup to fire and runs its iteration until the [loop ends](/docs/en/scheduled-tasks.md#stop-a-loop), even past the 10-minute cap.
77* **[Background commands](https://code.claude.com/docs/en/tools-reference.md#background-commands)**: for a command that the main conversation started, for example a dev server or a watch build, the run waits until the command exits or reaches its [time limit](https://code.claude.com/docs/en/tools-reference.md#time-limit-for-background-commands). Claude then takes one more turn with the outcome. While the command runs, the 10-minute cap doesn't end the wait.
78* **Background [subagents](https://code.claude.com/docs/en/sub-agents.md) and workflows**: the run stays open until that work completes, because its result is part of the final output.
79* **[Monitor](https://code.claude.com/docs/en/tools-reference.md#monitor-tool) watches**: the run waits until the watch times out or the 10-minute cap ends the wait, whichever comes first. While it waits, Claude keeps responding to what the watch reports. By default, a watch times out five minutes after Claude starts it.
80* **Pending wakeups**: in a run whose prompt you passed as text rather than with `--input-format stream-json`, when Claude has scheduled a [self-paced `/loop` wakeup](https://code.claude.com/docs/en/scheduled-tasks#let-claude-choose-the-interval), the run waits for each wakeup to fire and runs its iteration until the [loop ends](https://code.claude.com/docs/en/scheduled-tasks.md#stop-a-loop), even past the 10-minute cap.
8181
8282When stderr is a terminal and the run has waited five seconds, Claude Code prints a line to stderr that starts with `Waiting for background work to finish` and names the work. With [`json` or `stream-json` output](#get-structured-output), the line prints only when stdout isn't a terminal, so the JSON your script reads never carries it.
8383
84If the run reaches its [`--max-budget-usd`](/docs/en/cli-reference#cli-flags) cap, Claude Code stops the remaining background work instead of waiting.
84If the run reaches its [`--max-budget-usd`](https://code.claude.com/docs/en/cli-reference#cli-flags) cap, Claude Code stops the remaining background work instead of waiting.
8585
8686When background work starts another turn, the run prints each turn's result with the default `text` output and the last turn's result with `json` output. Before v2.1.295, the run printed only the last turn's result with `text` output too.
8787
from line 89
8989
9090A `claude -p` run doesn't wait for MCP work in the background:
9191
92* **[MCP tasks](/docs/en/mcp.md#mcp-tasks-that-run-on-the-server)**: on a remote server the job goes on. To follow it again, [resume that session](/docs/en/mcp.md#exit-clear-or-resume-while-an-mcp-task-runs), not as a one-shot `claude -p "<prompt>"` run.
93* **MCP calls that [automatic backgrounding](/docs/en/mcp.md#automatic-backgrounding-of-long-tool-calls) moved**: the call's result is lost.
92* **[MCP tasks](https://code.claude.com/docs/en/mcp.md#mcp-tasks-that-run-on-the-server)**: on a remote server the job goes on. To follow it again, [resume that session](https://code.claude.com/docs/en/mcp.md#exit-clear-or-resume-while-an-mcp-task-runs), not as a one-shot `claude -p "<prompt>"` run.
93* **MCP calls that [automatic backgrounding](https://code.claude.com/docs/en/mcp.md#automatic-backgrounding-of-long-tool-calls) moved**: the call's result is lost.
9494
9595### Stop a run with SIGTERM
9696
9797If you stop a `claude -p` run with SIGTERM, for example with `kill` or from a process supervisor, Claude Code exits with code 143. Claude Code leaves the turn that was in progress unfinished and records no result for it. To end the turn instead, send SIGINT, or call the Agent SDK's `interrupt()`, before you stop the process.
9898
99On SIGTERM, Claude Code terminates the process tree of any Bash command that is still running. Claude Code then runs [`SessionEnd` hooks](/docs/en/hooks#sessionend) and exits. While exiting, Claude Code starts no new tool call, sends no new model request, and runs no hook other than `SessionEnd`. If the run was in the middle of a command or waiting on a permission prompt when the signal arrived, Claude Code handles that step as follows:
99On SIGTERM, Claude Code terminates the process tree of any Bash command that is still running. Claude Code then runs [`SessionEnd` hooks](https://code.claude.com/docs/en/hooks#sessionend) and exits. While exiting, Claude Code starts no new tool call, sends no new model request, and runs no hook other than `SessionEnd`. If the run was in the middle of a command or waiting on a permission prompt when the signal arrived, Claude Code handles that step as follows:
100100
101101* **Running a command**: Claude Code records the command as killed in the session.
102102* **Waiting for an answer to a permission prompt**: if you send SIGTERM to the process, Claude Code leaves the prompt unanswered. If your program closes the session through the Agent SDK, the SDK ends Claude Code's input before sending any signal, and Claude Code cancels the prompt as soon as the input ends.
103103
104When you [resume the session](#continue-conversations), Claude Code leaves the interrupted turn as it is, and your next prompt drives the conversation. To have Claude Code continue the interrupted turn on resume instead, set [`CLAUDE_CODE_RESUME_INTERRUPTED_TURN=1`](/docs/en/env-vars).
104When you [resume the session](#continue-conversations), Claude Code leaves the interrupted turn as it is, and your next prompt drives the conversation. To have Claude Code continue the interrupted turn on resume instead, set [`CLAUDE_CODE_RESUME_INTERRUPTED_TURN=1`](https://code.claude.com/docs/en/env-vars).
105105
106106### If the working directory is deleted
107107
108If the working directory of a `claude -p` or Agent SDK session is deleted mid-session, the session keeps running. When a turn starts while the directory is missing, Claude Code emits a [warning message](/docs/en/agent-sdk/typescript.md#sdkinformationalmessage) in `stream-json` output, and shell commands fail until the directory exists again.
108If the working directory of a `claude -p` or Agent SDK session is deleted mid-session, the session keeps running. When a turn starts while the directory is missing, Claude Code emits a [warning message](https://code.claude.com/docs/en/agent-sdk/typescript.md#sdkinformationalmessage) in `stream-json` output, and shell commands fail until the directory exists again.
109109
110110## Examples
111111
from line 121
121121cat build-error.txt | claude -p 'concisely explain the root cause of this build error' > output.txt
122122```
123123
124With `--output-format json`, the response payload includes `total_cost_usd` and a per-model cost breakdown, so scripted callers can track spend without consulting the [usage dashboard](/docs/en/costs.md). When you continue an earlier conversation with `--continue` or `--resume`, the run reports the conversation's whole total, [earlier runs' spend included](/docs/en/agent-sdk/cost-tracking.md#accumulate-costs-across-multiple-calls). Both figures are [client-side estimates](/docs/en/agent-sdk/cost-tracking.md) and can differ from your actual bill.
124With `--output-format json`, the response payload includes `total_cost_usd` and a per-model cost breakdown, so scripted callers can track spend without consulting the [usage dashboard](https://code.claude.com/docs/en/costs.md). When you continue an earlier conversation with `--continue` or `--resume`, the run reports the conversation's whole total, [earlier runs' spend included](https://code.claude.com/docs/en/agent-sdk/cost-tracking.md#accumulate-costs-across-multiple-calls). Both figures are [client-side estimates](https://code.claude.com/docs/en/agent-sdk/cost-tracking.md) and can differ from your actual bill.
125125
126126> [!NOTE]
127127>
from line 207
207207 jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'
208208```
209209
210For programmatic streaming with callbacks and message objects, see [Stream responses in real-time](/docs/en/agent-sdk/streaming-output.md) in the Agent SDK documentation.
210For programmatic streaming with callbacks and message objects, see [Stream responses in real-time](https://code.claude.com/docs/en/agent-sdk/streaming-output.md) in the Agent SDK documentation.
211211
212212#### Follow subagent messages
213213
214Messages from [subagents](/docs/en/sub-agents.md) and from skills that [run in a subagent](/docs/en/skills.md#run-skills-in-a-subagent) appear in the stream as `assistant` and `user` messages. Their `parent_tool_use_id` field says which run each one belongs to. Messages from the main conversation carry `null` in that field.
214Messages from [subagents](https://code.claude.com/docs/en/sub-agents.md) and from skills that [run in a subagent](https://code.claude.com/docs/en/skills.md#run-skills-in-a-subagent) appear in the stream as `assistant` and `user` messages. Their `parent_tool_use_id` field says which run each one belongs to. Messages from the main conversation carry `null` in that field.
215215
216The first message from a forked skill, or from a subagent running in the [foreground](/docs/en/sub-agents.md#run-subagents-in-foreground-or-background), is a `user` message carrying the prompt or skill content that drives it. After that first message, Claude Code emits:
216The first message from a forked skill, or from a subagent running in the [foreground](https://code.claude.com/docs/en/sub-agents.md#run-subagents-in-foreground-or-background), is a `user` message carrying the prompt or skill content that drives it. After that first message, Claude Code emits:
217217
218218* **By default**: the run's `tool_use` and `tool_result` blocks.
219* **With [`--forward-subagent-text`](/docs/en/cli-reference#cli-flags) or [`CLAUDE_CODE_FORWARD_SUBAGENT_TEXT`](/docs/en/env-vars)**: the run's text and thinking blocks too, so you can reconstruct each run's transcript.
219* **With [`--forward-subagent-text`](https://code.claude.com/docs/en/cli-reference#cli-flags) or [`CLAUDE_CODE_FORWARD_SUBAGENT_TEXT`](https://code.claude.com/docs/en/env-vars)**: the run's text and thinking blocks too, so you can reconstruct each run's transcript.
220220
221When you enable either option, Claude Code forwards messages from [subagents at every nesting depth](/docs/en/sub-agents.md#let-subagents-spawn-their-own-subagents), whether each one was spawned with the Agent tool or started as a forked skill. In `parent_tool_use_id`, the nested subagent's messages carry the ID of the Agent or Skill tool call that started it, so you can rebuild the full nesting tree by following those IDs.
221When you enable either option, Claude Code forwards messages from [subagents at every nesting depth](https://code.claude.com/docs/en/sub-agents.md#let-subagents-spawn-their-own-subagents), whether each one was spawned with the Agent tool or started as a forked skill. In `parent_tool_use_id`, the nested subagent's messages carry the ID of the Agent or Skill tool call that started it, so you can rebuild the full nesting tree by following those IDs.
222222
223223A run that Claude starts with a tool call carries that tool call's ID. A forked skill that you start by passing `/<skill-name>` as the prompt has no tool call, so its messages carry a `forked-command-` value instead and arrive after it finishes. Find how the run started in the first column:
224224
from line 239
239239
240240#### Handle API retries
241241
242When 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.
242When 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`](https://code.claude.com/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.
243243
244244| Field | Type | Description |
245245| - | - | - |
from line 249
249249| `max_retries` | integer | total retries permitted for this failure's cause |
250250| `retry_delay_ms` | integer | milliseconds until the next attempt |
251251| `error_status` | integer or null | HTTP status code of the failed attempt, or `null` when the attempt got no HTTP response from the API |
252| `no_response` | object, optional | present only when the failed attempt got [no response headers in time](/docs/en/errors.md#no-response-from-api). `waited_ms` is how long that attempt waited and `retry_wait_ms` is how long the retry will wait. Requires Claude Code v2.1.261 or later |
252| `no_response` | object, optional | present only when the failed attempt got [no response headers in time](https://code.claude.com/docs/en/errors.md#no-response-from-api). `waited_ms` is how long that attempt waited and `retry_wait_ms` is how long the retry will wait. Requires Claude Code v2.1.261 or later |
253253| `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` |
254254| `uuid` | string | unique event identifier |
255255| `session_id` | string | session the event belongs to |
from line 258
258258
259259The `system/init` event reports session metadata including the model, tools, MCP servers, and loaded plugins. It is the first event in the stream unless startup events precede it:
260260
261* `plugin_install` events, when [`CLAUDE_CODE_SYNC_PLUGIN_INSTALL`](/docs/en/env-vars) is set.
262* [`hook_started`, `hook_progress`, and `hook_response` events](/docs/en/agent-sdk/typescript#sdkhookstartedmessage), while a configured [`SessionStart`](/docs/en/hooks#sessionstart) or [`Setup`](/docs/en/hooks#setup) hook runs. These stream as the hook produces them.
261* `plugin_install` events, when [`CLAUDE_CODE_SYNC_PLUGIN_INSTALL`](https://code.claude.com/docs/en/env-vars) is set.
262* [`hook_started`, `hook_progress`, and `hook_response` events](https://code.claude.com/docs/en/agent-sdk/typescript#sdkhookstartedmessage), while a configured [`SessionStart`](https://code.claude.com/docs/en/hooks#sessionstart) or [`Setup`](https://code.claude.com/docs/en/hooks#setup) hook runs. These stream as the hook produces them.
263263
264The event also carries an optional `capabilities` array of strings naming the protocol behaviors this Claude Code version implements, such as `interrupt_receipt_v1` or `interrupt_cancel_queued_v1`. Check it to feature-detect instead of comparing version strings, and ignore values you don't recognize. See [`SDKSystemMessage`](/docs/en/agent-sdk/typescript#sdksystemmessage) for the capability list.
264The event also carries an optional `capabilities` array of strings naming the protocol behaviors this Claude Code version implements, such as `interrupt_receipt_v1` or `interrupt_cancel_queued_v1`. Check it to feature-detect instead of comparing version strings, and ignore values you don't recognize. See [`SDKSystemMessage`](https://code.claude.com/docs/en/agent-sdk/typescript#sdksystemmessage) for the capability list.
265265
266266#### Fail CI when a plugin or MCP server doesn't load
267267
from line 274
274274
275275When 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.
276276
277Use the MCP server fields the same way. When you pass [`--mcp-config`](/docs/en/cli-reference#cli-flags) with `-p`, Claude Code waits for still-pending servers before running the first turn, up to the [`MCP_TIMEOUT`](/docs/en/env-vars) startup timeout, 30 seconds by default. A remote server with a [cached tool list](/docs/en/agent-sdk/mcp.md#connection-timing) skips the wait, shows `pending` in `system/init`, and connects on its first tool call. In a [self-hosted environment](/docs/en/self-hosted-environments-configuration.md#connection-timing), a shorter wait applies instead. The wait requires Claude Code v2.1.221 or later.
277Use the MCP server fields the same way. When you pass [`--mcp-config`](https://code.claude.com/docs/en/cli-reference#cli-flags) with `-p`, Claude Code waits for still-pending servers before running the first turn, up to the [`MCP_TIMEOUT`](https://code.claude.com/docs/en/env-vars) startup timeout, 30 seconds by default. A remote server with a [cached tool list](https://code.claude.com/docs/en/agent-sdk/mcp.md#connection-timing) skips the wait, shows `pending` in `system/init`, and connects on its first tool call. In a [self-hosted environment](https://code.claude.com/docs/en/self-hosted-environments-configuration.md#connection-timing), a shorter wait applies instead. The wait requires Claude Code v2.1.221 or later.
278278
279279Claude 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:
280280
from line 287
287287
288288#### Track plugin installs
289289
290When [`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.
290When [`CLAUDE_CODE_SYNC_PLUGIN_INSTALL`](https://code.claude.com/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.
291291
292292| Field | Type | Description |
293293| - | - | - |
from line 301
301301
302302### Auto-approve tools
303303
304Use `--allowedTools` to let Claude use certain tools without prompting. Listing `Read` and `Edit` lets Claude read and edit files without asking for permission, apart from reads from [network paths](/docs/en/permissions.md#network-paths). Listing `Bash` does the same for shell commands, except in a run that starts in [auto mode](/docs/en/permission-modes.md#how-auto-mode-evaluates-actions), where Claude Code drops a bare `Bash` entry as a broad allow rule and auto mode evaluates each command instead. This example runs a test suite and fixes failures with those three tools listed:
304Use `--allowedTools` to let Claude use certain tools without prompting. Listing `Read` and `Edit` lets Claude read and edit files without asking for permission, apart from reads from [network paths](https://code.claude.com/docs/en/permissions.md#network-paths). Listing `Bash` does the same for shell commands, except in a run that starts in [auto mode](https://code.claude.com/docs/en/permission-modes.md#how-auto-mode-evaluates-actions), where Claude Code drops a bare `Bash` entry as a broad allow rule and auto mode evaluates each command instead. This example runs a test suite and fixes failures with those three tools listed:
305305
306306```bash theme={null}
307307claude -p "Run the test suite and fix any failures" \
from line 308
308308 --allowedTools "Bash,Read,Edit"
309309```
310310
311Calls to tools you didn't list run if they need no approval. In a [Manual mode](/docs/en/permission-modes.md#available-modes) `claude -p` run, a call that needs approval is denied unless something approves it, such as a [`PermissionRequest` hook](/docs/en/hooks#permissionrequest) or a [`--permission-prompt-tool`](/docs/en/cli-reference#cli-flags). With Claude Code v2.1.302 or later, `claude -p` runs start in Manual mode when [nothing sets a permission mode](/docs/en/permission-modes.md#which-mode-a-non-interactive-run-starts-in).
311Calls to tools you didn't list run if they need no approval. In a [Manual mode](https://code.claude.com/docs/en/permission-modes.md#available-modes) `claude -p` run, a call that needs approval is denied unless something approves it, such as a [`PermissionRequest` hook](https://code.claude.com/docs/en/hooks#permissionrequest) or a [`--permission-prompt-tool`](https://code.claude.com/docs/en/cli-reference#cli-flags). With Claude Code v2.1.302 or later, `claude -p` runs start in Manual mode when [nothing sets a permission mode](https://code.claude.com/docs/en/permission-modes.md#which-mode-a-non-interactive-run-starts-in).
312312
313To set a baseline for the whole session instead of listing individual tools, pass a [permission mode](/docs/en/permission-modes.md) with `--permission-mode`, such as `auto`, `dontAsk`, or `acceptEdits`:
313To set a baseline for the whole session instead of listing individual tools, pass a [permission mode](https://code.claude.com/docs/en/permission-modes.md) with `--permission-mode`, such as `auto`, `dontAsk`, or `acceptEdits`:
314314
315315* **`auto`**: pass `--permission-mode auto` to have a classifier review most actions instead of you
316* **`dontAsk`**: Claude Code denies every call that would otherwise prompt, which is useful for locked-down CI runs, though a [mod](/docs/en/plugins/mods/overview.md) you installed can still approve some of those calls. To check which calls a mod can approve, see [Extend permissions with hooks](/docs/en/permissions.md#precedence-among-rules-hooks-and-mods).
316* **`dontAsk`**: Claude Code denies every call that would otherwise prompt, which is useful for locked-down CI runs, though a [mod](https://code.claude.com/docs/en/plugins/mods/overview.md) you installed can still approve some of those calls. To check which calls a mod can approve, see [Extend permissions with hooks](https://code.claude.com/docs/en/permissions.md#precedence-among-rules-hooks-and-mods).
317317
318 Actions that need no approval in Manual mode still run, such as file reads in your working directories and the [read-only command set](/docs/en/permissions.md#read-only-commands). Actions covered by your `--allowedTools` entries or `permissions.allow` rules also run. `AskUserQuestion`, connector tools [your organization set to `ask`](/docs/en/mcp#organization-controls-on-connector-tools), MCP tools marked [`requiresUserInteraction`](/docs/en/mcp#require-approval-for-a-specific-tool), and [reads from network paths](/docs/en/permissions.md#network-paths) are denied even when an allow rule matches
319* **`acceptEdits`**: Claude writes files without prompting, and Claude Code auto-approves common filesystem commands such as `mkdir`, `touch`, `mv`, and `cp`. The [actions no mode auto-approves](/docs/en/permission-modes.md#actions-no-mode-auto-approves) still apply. Apart from the read-only command set, other shell commands and network requests still need an `--allowedTools` entry or a `permissions.allow` rule. See [what `acceptEdits` auto-approves](/docs/en/permission-modes#auto-approve-file-edits-with-acceptedits-mode) for the full list
318 Actions that need no approval in Manual mode still run, such as file reads in your working directories and the [read-only command set](https://code.claude.com/docs/en/permissions.md#read-only-commands). Actions covered by your `--allowedTools` entries or `permissions.allow` rules also run. `AskUserQuestion`, connector tools [your organization set to `ask`](https://code.claude.com/docs/en/mcp#organization-controls-on-connector-tools), MCP tools marked [`requiresUserInteraction`](https://code.claude.com/docs/en/mcp#require-approval-for-a-specific-tool), and [reads from network paths](https://code.claude.com/docs/en/permissions.md#network-paths) are denied even when an allow rule matches
319* **`acceptEdits`**: Claude writes files without prompting, and Claude Code auto-approves common filesystem commands such as `mkdir`, `touch`, `mv`, and `cp`. The [actions no mode auto-approves](https://code.claude.com/docs/en/permission-modes.md#actions-no-mode-auto-approves) still apply. Apart from the read-only command set, other shell commands and network requests still need an `--allowedTools` entry or a `permissions.allow` rule. See [what `acceptEdits` auto-approves](https://code.claude.com/docs/en/permission-modes#auto-approve-file-edits-with-acceptedits-mode) for the full list
320320
321321This example applies lint fixes with `acceptEdits` as the baseline:
322322
from line 326
326326
327327### Turn off permission prompts in unattended runs
328328
329Pass `--permission-prompts none` when nobody is available to answer permission prompts, for example in a scheduled job. The flag matters most when your run has a permission host: an Agent SDK app with a [`canUseTool` callback](/docs/en/agent-sdk/user-input), or an MCP tool you pass with [`--permission-prompt-tool`](/docs/en/cli-reference#cli-flags). Without the flag, your run waits for that host to answer each permission request.
329Pass `--permission-prompts none` when nobody is available to answer permission prompts, for example in a scheduled job. The flag matters most when your run has a permission host: an Agent SDK app with a [`canUseTool` callback](https://code.claude.com/docs/en/agent-sdk/user-input), or an MCP tool you pass with [`--permission-prompt-tool`](https://code.claude.com/docs/en/cli-reference#cli-flags). Without the flag, your run waits for that host to answer each permission request.
330330
331With the flag, your run doesn't consult the host or wait on it. Anything that would prompt is denied unless a `PermissionRequest` hook allows it, Claude is told that nobody can approve the request and not to retry it, and the run continues. In a `-p` run with no host, these requests are denied either way, and the flag also tells Claude not to retry them. Permission rules, [`PermissionRequest` hooks](/docs/en/hooks#permissionrequest), and the permission mode you set still decide every call first; Claude Code denies only the requests that nothing else resolves.
331With the flag, your run doesn't consult the host or wait on it. Anything that would prompt is denied unless a `PermissionRequest` hook allows it, Claude is told that nobody can approve the request and not to retry it, and the run continues. In a `-p` run with no host, these requests are denied either way, and the flag also tells Claude not to retry them. Permission rules, [`PermissionRequest` hooks](https://code.claude.com/docs/en/hooks#permissionrequest), and the permission mode you set still decide every call first; Claude Code denies only the requests that nothing else resolves.
332332
333This example runs an unattended task in [auto mode](/docs/en/permission-modes.md#eliminate-prompts-with-auto-mode). The classifier reviews each action as usual, and Claude Code denies anything that would have fallen back to a prompt:
333This example runs an unattended task in [auto mode](https://code.claude.com/docs/en/permission-modes.md#eliminate-prompts-with-auto-mode). The classifier reviews each action as usual, and Claude Code denies anything that would have fallen back to a prompt:
334334
335335```bash theme={null}
336336claude -p "Update the dependency pins and run the tests" --permission-mode auto --permission-prompts none
337337```
338338
339With `--permission-prompts none`, Claude Code removes the tools that need an answer from a person, such as [`AskUserQuestion`](/docs/en/tools-reference#askuserquestion-tool-behavior), so Claude can't call them. Any [MCP elicitation request](/docs/en/mcp.md#respond-to-mcp-elicitation-requests) that no [`Elicitation` hook](/docs/en/hooks#elicitation) answers is cancelled.
339With `--permission-prompts none`, Claude Code removes the tools that need an answer from a person, such as [`AskUserQuestion`](https://code.claude.com/docs/en/tools-reference#askuserquestion-tool-behavior), so Claude can't call them. Any [MCP elicitation request](https://code.claude.com/docs/en/mcp.md#respond-to-mcp-elicitation-requests) that no [`Elicitation` hook](https://code.claude.com/docs/en/hooks#elicitation) answers is cancelled.
340340
341341With `--output-format stream-json`, denials appear as `permission_denied` system messages, and the final result message lists them in `permission_denials`.
342342
from line 353
353353 --allowedTools "Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"
354354```
355355
356The `--allowedTools` flag uses [permission rule syntax](/docs/en/settings-reference.md#permission-rule-syntax). The trailing ` *` enables prefix matching, so `Bash(git diff *)` allows any command starting with `git diff`. The space before `*` is important: without it, `Bash(git diff*)` would also match `git diff-index`.
356The `--allowedTools` flag uses [permission rule syntax](https://code.claude.com/docs/en/settings-reference.md#permission-rule-syntax). The trailing ` *` enables prefix matching, so `Bash(git diff *)` allows any command starting with `git diff`. The space before `*` is important: without it, `Bash(git diff*)` would also match `git diff-index`.
357357
358358> [!NOTE]
359359>
360360> Command support differs in `-p` mode:
361361>
362> * User-invoked [skills](/docs/en/skills.md) and custom commands work. Include `/skill-name` in the prompt string and Claude Code expands it before running.
362> * User-invoked [skills](https://code.claude.com/docs/en/skills.md) and custom commands work. Include `/skill-name` in the prompt string and Claude Code expands it before running.
363363> * Built-in commands that only run in the terminal interface, such as `/login`, aren't available.
364> * `/model`, `/effort`, `/fast`, `/color`, and `/rename` accept the value as an argument, for example `/model sonnet`, and `/mcp` with no argument prints a text summary of server status. These forms follow each command's [availability notes](/docs/en/commands.md#all-commands).
364> * `/model`, `/effort`, `/fast`, `/color`, and `/rename` accept the value as an argument, for example `/model sonnet`, and `/mcp` with no argument prints a text summary of server status. These forms follow each command's [availability notes](https://code.claude.com/docs/en/commands.md#all-commands).
365365> * To change a setting, pass `key=value` to `/config`, for example `/config thinking=false`.
366> * `/output-style <style>` switches [output styles](/docs/en/output-styles.md) and `/output-style` alone lists them. Requires Claude Code v2.1.269 or later.
366> * `/output-style <style>` switches [output styles](https://code.claude.com/docs/en/output-styles.md) and `/output-style` alone lists them. Requires Claude Code v2.1.269 or later.
367367
368368### Customize the system prompt
369369
from line 377
377377
378378In the script, `"$1"` stands for the first argument you pass on the command line. Run `bash review.sh 123` and the shell replaces `"$1"` with `123`, so the script fetches the diff for PR 123. Claude Code prints the review as JSON, with the text in the `result` field.
379379
380See [system prompt flags](/docs/en/cli-reference.md#system-prompt-flags) for more options including `--system-prompt` to fully replace the default prompt. If you replace it, the run also starts without the [git status snapshot](/docs/en/settings-reference.md#includegitinstructions).
380See [system prompt flags](https://code.claude.com/docs/en/cli-reference.md#system-prompt-flags) for more options including `--system-prompt` to fully replace the default prompt. If you replace it, the run also starts without the [git status snapshot](https://code.claude.com/docs/en/settings-reference.md#includegitinstructions).
381381
382382### Continue conversations
383383
384Use `--continue` to continue the most recent conversation, or `--resume` with a session ID to continue a specific conversation. On Claude Code v2.1.257 or later, when you pass `--continue`, Claude Code opens a [background session](/docs/en/sessions.md#where-the-session-picker-looks) that has finished, but not one that is still running. This example runs a review, then sends follow-up prompts:
384Use `--continue` to continue the most recent conversation, or `--resume` with a session ID to continue a specific conversation. On Claude Code v2.1.257 or later, when you pass `--continue`, Claude Code opens a [background session](https://code.claude.com/docs/en/sessions.md#where-the-session-picker-looks) that has finished, but not one that is still running. This example runs a review, then sends follow-up prompts:
385385
386386```bash theme={null}
387387# First request
from line 399
399399claude -p "Continue that review" --resume "$session_id"
400400```
401401
402You can run the two commands from different directories: Claude Code [finds the session by its ID](/docs/en/sessions.md#where-the-session-picker-looks) in any project on this machine.
402You can run the two commands from different directories: Claude Code [finds the session by its ID](https://code.claude.com/docs/en/sessions.md#where-the-session-picker-looks) in any project on this machine.
403403
404In place of the session ID, you can pass `--resume` the absolute path to a session's `.jsonl` [transcript file](/docs/en/sessions.md#where-transcripts-are-stored), and Claude Code continues the conversation stored in that file.
404In place of the session ID, you can pass `--resume` the absolute path to a session's `.jsonl` [transcript file](https://code.claude.com/docs/en/sessions.md#where-transcripts-are-stored), and Claude Code continues the conversation stored in that file.
405405
406406## Next steps
407407
408* [Agent SDK quickstart](/docs/en/agent-sdk/quickstart.md): build your first agent with Python or TypeScript
409* [CLI reference](/docs/en/cli-reference.md): all CLI flags and options
410* [GitHub Actions](/docs/en/github-actions.md): use the Agent SDK in GitHub workflows
411* [GitLab CI/CD](/docs/en/gitlab-ci-cd.md): use the Agent SDK in GitLab pipelines
408* [Agent SDK quickstart](https://code.claude.com/docs/en/agent-sdk/quickstart.md): build your first agent with Python or TypeScript
409* [CLI reference](https://code.claude.com/docs/en/cli-reference.md): all CLI flags and options
410* [GitHub Actions](https://code.claude.com/docs/en/github-actions.md): use the Agent SDK in GitHub workflows
411* [GitLab CI/CD](https://code.claude.com/docs/en/gitlab-ci-cd.md): use the Agent SDK in GitLab pipelines
412412
No line in this hunk matches that.