CloudCodeTree LogoCloudCodeTree
AI NewsTutorialsAbout
CloudCodeTree Logo
CloudCodeTree
  • AI News
  • Tutorials
  • About
← Back to AI News
Real-Time Claude Code Progress in Your Terminal or Pipeline: Use --output-format stream-json

Real-Time Claude Code Progress in Your Terminal or Pipeline: Use --output-format stream-json

Chris Harper

3 min read

Jul 23, 2026 · 04:06 UTC

AI
Workflow
Claude Code
Best Practices
Developer Tools

TL;DR: --output-format stream-json emits one JSON line per event as Claude works — text deltas, tool calls, costs — so you can build live progress bars or CI monitors without parsing screen output.

When you run claude -p "..." the default text output works fine for reading but breaks when you need to parse it programmatically. Three output modes cover different needs:

FlagUse case
--output-format textDefault. Human-readable prose. Hard to parse.
--output-format jsonOne JSON blob at the end with result + cost. Great for scripts that need the answer.
--output-format stream-jsonNDJSON (one JSON per line), emitted in real time. Great for progress monitors and streaming UIs.

What stream-json emits

Each line is a standalone JSON object with a type field. Key event types:

  • system / init: session metadata, working directory, model in use
  • assistant / text: a token delta — event.delta.text gives the partial string
  • tool_use: Claude is calling a tool — event.name + event.input
  • tool_result: the result returned to Claude
  • result: final event — contains result (the answer string), total_cost_usd, session_id, num_turns

Stream text tokens live

claude -p "List the 5 largest files in the current directory" \
  --output-format stream-json \
  --verbose \
| jq -r 'select(.type == "assistant") | .event.delta.text // empty'

This prints text as it streams — each token appears immediately, same as interactive mode. The --verbose flag ensures the init event with session metadata is included; always pair it with stream-json.

Extract the final result

RESULT=$(claude -p "Summarize the file README.md" \
  --output-format stream-json \
  | tail -1 \
  | jq -r '.result')
echo "$RESULT"

The last line is always the result event.

Track cost per invocation

claude -p "Review src/auth.ts for security issues" \
  --output-format stream-json \
| jq -r 'select(.type == "result") | "Cost: $\(.total_cost_usd) | Turns: \(.num_turns)"'

Output: Cost: $0.0031 | Turns: 4

Python: build a live progress display

import subprocess, json

proc = subprocess.Popen(
    ["claude", "-p", "Audit our API surface for missing rate limits",
     "--output-format", "stream-json", "--verbose"],
    stdout=subprocess.PIPE, text=True
)

for line in proc.stdout:
    event = json.loads(line)
    if event.get("type") == "assistant":
        print(event["event"]["delta"].get("text", ""), end="", flush=True)
    elif event.get("type") == "tool_use":
        print(f"\n[tool: {event['event']['name']}]", end="", flush=True)
    elif event.get("type") == "result":
        print(f"\n\nDone. Cost: ${event['total_cost_usd']:.4f} | Turns: {event['num_turns']}")

Use --output-format json when you only need the final answer (cheaper to process); reach for stream-json when you need real-time visibility, tool-call audit trails, or per-invocation cost logging without a separate dashboard.

Sources: Run Claude Code programmatically — Claude Code Docs · Claude Code stream-json: the output format that changes everything — backgroundclaude.com · Parsing Claude Code stream-json with jq — ytyng.com