Skip to content
,

What Is claude -p? Claude Code Headless Mode Explained (Flags, JSON, CI, Examples)

8–13 minutes
Worried woman in a white coat at a tech conference holding up a card with the Claude logo, with the text Run Claude Without the Chat

If you have seen claude -p in a script or a GitHub workflow and wondered what it does, here is the short answer: -p (short for --print) runs Claude Code non-interactively. You give it a prompt, it does the work, prints the answer and exits, just like any other command-line tool.

That one flag turns Claude Code into something you can pipe data into, call from npm scripts, run in CI and chain in shell scripts.

This guide covers what claude -p is, every useful flag, JSON and structured output, permissions for unattended runs, bare mode, continuing conversations, ready-to-use examples and fixes for common errors, all checked against Anthropic’s current Claude Code docs.

TL;DR

  • What it is: claude -p "prompt" runs Claude Code once without the interactive interface, prints the result and exits (code 0 on success, non-zero on failure).
  • Pipe data in: cat error.log | claude -p "explain the root cause" (stdin is capped at 10 MB).
  • Machine-readable output: --output-format json (or stream-json), plus --json-schema for structured results.
  • Permissions: pre-approve tools with --allowedTools "Read,Edit,Bash" or set --permission-mode (acceptEdits, auto, dontAsk).
  • For CI: add --bare for fast, repeatable runs that skip local hooks, plugins, MCP servers, CLAUDE.md and auto memory (needs ANTHROPIC_API_KEY).
  • Limits: --max-turns and --max-budget-usd stop runaway jobs.

What claude -p Means

Normally, claude opens an interactive session in your terminal. Adding -p or --print switches to non-interactive mode, which Anthropic calls running Claude Code programmatically through the Agent SDK’s CLI.

You get the same tools, agent loop and context handling as the interactive app, but with no chat window. The run ends when Claude finishes, so you can:

  • Use Claude inside shell scripts, Makefiles and npm scripts.
  • Pipe logs, diffs and files into it, and redirect its answer to a file.
  • Run it in CI/CD (GitHub Actions, GitLab) for reviews, fixes and reports.
  • Get JSON back and parse it with tools like jq.

Not installed yet? Follow our Claude Code install guide first.

Basic Usage

claude -p "What does the auth module do?"

Claude reads your project, answers and exits. Claude Code returns exit code 0 on success and a non-zero code when the run fails, so scripts can branch on it. Invalid flags are reported on stderr before the run starts.

To let Claude actually change files, pre-approve the tools it needs:

claude -p "Find and fix the bug in auth.py" --allowedTools "Read,Edit,Bash"

Not every flag combines with -p. For example, Claude Code rejects --bg with an error naming the conflict.

The Flags You Will Use Most

Flag What it does Example
-p, --print Non-interactive mode claude -p "summarise README.md"
--output-format text (default), json or stream-json --output-format json
--json-schema Force output to match a JSON Schema See the JSON section
--allowedTools Pre-approve tools or commands --allowedTools "Read,Edit"
--permission-mode Baseline approvals: acceptEdits, auto, dontAsk --permission-mode acceptEdits
--permission-prompts none Deny anything that would wait for a human (v2.1.259+) Scheduled jobs
--bare Skip auto-discovery of hooks, skills, plugins, MCP, CLAUDE.md, auto memory CI runs
--model Pick a model alias (sonnet, opus, haiku, fable) or full name --model sonnet
--max-turns Cap agentic turns (print mode only) --max-turns 5
--max-budget-usd Stop when estimated API spend hits a cap (print mode only) --max-budget-usd 2
--continue, -c Continue the most recent conversation claude -p "now fix it" -c
--resume, -r Resume a session by ID, name or transcript path --resume "$id"
--append-system-prompt Add instructions on top of the default system prompt Role prompts in scripts
--mcp-config Load MCP servers from a file or JSON Tools in bare mode

Pipe Data In and Out

Non-interactive mode reads stdin, so it behaves like any Unix tool:

cat build-error.txt | claude -p "concisely explain the root cause of this build error" > output.txt
  • Stdin cap: piped input is limited to 10 MB. For bigger inputs, save to a file and reference the path in your prompt.
  • No extra permissions needed: piping a diff in means Claude does not need Bash permission to read it.
  • Windows-friendly scripts: use escaped double quotes inside package.json scripts.

JSON, Streaming and Structured Output

JSON with metadata

claude -p "Summarize this project" --output-format json | jq -r '.result'

The JSON includes the text in result, plus session_id, usage and total_cost_usd with a per-model cost breakdown, so scripts can track spend.

Structured output with a schema

claude -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"]}' \
  | jq '.structured_output'

The result lands in structured_output. If Claude declines or the run fails, that field is missing, so always check it exists before using it. An invalid schema exits with Error: --json-schema is not a valid JSON Schema.

Live streaming

claude -p "Explain recursion" --output-format stream-json --verbose --include-partial-messages

Each line is a JSON event; the last line is a result message with the final text, cost and session data. Retryable API failures show up as system/api_retry events.

Permissions in Non-Interactive Runs

There is nobody to click “Allow” in a script, so decide permissions up front.

Option Effect Good for
--allowedTools "Read,Edit" Those tools run without asking Targeted jobs
--allowedTools "Bash(git diff *)" Only commands starting with git diff (note the space before *) Tight command allowlists
--permission-mode acceptEdits File writes and common file commands (mkdir, mv, cp) auto-approved Lint fixes, refactors
--permission-mode auto A classifier reviews most actions instead of you Longer unattended tasks
--permission-mode dontAsk Denies anything that would prompt Locked-down CI
--permission-prompts none Never waits for a human; prompts become denials Cron jobs, scheduled runs

Calls to tools you did not list still run if they need no approval (such as reading files in your working directory). In Manual mode, anything that needs approval is denied unless something approves it.

Security note: without --bare, a -p run executes the hooks in a project’s .claude/settings.json and connects servers in its .mcp.json, even in a folder you have never trusted, and shows no trust dialog. Only run claude -p in repos you trust, or use --bare. See our MCP security best practices.

Bare Mode for CI and Scripts

claude --bare -p "Summarize README.md" --allowedTools "Read"

--bare skips auto-discovery of hooks, skills, custom commands, subagents, plugins, MCP servers, auto memory and CLAUDE.md. It starts faster and gives the same result on every machine. Anthropic recommends it for scripted and SDK calls and says it will become the default for -p in a future release.

  • Auth: bare mode never reads your subscription login or keychain. Set ANTHROPIC_API_KEY (from the Claude Console) or use an apiKeyHelper in --settings.
  • Tools: Claude gets Bash, file read and file edit.
  • Add context explicitly: --append-system-prompt or --append-system-prompt-file, --settings, --mcp-config, --agents, --plugin-dir.
  • Limits: no hooks (even passed via settings), no system reminders and no background tasks.

Because bare mode skips CLAUDE.md, pass key project rules with --append-system-prompt-file. Our CLAUDE.md guide explains what to put in that file.

Continue a Conversation

# First request
claude -p "Review this codebase for performance issues"

# Continue the most recent conversation
claude -p "Now focus on the database queries" --continue

# Resume a specific session
session_id=$(claude -p "Start a review" --output-format json | jq -r '.session_id')
claude -p "Continue that review" --resume "$session_id"

Claude Code finds a session by ID in any project on the same machine, and --resume also accepts the absolute path to a session’s .jsonl transcript.

7 Ready-to-Use Examples

  1. Explain a failing build: npm run build 2>&1 | claude -p "explain this error and suggest a fix"
  2. Typo linter in package.json: "lint:claude": "git diff main | claude -p \"you are a typo linter. report filename:line and the issue. return nothing else.\""
  3. Auto commit message: claude -p "Look at my staged changes and create an appropriate commit" --allowedTools "Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"
  4. Security review of a PR: gh pr diff "$1" | claude -p --append-system-prompt "You are a security engineer. Review for vulnerabilities." --output-format json
  5. Fix failing tests: claude -p "Run the test suite and fix any failures" --allowedTools "Bash,Read,Edit" --max-turns 10
  6. Apply lint fixes: claude -p "Apply the lint fixes" --permission-mode acceptEdits
  7. Unattended dependency update: claude -p "Update the dependency pins and run the tests" --permission-mode auto --permission-prompts none

Slash Commands and Skills in -p Mode

  • Skills and custom commands work: include /skill-name in the prompt and Claude Code expands it. See our Claude Skills guide.
  • Terminal-only commands like /login are not available.
  • Some commands take an argument: /model sonnet, /effort, /fast, and /config thinking=false to change a setting.
  • /mcp with no argument prints a text summary of server status.

Costs and Safety Limits

  • Subscription vs API: normal -p runs can use your Claude login; --bare runs bill your API key. Compare plans in our Claude Code pricing guide.
  • Cap spend: --max-budget-usd stops the run (and any background work) at your limit.
  • Cap loops: --max-turns limits agentic turns; there is no limit by default.
  • Track costs: read total_cost_usd from JSON output.
  • Background work: a run can wait for background tasks it started; by default, idle waiting stops after 10 minutes.
  • Stopping: SIGTERM exits with code 143 and leaves the turn unfinished; send SIGINT first to end the turn cleanly.

More ways to save are in how to reduce Claude Code token usage.

Troubleshooting

Problem Likely cause Fix
Claude says it cannot edit files Edit or Bash not approved Add --allowedTools "Read,Edit,Bash" or a permission mode
Auth error in --bare Bare mode ignores your login Set ANTHROPIC_API_KEY
Input too large error Stdin over 10 MB Write to a file and reference its path
structured_output missing Claude declined or run failed Check the field exists; look at result and exit code
Unknown option --permission-prompts Claude Code older than v2.1.259 Update Claude Code
A hook or MCP server unexpectedly ran Normal -p loads project config Use --bare and pass only what you need
Different results on CI vs laptop Local hooks, plugins or CLAUDE.md differ Use --bare for repeatable runs
MCP server silently missing Invalid --mcp-config entry skipped Check mcp_server_errors in the system/init event
Run hangs at the end Waiting for background work Check the stderr “Waiting for background work” line; lower the 10-minute cap with CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS

My Take

claude -p is where Claude Code stops being a chat app and becomes a building block. Start with piping errors and diffs into it, then add --output-format json when you need to parse results.

For anything in CI, use --bare, a tight --allowedTools list and a --max-budget-usd cap. That combination is fast, predictable and safe.

FAQ

What does claude -p do?

It runs Claude Code non-interactively: it takes your prompt, does the work, prints the result and exits. -p is short for --print.

What is the difference between claude and claude -p?

claude opens an interactive session. claude -p runs one task without the interface, so it works in scripts, pipes and CI.

How do I get JSON output from Claude Code?

Add --output-format json. For a fixed shape, also pass --json-schema and read the structured_output field.

Does claude -p use CLAUDE.md?

Yes, normally it loads CLAUDE.md like an interactive session. With --bare it skips CLAUDE.md, hooks, plugins, MCP servers and auto memory.

How do I stop claude -p asking for permission?

Pre-approve tools with --allowedTools, or set --permission-mode acceptEdits, auto or dontAsk. Add --permission-prompts none for unattended runs.

Can I continue a claude -p conversation?

Yes. Use --continue for the most recent one, or --resume with a session ID from the JSON output.

Does claude -p cost extra?

It uses the same usage as interactive Claude Code. Bare mode bills your API key. Use --max-budget-usd to cap spend.

Can I use claude -p in GitHub Actions?

Yes. Anthropic documents GitHub Actions and GitLab CI/CD setups; use --bare and an API key secret for repeatable runs.

Sources

Free weekly email

Get new AI guides every week

One short weekly email with our newest local AI, ComfyUI and AI tool guides. No spam, no pop-ups, just the good stuff.

Free. Unsubscribe anytime in one click. We only use your email to send this newsletter. See our privacy policy.

Worried woman in a white coat at a tech conference holding up a card with the Claude logo, with the text Run Claude Without the Chat