Most people use Claude Code as a helper — you type, it responds, you go back and forth. But Claude can also be an agent embedded in your project. A script that reviews every PR at 2am. A cron job that audits dependencies weekly. A CI step that catches security issues before code ships. No human in the loop, no terminal open.
The claude -p flag (short for --print) makes this possible. It runs Claude non-interactively — no terminal UI, just a prompt in and structured output out. Your scripts call it, parse the JSON, and act on the results. This is the foundation for turning Claude from a tool you talk to into an agent that works for you.
Add —bare to skip auto-discovery of hooks, plugins, MCP servers, and CLAUDE.md. This makes your scripts faster, more portable, and less dependent on local configuration. Anthropic recommends —bare for all scripted calls — it will become the default for -p in a future release.
Text Output Mode
The simplest way to call Claude from a terminal:
$ claude -p "What is the capital of France?"Paris is the capital of France.No metadata, no JSON — just the result field as plain text. This is the default output format when you use -p, and it is perfect for quick questions or piping a response directly into another command.
But for automation, you need more than the answer. You need the session ID, token counts, cost, and stop reason. That is where structured output comes in.
JSON Output Mode
Add --output-format json to get the full response envelope:
$ claude -p "Say exactly: Hello CLI Test" --output-format jsonEvery JSON response wraps the actual answer inside a typed envelope — a structured JSON object that contains both the result and metadata. The result field contains the same text you would see in text mode, but now it comes alongside metadata you can parse, log, and act on. This is our recommended starting point for any automation work.
The JSON Envelope
Top-Level Fields
| Field | Type | Description |
|---|---|---|
type | string | Always “result” for a completed response |
subtype | string | ”success” or “error_max_budget_usd” if the cost limit was hit |
is_error | boolean | false on success — check this first in every response handler |
duration_ms | number | Wall-clock time including tool execution |
result | string | The text response, identical to what text mode returns |
stop_reason | string | ”end_turn” when Claude finished naturally, “max_tokens” if truncated |
session_id | string | UUID for this conversation — pass to —resume to continue it later |
total_cost_usd | number | Cost in USD for this single call |
usage | object | Token breakdown: input_tokens, cache_creation_input_tokens, cache_read_input_tokens, output_tokens |
permission_denials | array | Tools that were blocked by the permission system — empty when nothing was denied |
The total_cost_usd field is the cost for this single call, not a cumulative total. In a resumed session, each response reports only its own cost. If you need to track spend across an entire conversation, sum total_cost_usd from every call in the chain.
Pipe JSON output to jq for quick extraction on the command line:
claude -p ”…” —output-format json | jq ‘.result’
Install jq with brew install jq (macOS), apt install jq (Ubuntu), or visit jqlang.org for other platforms.
Run your first JSON call and extract the cost:
claude -p “What is 2+2?” —output-format json | jq ‘{answer: .result, cost: .total_cost_usd, session: .session_id}‘
Save that session_id — you’ll use it in the Sessions chapter to resume this conversation.
What if it goes wrong? If you see jq: command not found, install jq first. If the CLI hangs, check your API key with claude config view. If you get a 401 error, run claude login to re-authenticate.
Stream-JSON Preview
When you need real-time output — for a typewriter UI, a progress indicator, or a long-running agent pipeline — there is a third format: stream-json.
$ claude -p "Say exactly: Hello CLI Test" --output-format stream-json --verboseThis emits NDJSON (newline-delimited JSON) events in real time, one JSON object per line. Each line has a type field that tells you what kind of event it is: system for initialization metadata, assistant for text responses, rate_limit_event for API status, and result for the final envelope.
The stream protocol is covered in depth in the Stream Protocol chapter, including how to parse partial messages for typewriter effects and how to handle tool-use events mid-stream.
Want to explore these flags interactively? The explorer below lets you toggle between output formats and see what each flag does:
Run claude -p “Hello” —output-format json | jq ‘{cost: .total_cost_usd, session: .session_id}’. You now know the cost and session ID for every call. Try piping a different question and compare costs — even trivial prompts have a minimum cost from the system prompt cache.