Add plain-text CI-friendly output format for streaming logs

Resolved 💬 3 comments Opened Apr 2, 2026 by jangel97 Closed Apr 6, 2026

Summary

When running claude -p in CI pipelines (GitLab CI, GitHub Actions, etc.), the current output options are:

  • Default (no flag): Clean but no real-time streaming — you only see output after completion
  • --output-format stream-json: Real-time streaming but produces dense JSON blobs that are nearly unreadable in CI job logs (e.g. a single 162-line trace can be 50K+ tokens of JSON)

There's no middle ground: a plain-text streaming format designed for human consumption in CI logs.

Proposal

Add a new output format (e.g. --output-format stream-text or --output-format ci) that streams human-readable, grep-friendly progress lines. Something like:

[thinking] Planning approach...
[tool] Bash: git checkout main
[result] Switched to branch 'main' (exit 0)
[tool] Read: releases/model-opt.yaml
[tool] Edit: releases/model-opt.yaml (lines 12-15)
[text] Created release YAML for model-opt 3.4.0-ea.2
[tool] Bash: git push origin release/model-opt-3.4.0-ea.2
[result] To gitlab.com:... (exit 0)
[cost] $1.46 | 68 turns | 8m32s

Key properties

  • One line per event — easy to scan in CI job logs
  • Prefixed by event type[thinking], [tool], [result], [text], [error], [cost] — easy to grep/filter
  • Tool results truncated to a reasonable length (e.g. first 5 lines or 500 chars) to avoid log bloat
  • Real-time streaming — lines appear as events happen, not buffered until completion
  • No JSON parsing required — readable directly in GitLab/GitHub CI log viewers

Use case

We run Claude Code as an autonomous agent in GitLab CI pipelines (via claude -p --permission-mode acceptEdits). With stream-json, the job trace is essentially unusable for human review — you need to download and parse it with a script. Without streaming, you can't monitor progress in real-time. A CI-friendly text format would solve both problems.

Current workaround

We removed --output-format stream-json --verbose entirely and just use default output, sacrificing real-time visibility for readability.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗