-p with your prompt and any CLI options:
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.
Basic usage
Add the-p (or --print) flag to any claude command to run it non-interactively. All CLI options work with -p, including:
--continuefor continuing conversations--allowedToolsfor auto-approving tools--output-formatfor structured output
Start faster with bare mode
Add--bare to reduce startup time by skipping auto-discovery of hooks, skills, plugins, MCP servers, auto memory, and CLAUDE.md. Without it, claude -p loads the same context an interactive session would, including anything configured in the working directory or ~/.claude.
Bare 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. Only flags you pass explicitly take effect.
This example runs a one-off summarize task in bare mode and pre-approves the Read tool so the call completes without a permission prompt:
Bare mode skips OAuth and keychain reads. For Anthropic authentication, set
ANTHROPIC_API_KEY or configure an apiKeyHelper in the JSON you pass to --settings. Amazon Bedrock, Google Cloud’s Agent Platform, and Microsoft Foundry use their usual provider credentials.
--bare is the recommended mode for scripted and SDK calls, and will become the default for -p in a future release.Background tasks at exit
If Claude starts a background Bash task during aclaude -p run, for example a dev server or a watch build, that shell is terminated about five seconds after Claude has returned its final result and stdin has closed. The grace period lets a task that finishes right after the result still deliver its output. Before v2.1.163, a never-exiting background process would hold the claude -p invocation open indefinitely.
Background subagents and workflows are exempt from the five-second grace because their result is part of the final output, so claude -p waits for them to complete. From v2.1.182, that wait is capped at ten minutes by default so a stuck background agent cannot hold the process open indefinitely. Adjust the cap with CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS, or set it to 0 to wait without a limit.
If you stop a claude -p run with SIGTERM, for example from kill, a process supervisor, or an SDK host closing the session, Claude Code aborts the in-progress turn, terminates the process tree of any running Bash command, runs SessionEnd hooks, and exits with code 143.
Examples
These examples highlight common CLI patterns. For CI and other scripted calls, add--bare so they don’t pick up whatever happens to be configured locally.
Pipe data through Claude
Non-interactive mode reads stdin, so you can pipe data in and redirect the response out like any other command-line tool. This example pipes a build log into Claude and writes the explanation to a file:--output-format json, the response payload includes total_cost_usd and a per-model cost breakdown, so scripted callers can track spend per invocation without consulting the usage dashboard.
As of Claude Code v2.1.128, piped stdin is capped at 10MB. If you exceed the cap, Claude Code exits with a clear error and a non-zero status. To work with larger inputs, write the content to a file and reference the file path in your prompt instead of piping it.
Add Claude to a build script
You can wrap a non-interactive call in a script to use Claude as a project-specific linter or reviewer. Thispackage.json script pipes the diff against main into Claude and asks it to report typos. Piping the diff means Claude doesn’t need Bash permission to read it, and the escaped double quotes keep the script portable to Windows:
Get structured output
Use--output-format to control how responses are returned:
text(default): plain text outputjson: structured JSON with result, session ID, and metadatastream-json: newline-delimited JSON for real-time streaming
result field:
--output-format json with --json-schema and a JSON Schema definition. The response includes metadata about the request (session ID, usage, etc.) with the structured output in the structured_output field.
This example extracts function names and returns them as an array of strings:
claude exits with Error: --json-schema is not a valid JSON Schema followed by the validator’s diagnostic. Claude Code accepts schemas that use the format keyword, such as "format": "email", but treats format as an annotation and doesn’t enforce it. Before v2.1.205, Claude Code silently ignored an invalid schema and returned unstructured text, and treated any schema containing format as invalid.
Stream responses
Use--output-format stream-json with --verbose and --include-partial-messages to receive tokens as they’re generated. Each line is a JSON object representing an event:
result message with the final response text, cost, and session metadata.
If your consumer reads the stream slowly, Claude Code waits for the queued output to drain before exiting, scaling the wait with how much is still queued, capped at 30 seconds. Before v2.1.214 the exit wait was capped at about two seconds, which could cut off the end of a large response.
The following example uses jq to filter for text deltas and display just the streaming text. The -r flag outputs raw strings (no quotes) and -j joins without newlines so tokens stream continuously:
Follow subagent messages
Messages from subagents appear in the stream asassistant and user messages whose parent_tool_use_id field is the ID of the tool call that spawned the subagent. Messages from the main conversation carry null in that field.
By default, Claude Code emits only subagent tool_use and tool_result blocks. Pass --forward-subagent-text or set CLAUDE_CODE_FORWARD_SUBAGENT_TEXT to also emit subagent text and thinking blocks, so you can reconstruct each subagent’s transcript. This requires Claude Code v2.1.211 or later.
When you enable either option, Claude Code forwards messages from subagents at every nesting depth: when a subagent spawns its own subagent, the nested subagent’s messages carry the ID of the Agent tool call that spawned it in parent_tool_use_id, so you can rebuild the full nesting tree by following those IDs. Before v2.1.219, messages from nested subagents didn’t appear in the stream.
Handle API retries
When an API request fails with a retryable error, Claude Code emits asystem/api_retry event before retrying. You can use this to surface retry progress or implement custom backoff logic.
Read session metadata
Thesystem/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:
plugin_installevents, whenCLAUDE_CODE_SYNC_PLUGIN_INSTALLis set.hook_started,hook_progress, andhook_responseevents, while a configuredSessionStartorSetuphook runs. These stream as the hook produces them. Claude Code v2.1.169 through v2.1.203 delivered them in one batch after the hook completed, still ahead ofsystem/init; v2.1.204 restored live delivery.
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. The field requires Claude Code v2.1.205 or later and is absent from earlier versions. See SDKSystemMessage for the capability list.
Fail CI when a plugin or MCP server doesn’t load
Use the plugin fields in thesystem/init event to catch a plugin that didn’t load:
Use the MCP server fields the same way. Claude 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:
When you run the command by hand in a terminal, Claude Code also prints a startup warning to stderr, such as
Warning: 1 MCP server skipped due to invalid config:, followed by the reason for each skipped entry. When you redirect stderr, or when a program such as a CI runner or an SDK host captures it, Claude Code prints no warning and reports the skipped entries only in the mcp_server_errors field. The warning requires Claude Code v2.1.219 or later.
Track plugin installs
WhenCLAUDE_CODE_SYNC_PLUGIN_INSTALL 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.
Auto-approve tools
Use--allowedTools to let Claude use certain tools without prompting. This example runs a test suite and fixes failures, allowing Claude to execute Bash commands and read/edit files without asking for permission:
dontAsk denies anything not in your permissions.allow rules or the read-only command set, which is useful for locked-down CI runs. AskUserQuestion, connector tools your organization set to ask, and MCP tools marked requiresUserInteraction are denied even when an allow rule matches.
acceptEdits lets Claude write files without prompting and also auto-approves common filesystem commands such as mkdir, touch, mv, and cp. Other shell commands and network requests still need an --allowedTools entry or a permissions.allow rule, otherwise the run aborts when one is attempted:
Create a commit
This example reviews staged changes and creates a commit with an appropriate message:--allowedTools flag uses 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.
User-invoked skills and custom commands work in
-p mode: include /skill-name in the prompt string and Claude Code expands it before running. Built-in commands that only run in the terminal interface, such as /login, aren’t available in -p mode. /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 require Claude Code v2.1.205 or later and follow each command’s availability notes. To change a setting from a -p invocation, pass key=value to /config, for example /config thinking=false.Customize the system prompt
Use--append-system-prompt to add instructions while keeping Claude Code’s default behavior. This example pipes a PR diff to Claude and instructs it to review for security vulnerabilities:
--system-prompt to fully replace the default prompt.
Continue conversations
Use--continue to continue the most recent conversation, or --resume with a session ID to continue a specific conversation. This example runs a review, then sends follow-up prompts:
Next steps
- Agent SDK quickstart: build your first agent with Python or TypeScript
- CLI reference: all CLI flags and options
- GitHub Actions: use the Agent SDK in GitHub workflows
- GitLab CI/CD: use the Agent SDK in GitLab pipelines