Lesson 3.1 — –print Flag and Single-Shot Mode: The Automation Foundation
Lesson 3.1 — --print Flag and Single-Shot Mode: The Automation Foundation
Module 3 — Agentic & Headless Workflows | ClaudeForge
THE NAIVE APPROACH TRAP
A developer fluent in the Claude.ai browser interface reaches for the obvious answer: open chat, paste a file, copy the improved code back to disk. For a one-off fix this is tolerable. For the 340 Python files in a monorepo that need Google-style docstrings before an API freeze on Friday, it is not a workflow — it is a grind that introduces inconsistency at every paste boundary.
The next instinct is to script around the interactive claude terminal:
This breaks immediately. The interactive REPL writes terminal control sequences (33[2K, carriage returns, spinner frames) to stdout alongside response content. Redirect stdout to a file and you get ANSI noise with code fragments embedded. diff cannot parse it, jq throws, and the output files are corrupted.
The root failure is architectural: interactive mode was built for a human TTY. There is no mechanism to separate Claude's response content from its UI chrome in that mode. Attempting to grep or sed through ANSI output is a road to fragile heuristics. The whole model is wrong for scripted use.
THE FAILURE MODE
ANSI pollution survives piping. Even when stdout is redirected, the interactive session emits escape sequences based on environment detection. --output-format json is the correct fix: it forces a clean JSON envelope regardless of terminal state, making Claude Code a proper UNIX filter.
ANTHROPIC_API_KEY silently switches billing. If this variable is set in your shell — leftover from a Module 8 experiment or copied from a .env — every claude --print invocation silently routes to paid API credits instead of your Claude.ai Pro subscription. No banner, no warning, identical exit codes. You discover it when the invoice arrives. Run claude auth status before any batch job and confirm the output reads Logged in via Claude.ai (Pro). If it shows API key authentication, unset ANTHROPIC_API_KEY before continuing.
Non-zero exit codes swallowed by bare for loops. claude --print exits 0 on success, 1 on API errors including 429 rate limits, and 2 on usage errors (malformed flag combinations). A for file in ...; do claude --print ...; done loop without set -euo pipefail ignores every non-zero exit and reports success at the end. At file 280 of 340, a rate-limit failure silently drops output for the remaining 60 files. The state log pattern — write a file path to .claude/processed.log only after a confirmed exit 0 — is the only correct way to know which files were actually processed.
Restarting without a state file burns tokens. A batch with no restart ledger reprocesses all 340 files from zero if interrupted at file 200. At roughly 2,000 tokens per file pair, that is 280,000 wasted input tokens. The state file is not a nice-to-have; it is the mechanism that makes headless pipelines economically viable.
--max-turns absent means Claude decides depth. Without --max-turns 1, Claude Code may take 3–5 agentic steps per file — read, analyse, inspect related modules, write, verify. For a docstring-only task this wastes turns and tokens. In CI, uncapped turns produce non-deterministic runtime and token cost.
THE CLAUDEFORGE ARCHITECTURE
--print is the single flag that converts Claude Code from a REPL into a UNIX tool. The rest of Module 3 is built on it.
Backward connections:
Keep going with the full lesson
The rest of this lesson — plus its implementation guide, runnable scripts and source code — is included with the course or an All Access plan. Create a free account to start the free lessons in every course.
Already a member? Sign in