0Pricing
Claude Architect · Lesson

Non-Interactive Mode

The -p / --print flag for headless CI execution.

Non-Interactive Mode is a free Claude Architect lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Claude Architect learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Why Headless Mode Exists

Claude Code defaults to an interactive terminal session: it prompts you, waits for input, and streams a conversation. That model is perfect at your desk and useless inside a pipeline.

A CI/CD runner has no human to confirm a plan, approve an edit, or answer a follow-up question. It needs a single command that runs, produces output, and exits with a status code.

That is exactly what -p / --print delivers: non-interactive (headless) execution. It is the foundational flag for running Claude Code in CI.

The --print Flag

You invoke headless mode by passing your prompt to -p (the short form of --print). Claude runs the agentic loop to completion and prints the final result to stdout, then the process exits.

There is no REPL, no waiting on input, no confirmation prompts. One command in, one result out — the contract a pipeline step needs.

# Interactive (default) — opens a session, waits for you
claude

# Non-interactive (headless) — runs and exits, prints to stdout
claude -p "Review the staged diff and list any blocking issues"

A Real CI Step

In practice -p becomes one step in a job. The runner checks out the code, then calls Claude with a precise instruction. Because the process exits when the loop reaches end_turn, the pipeline moves on naturally.

Keep the prompt scoped and explicit — there is no human to clarify ambiguity mid-run, so the instruction must stand on its own.

# .github/workflows/review.yml (excerpt)
- name: Claude review
  run: |
    claude -p "Review the diff in this PR. Flag only changes that
    introduce a bug, a security issue, or break a public API."
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

Parseable Output: --output-format json

Plain text is fine for a human reading logs, but a pipeline usually needs to act on the result — post a comment, set a check status, gate a merge.

Add --output-format json so Claude emits a structured, machine-readable result instead of free prose. Your next step can then parse fields deterministically with jq or a script.

claude -p "List blocking issues in the staged diff" \
  --output-format json | jq '.result'

Enforcing a Schema

JSON alone still lets the model choose its shape. For reliable automation, pair --output-format json with a schema so every run returns the same fields. This eliminates syntax surprises and lets you require exactly the keys your pipeline consumes.

Reuse the same structured-output discipline as the API: mark a field required only if it is always present — never force a field that may legitimately be absent, or the model will fabricate it.

{
  "type": "object",
  "properties": {
    "verdict": { "type": "string", "enum": ["pass", "fail"] },
    "issues": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "file": { "type": "string" },
          "severity": { "type": "string", "enum": ["blocking", "warning"] },
          "detail": { "type": "string" }
        },
        "required": ["file", "severity", "detail"]
      }
    }
  },
  "required": ["verdict", "issues"]
}

Review in an Isolated Session

A subtle but exam-critical point: when Claude both generates code and then reviews it in the same session, the review is biased — the author retains its own reasoning and won't challenge itself.

In CI, run the review in a fresh, isolated session, separate from any generation context. An independent instance is far more likely to catch real defects. This mirrors the general rule: independent review beats same-session self-review.

# Generation and review are SEPARATE invocations / sessions
claude -p "Implement the change described in TASK.md"

# Fresh, unbiased reviewer — no generation history
claude -p "Review the resulting diff for correctness and security only" \
  --output-format json

Minimize False Positives

A CI reviewer that cries wolf gets ignored. The goal is precision: surface real blockers, stay quiet otherwise.

The lever is the prompt, not vague pleading. Explicit criteria beat fuzzy asks: "flag a comment only when it contradicts the code" outperforms "be more precise." A few targeted few-shot examples (2-4) of true vs. false positives further calibrate the model on your edge cases.

claude -p "Review the diff. Report an issue ONLY if it (a) causes
incorrect behavior, (b) is a security risk, or (c) breaks a public
contract. Do NOT comment on style, naming, or formatting.

Example (flag):   off-by-one in loop bound -> array overrun
Example (ignore): a variable could be renamed for clarity" \
  --output-format json

Scope Tools with Least Privilege

A headless run executes without human approval, so unrestricted tool access is risky. Grant only what the job needs.

For a read-only review you typically want Read, Grep, and Glob — not Write, Edit, or arbitrary Bash. This is the same least-privilege principle you apply to agent tool sets: scope tools to the role, and keep the set small for reliable selection.

claude -p "Review the diff and report blocking issues" \
  --output-format json \
  --allowedTools "Read,Grep,Glob"

Stop on the Loop, Not on a Status Line

Even headless, the agentic loop is unchanged: request -> inspect stop_reason -> if tool_use, run tools and continue -> repeat until end_turn. The process exits when the model reaches end_turn.

Do not wrap Claude in a script that greps the output for words like "done" or "finished" to decide completion. Termination is driven by the stop reason. Any iteration cap you set is a safety net, never the primary stop mechanism.

Re-Runs: Report Only What's New

CI re-runs constantly — every push retriggers the job. If the reviewer re-reports the same five issues each time, the signal drowns in noise.

On a re-run, feed the prior results back in and instruct Claude to report only new or still-unfixed issues. This keeps each comment actionable and respects that developers have already seen the earlier findings.

claude -p "Here are the issues from the previous run:
$(cat prev_review.json)

Review the current diff. Report ONLY issues that are new or remain
unfixed. Omit anything already resolved." \
  --output-format json > review.json

Headless vs. the Batch API

Don't confuse non-interactive CLI execution with the Message Batches API. They solve different problems.

  • -p / --print: synchronous, blocking, returns now — correct for a pre-merge gate where the pipeline waits on the verdict.
  • Batch API: 50% cheaper, up to a 24h window, no latency SLA, and no multi-turn tool calling — correct for non-blocking overnight audits, never for a time-sensitive blocking check.

A pre-merge review must block, so use -p; reach for Batch only for offline, non-urgent jobs.

Quick Check: Wiring Up a CI Reviewer

You're adding Claude Code as a pre-merge review step in your pipeline. The job must run with no human present, return a result the next step can parse to set the check status, and avoid biased self-review of generated code. Which approach is correct?

Recap: Headless Claude Code

Key takeaways for non-interactive mode:

  • -p / --print is the required flag for headless CI execution — runs the loop to completion, prints to stdout, exits.
  • --output-format json (ideally with a schema) makes results parseable so the pipeline can act on them; require only always-present fields.
  • Run review in an isolated, fresh session — independent review beats biased same-session self-review.
  • Drive precision with explicit criteria and few-shot examples to minimize false positives.
  • Apply least-privilege tools for unattended runs; on re-runs report only new/unfixed issues.
  • Termination follows the stop reason, never text parsing; iteration caps are only a safety net.
  • Use -p for blocking pre-merge gates; reserve the Batch API for non-blocking, non-urgent jobs.

Frequently asked questions

Is the “Non-Interactive Mode” lesson free?

Yes — the full text of “Non-Interactive Mode” is free to read here on the web, and the Claude Architect course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Claude Architect course, upgrade to CoddyKit PRO.

What will I learn in “Non-Interactive Mode”?

The -p / --print flag for headless CI execution. You practise Claude Architect with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Claude Architect?

No prior experience is required. Claude Architect on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Non-Interactive Mode” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Claude Architect lesson?

Yes. Every Claude Architect lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Non-Interactive Mode
  2. Structured Output
  3. Session Isolation for Reviews
  4. Test Generation & Standards
← Back to Claude Architect