Run Claude Code from a script with claude -p

Add -p to a claude command and it answers once, prints the result and exits. That makes it usable inside shell scripts, build steps and scheduled jobs. The catch: nobody is there to click yes, so you have to decide in advance what it may do.

The basics

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

Claude Code exits with code 0 when the run succeeds and a non-zero code when it fails, so a script can branch on the exit status. It also reads standard input, so you can pipe text in and send the answer to a file:

cat build-error.txt | claude -p 'concisely explain the root cause of this build error' > output.txt

Piped input is capped at 10 MB. For anything bigger, write it to a file and mention the file path in your prompt.

Choose the output format

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

To get an answer in a shape you define, add --json-schema with a JSON Schema. The data comes back in the structured_output field. If a run ends without valid structured output, for example because Claude declined, that field is missing, so check that it is there before you use it.

What it may do when nobody can click yes

In a claude -p run in the default Manual mode, a tool call that would normally ask for approval is denied unless something approves it. You have three simple ways to say yes ahead of time:

A starting list of rules is in a starter list of permission rules. Deny rules still apply in a script run.

Bare mode, and why it matters

By default a -p run loads what an interactive session would: hooks, skills, subagents, plugins, MCP servers, auto memory and CLAUDE.md. Add --bare and it skips all of that. You then pass in only what you want, for example --settings, --mcp-config or --append-system-prompt.

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

Two things to know. First, bare mode does not use your subscription login: it needs ANTHROPIC_API_KEY or another provider's credentials. Second, the documentation recommends bare mode for scripts and CI, because the result no longer depends on whatever hooks or servers happen to be on that machine.

One warning about repositories you did not write

Without --bare, a -p run executes the hooks in the project's .claude/settings.json and connects the servers in its .mcp.json, even in a folder you have never trusted. Print mode shows no trust dialog and no per-server approval prompt. So before you point a script at a repository you did not write, read those two files, or use --bare.

Keep a conversation going

claude -p "Review this codebase for performance issues"
claude -p "Now focus on the database queries" --continue

--continue picks up the most recent conversation. To resume a specific one, capture its ID:

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

Good to know

Try it on something harmless

  1. Run echo "hello" | claude -p "reply with one word" and check that you get an answer.
  2. Run the same with --output-format json and look at the fields.
  3. Run echo $? right after (or echo %errorlevel% on Windows cmd) and confirm 0.

Limits

This follows Anthropic's documentation on running Claude Code programmatically as we read it in October 2026. We are not affiliated with Anthropic. We wrote this from the documentation and have not tested every example.

See also: Run Claude on a schedule with /loop · Work toward a goal with /goal · Everyday workflows · Claude Code in GitHub Actions.

The free loop-stop skill gives long tasks a limit and a stop rule. If you want a second pair of eyes on your CLAUDE.md and settings, the Tune-Up Kit is a checklist for exactly that.