Skip to content

Run Claude Code in CI with claude -p without it hanging

How to run Claude Code non-interactively with claude -p, which flags a CI job needs, why most unattended runs stall on a permission prompt, and how to cap what a run can spend.

Short answer: run claude -p with --output-format json, a permission mode and an --allowedTools list that cover everything the job needs, and a --max-budget-usd cap. Most stalled runs are waiting for a permission prompt nobody can answer.

claude -p runs Claude Code with no conversation: one prompt in, one answer out, then it exits. That is what you want in a CI job, a git hook or a cron script. It is also where most first attempts go wrong, because the defaults are built for a person sitting at the keyboard.

What is the basic command?

claude -p 'Review the diff on this branch and list anything that would break' \
  --output-format json \
  --permission-mode plan \
  --allowedTools 'Read Grep Glob' \
  --max-budget-usd 2

Each flag answers a question nobody will be around to answer:

FlagWhat it settles
-pPrint mode: no conversation, exit when done
--output-formattext for a person, json for one object a script reads, stream-json for one object per line as it goes
--permission-modeWhat it may do without asking
--allowedTools / --disallowedToolsExactly which tools the job gets
--max-budget-usdA spend cap for the run
--append-system-promptExtra instructions for this run only
--add-dirAnother directory it may work in
--modelWhich model, instead of your default

Why does my headless Claude Code run hang?

Almost always: the permission mode asks. In normal use Claude Code asks before many tool calls. With nobody at the terminal, the first question waits forever, or the call is refused and the job does nothing useful.

Pick a mode that does not ask, and allow exactly what the job needs:

  • plan: it reads and reasons, changes nothing. Right for reviews and reports
  • acceptEdits: it may edit files without asking. Right for a job that fixes formatting or updates snapshots
  • bypassPermissions: nothing asks and nothing is checked. Only somewhere disposable, with no network and nothing you mind losing. A deny rule still applies even here

How do you cap the spend?

A run on a timer that loops does so at full speed and bills for every turn. --max-budget-usd stops it at a number you chose. Put it on every scheduled or CI run, even a generous one.

Which smaller traps catch people?

Shell variables in the prompt. In double quotes, $BRANCH in your prompt is expanded by the shell before Claude sees it. Single quotes keep the text as written. Use whichever you mean, on purpose.

stream-json without --verbose. You get the events, not the whole stream. Usually that is what you want, but it is worth knowing you chose it.

How do you read the result in a script?

With --output-format json the answer comes back as one JSON object, so a CI step can parse it and fail the build, post a comment or open an issue. Keep the prompt specific about the shape you want back ("a list of findings, each with a file and a line") so the script has something stable to read.

How do you schedule it safely?

A scheduled run is a headless run with a cron expression in front of it. Before you commit the schedule, check how often it actually fires: */5 * * * * is about 8,640 runs a month, and a one-character typo can be the difference between hourly and every minute.

Where can you check this?

Can you build and check the command first?

Config Studio for Claude Code has a Headless runs editor that writes the whole command, every flag spelled out, and warns about the combinations above. Its Would this run unattended? check answers "schedulable" only when the run is bounded, nothing asks and there is a prompt. The Profile: unattended and CI starter pack sets the whole posture at once. The full walkthrough is in Run Claude Code unattended.

The tool

Do it in your browser.

Claude Code

Config Studio for Claude Code

Every file Claude Code reads, explained: what each setting does, where it lives, which file wins, and an editor that writes it for you.

Keep reading

More from the blog.

Every post

Contact