Your First CLI Call

Run your first Claude CLI command and understand what comes back

Everything starts with a single command. The claude -p flag (short for --print) runs Claude in headless mode — no interactive UI, just a prompt in and a response out. This is the foundation for every script, pipeline, and automation you will build.

Text Output Mode

The simplest way to call Claude from a terminal:

Terminal window
$ 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:

Terminal window
$ claude -p "Say exactly: Hello CLI Test" --output-format json
JSON Response Envelopeartifacts/01/json_output.json
1{
2 "type": "result",
3 "subtype": "success",
4 "is_error": false,
5 "duration_ms": 1998,
6 "duration_api_ms": 1976,
7 "num_turns": 1,
8 "result": "Hello CLI Test",A
9 "stop_reason": "end_turn",
10 "session_id": "0e639165-79b1-4bd4-bb0f-4cb4c15115d4",B
11 "total_cost_usd": 0.0079825,C
12 "usage": {
13 "input_tokens": 3,
14 "cache_read_input_tokens": 15635,
15 "output_tokens": 6
16 }
17}
AThe text response — same as text mode output
BSave this UUID to resume the conversation later
CCost for this single call, not cumulative

Every JSON response wraps the actual answer inside a typed envelope. 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.

The JSON Envelope

Top-Level Fields

FieldTypeDescription
typestringAlways “result” for a completed response
subtypestring”success” or “error_max_budget_usd” if the cost limit was hit
is_errorbooleanfalse on success — check this first in every response handler
duration_msnumberWall-clock time including tool execution
resultstringThe text response, identical to what text mode returns
stop_reasonstring”end_turn” when Claude finished naturally, “max_tokens” if truncated
session_idstringUUID for this conversation — pass to —resume to continue it later
total_cost_usdnumberCost in USD for this single call
usageobjectToken breakdown: input_tokens, cache_read_input_tokens, output_tokens
permission_denialsarrayTools that were blocked by the permission system — empty when nothing was denied
Gotcha

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.

Tip

Pipe JSON output to jq for quick extraction on the command line: claude -p ”…” —output-format json | jq ‘.result’

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.

Terminal window
$ claude -p "Say exactly: Hello CLI Test" --output-format stream-json --verbose

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

$ claude -p "your prompt here"