--print: Non-Interactive Mode
The --print flag (short form: -p) turns Claude Code from an interactive assistant into a command-line tool. Instead of opening the chat UI, Claude processes your prompt, does the work, prints the result to stdout, and exits. That one change unlocks everything Unix is good at: pipes, scripts, cron jobs, CI pipelines, and git hooks.
If interactive Claude Code is a pair programmer, claude -p is a programmable one.
How It Works
# Ask a one-off question
claude -p "Explain what src/routes.ts does in two sentences"
# Pipe data in via stdin
cat error.log | claude -p "What's the root cause of this error?"
# Chain it like any other CLI tool
git diff | claude -p "Write a conventional commit message for this diff"
Claude still has its full toolkit — it can read files, run commands, and edit code (subject to your permission settings) — it just does so without the conversational UI, then prints its final answer and exits: code 0 on success, non-zero when the run fails, so scripts can branch on it.
It also loads the same context an interactive session would — your CLAUDE.md, hooks, skills, plugins and MCP servers — and skips the workspace trust dialog, so only run it in directories you trust.
Because output goes to stdout, everything composes:
claude -p "List every TODO comment in src/ as a markdown checklist" > todos.md
Output Formats
For scripting, plain text isn't always enough. --output-format gives you structure:
| Format | What you get | Use when |
|---|---|---|
text (default) | Just the final response | Human-readable output, simple pipes |
json | Result plus metadata (cost, duration, session ID) in one JSON object | Programmatic consumption, logging |
stream-json | Newline-delimited JSON events as they happen | Real-time monitoring, long tasks |
claude -p "Count the TypeScript files in src/" --output-format json | jq -r '.result'
The JSON envelope includes the session ID and an estimated total_cost_usd, which means a script can capture the ID and resume that same session later with claude -p --resume "$id". Non-interactive sessions are saved like interactive ones, though they stay out of the /resume picker.
When you need a guaranteed shape, add --json-schema with a JSON Schema; the validated result arrives in the structured_output field:
claude -p "List the exported functions in src/api.ts" --output-format json \
--json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
| jq '.structured_output.functions'
Real-World Patterns
# Code review in CI
git diff main...HEAD | claude -p "Review this diff for bugs and security issues"
# Batch processing
for f in docs/*.md; do
claude -p "Fix spelling and grammar in $f, edit the file in place" \
--permission-mode acceptEdits
done
# Continue your last interactive session from a script
claude -c -p "Write a summary of today's changes"
One thing to plan for: in a pipeline there's no human to click "allow". Anything that would prompt is denied, and the run carries on without it. So decide up front what the run may do:
| Option | Effect |
|---|---|
--allowedTools "Read,Edit,Bash(npm test *)" | Pre-approve specific tools or commands |
--permission-mode acceptEdits | File edits go through; other commands still need a rule |
--permission-mode auto | A safety classifier reviews each action instead of you |
--permission-mode dontAsk | Deny everything not already allowed — good for locked-down CI |
--tools "Read,Grep,Glob" | Remove tools entirely |
If the run has nothing to set its mode, it takes the built-in starting mode, which can be auto mode — so pass the one you want explicitly. For CI, add --bare as well: it skips hooks, plugins, MCP servers, auto memory and CLAUDE.md discovery, so the run behaves the same on every machine (it needs ANTHROPIC_API_KEY rather than a subscription login).
Pro tip: keep -p prompts specific about output shape — "as a markdown table", "one file path per line", "JSON array only, no prose". You're writing for a parser now, not a person, and Claude follows format instructions well.
Try It Now
- Ask a quick question about this very project without opening a session:
claude -p "How many views does this app have, according to CLAUDE.md?" - Pipe something in:
ls -la | claude -p "Which of these files was modified most recently?" - Try structured output:
Look at the fields you get back — note the session ID and cost metadata.claude -p "Say hello" --output-format json
Related Features
--continue/-c— Pair with-pto append non-interactive turns to your latest session--tools— Restrict what a scripted Claude is allowed to do--bare— Fast, reproducible scripted runs that skip hooks, plugins and memory- Auto Mode — Let a safety classifier approve routine actions in unattended runs
--dangerously-skip-permissions— Removes permission prompts entirely for sandboxed automation (handle with care)--session-id— Give scripted runs predictable IDs so later steps can resume them