Headless mode is where configuration mistakes become security incidents — there is no human to approve a prompt. Build a CI job that reviews a diff, and constrain it so the worst case is a bad comment rather than a bad commit.
What to build
- Write a CI step invoking Claude Code non-interactively with -p and structured JSON output.
- Grant a deny-by-default permission set: read and analyse, no writes, no network beyond what is required.
- Feed it the PR diff and a rubric.
- Parse the JSON output and post findings as a comment.
- Add a PreToolUse hook as a second layer that hard-blocks writes outside a temp directory.
- Attempt to make the job write to the repo, and confirm both layers hold.
- Handle the non-zero exit path so a failed review does not silently pass the build.
Done when
- The job cannot modify repository files, verified by trying.
- Output is parsed as structured data rather than scraped from prose.
- A model failure fails the step visibly instead of passing quietly.
- No credentials are passed in a way that would appear in logs.
If you want to go further
- Add .mcp.json project servers and scope which ones CI may reach.
The trap this exercise teaches
Before you start
The theory behind this build is covered in MCP config and CI/CD workflows. If any step below is unfamiliar, read that first — the exercise assumes it. Primary source: Claude Code Docs — Headless.
Check yourself against the exam
This exercise sits in Domain 2, which is 20% of the CCAR‑F exam. Once you have built it, run a domain drill in the study app and see whether the questions read differently.