Claude Code

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?"
CommandPurpose
claude -p "Summarize this project"One text result
claude -p "Explain this error" < build.logRead logs from stdin
claude -p "Focus on queries" --continueContinue 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 jsonJSON 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:

NeedFlag
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.txt

Since 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:

package.json
{
  "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

FormatMeaning
textFinal text, default
jsonResult, session ID, usage, cost, metadata
stream-jsonLine-delimited events for live UI/logging

Ordinary JSON:

claude --bare -p "Summarize this project" --output-format json

Constrain 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
EventPurpose
system/initSession, model, tools, MCP, plugins
system/api_retryRetry count, delay, error category
system/plugin_installMarketplace installation progress when synchronization is enabled
stream_eventModel 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.

ConfigurationBehavior
--allowedTools "Read,Edit,Bash"No interactive approval for these tools
--permission-mode dontAskReject actions not allowed by rules
--permission-mode acceptEditsAutomatically accept edits/common filesystem operations
permissions.allowPrecisely allow commands, paths, or MCP tools
claude --bare -p "Run the test suite and fix failures" \
  --allowedTools "Bash,Read,Edit" \
  --permission-mode acceptEdits

For 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 json

System-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" --continue

For 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.