Headless mode
Run Claude Code non-interactively in scripts and CI with bare mode, structured output, tool permissions, and session continuation.
Headless mode takes a prompt, performs work, and prints results without the interactive TUI. Use claude -p or --print for scripts, CI, review bots, and one-off automation.
For GitHub Actions, GitLab CI, official Code Review, and cloud comparisons, see Platforms and integrations.
For a CLI script, print mode is enough. For message objects, approval callbacks, structured events, and long-running agents inside a product, use the Agent SDK.
#Minimal usage
claude -p "What does the auth module do?"| Command | Purpose |
|---|---|
| claude -p "Summarize this project" | One text result |
| claude -p "Explain this error" < build.log | Read logs from stdin |
| claude -p "Focus on queries" --continue | Continue latest local session |
| claude -p "Continue review" --resume "$session_id" | Resume a selected session |
| claude -p "Fix test failures" --allowedTools "Bash,Read,Edit" | Pre-approve tools |
| claude -p "Summarize" --output-format json | JSON result and metadata |
Print mode supports ordinary flags including model, settings, mcp-config, append-system-prompt, allowedTools, output-format, and json-schema.
#Prefer bare mode for scripts
Bare mode skips automatic discovery of hooks, skills, plugins, MCP, auto memory, and CLAUDE.md, using explicit configuration. This makes CI less dependent on a developer's local setup.
claude --bare -p "Summarize this file" --allowedTools "Read"Built-in Bash, file reads, and edits remain available. Load extra context explicitly:
| Need | Flag |
|---|---|
| Additional system prompt | --append-system-prompt or --append-system-prompt-file |
| Settings | --settings <file-or-json> |
| MCP | --mcp-config <file-or-json> |
| Agents | --agents <json> |
| Plugin | --plugin-dir or --plugin-url |
Bare mode skips OAuth/keychain discovery. Supply Passion8's ANTHROPIC_BASE_URL=https://passion8.cc and ANTHROPIC_AUTH_TOKEN explicitly in the run environment or passed settings.
The official guide recommends bare mode for scripts/SDK use and describes a transition toward making it the print-mode default. Explicitly choosing it avoids relying on implicit discovery.
#Pipe input and output
cat build-error.txt | claude --bare -p "Explain the root cause concisely" > output.txtSince v2.1.128, piped stdin has a 10 MB limit; oversized input produces a nonzero exit. Save larger material as a file and reference its path instead.
A package script can use Claude as a project checker:
{
"scripts": {
"lint:claude": "git diff main | claude --bare -p \"you are a typo linter. for each typo in this diff, report filename:line on one line and the issue on the next. return nothing else.\""
}
}A diff supplied on stdin does not require Bash access to obtain that diff.
#Structured output
| Format | Meaning |
|---|---|
| text | Final text, default |
| json | Result, session ID, usage, cost, metadata |
| stream-json | Line-delimited events for live UI/logging |
Ordinary JSON:
claude --bare -p "Summarize this project" --output-format jsonConstrain the result with JSON Schema:
claude --bare -p "Extract the main function names from auth.py" \
--output-format json \
--json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'Natural-language output is in result; schema-constrained output is in structured_output. For example:
claude --bare -p "Summarize this project" --output-format json | jq -r '.result'#Streaming events
claude --bare -p "Explain recursion" \
--output-format stream-json \
--verbose \
--include-partial-messages| Event | Purpose |
|---|---|
| system/init | Session, model, tools, MCP, plugins |
| system/api_retry | Retry count, delay, error category |
| system/plugin_install | Marketplace installation progress when synchronization is enabled |
| stream_event | Model and tool-call deltas |
Display text deltas only:
claude --bare -p "Write a short release note" --output-format stream-json --verbose --include-partial-messages | \
jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'#Tool approval and modes
AllowedTools pre-approves tools; it does not limit the available set. Combine it with permissions for restricted CI.
| Configuration | Behavior |
|---|---|
| --allowedTools "Read,Edit,Bash" | No interactive approval for these tools |
| --permission-mode dontAsk | Reject actions not allowed by rules |
| --permission-mode acceptEdits | Automatically accept edits/common filesystem operations |
| permissions.allow | Precisely allow commands, paths, or MCP tools |
claude --bare -p "Run the test suite and fix failures" \
--allowedTools "Bash,Read,Edit" \
--permission-mode acceptEditsFor automated commits, narrow Bash patterns:
claude --bare -p "Review staged changes and create a commit" \
--allowedTools "Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"Spaces matter: git diff followed by a wildcard has a narrower command boundary than git diff immediately followed by a wildcard.
#Custom system prompt
Append instructions to retain Claude Code's default behavior:
gh pr diff "$1" | claude --bare -p \
--append-system-prompt "You are a security engineer. Review for vulnerabilities." \
--output-format jsonSystem-prompt replacement replaces the default instructions. Prefer append unless deliberately taking over the whole agent behavior.
#Continue sessions
claude --bare -p "Review this codebase for performance issues"
claude --bare -p "Now focus on database queries" --continue
claude --bare -p "Generate a summary of all issues found" --continueFor precise resumption, save the session ID:
session_id=$(claude --bare -p "Start a review" --output-format json | jq -r '.session_id')
claude --bare -p "Continue that review" --resume "$session_id"Run from the same directory. Session lookup is scoped by project and Git worktree.
#Background task exit behavior
Background Bash processes such as development servers are terminated about five seconds after print mode produces the final result and stdin closes. The grace period lets nearly completed output finish.
Subagents and workflows are different because their results belong to the final output. Claude waits for them, with a documented default ceiling of ten minutes since v2.1.182. CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS changes that ceiling; zero removes it.
#Commands and skills
User-invoked skills and custom commands can appear directly in a print prompt:
claude -p "/my-skill Review this module's release risks"Bare mode does not discover local skills/plugins automatically. Omit bare mode or explicitly load the required plugin.
Interactive built-in commands such as /login are unsuitable for headless runs. Configuration changes that support noninteractive syntax can use forms such as /config key=value.
#Official references
Support
Need help?
For setup, billing, or model issues, email us. Check the status page for uptime.
WeChat / QQ support is available at the bottom right.

