Claude Code in CI/CD: non-interactive -p mode and GitHub Actions
Claude Code can run without a UI: it takes a task via -p, does the work and exits. The documented flags and a working workflow for pull request reviews.
5 min · · development · автоматизация
Claude Code in CI pays off for tasks that repeat on every commit: reviewing a diff, explaining a failed build, drafting a PR description. Non-interactive mode -p handles this: Claude Code takes a prompt, does the work, prints the result and exits. Below are the flags from the official docs (Run Claude Code programmatically and the CLI reference) and a working GitHub Actions workflow with a Zukko key.
Non-interactive mode: the -p flag
claude -p "What does the auth module do?"-p (or --print) runs Claude Code without the interactive UI. It reads stdin, so you can pipe data in:
cat build-error.txt | claude -p "concisely explain the root cause of this build error" > output.txtPiped stdin is capped at 10 MB. For larger inputs, write the content to a file and reference the path in the prompt.
Output format
--output-format takes three values:
text— plain text (default);json— JSON withresult(the response text),session_id, usage data andtotal_cost_usd;stream-json— newline-delimited JSON events (use with--verbose).
There is no markdown format. If you want a Markdown report, ask for one in the prompt and pull the text out of result:
claude -p "Summarize this project" --output-format json | jq -r '.result'For strict structure, use --json-schema; the schema-conforming answer arrives in structured_output.
total_cost_usd is a client-side estimate based on the prices Claude Code knows about. Through a gateway it won't match the actual charge, so check real spend on the Usage page of your Zukko dashboard.
Permissions: nobody is there to click "Yes"
In CI nobody can answer permission prompts, so set them up front:
--allowedTools "Read,Edit,Bash"— tools that run without prompting. Rule syntax works too:"Bash(git diff *)"allows only commands starting withgit diff;--permission-mode acceptEdits— file edits and common filesystem commands without prompting;--permission-mode dontAsk— denies everything that would need approval unless explicitly allowed. Good for locked-down runs;--max-turns 10— caps the number of agent turns;--max-budget-usd 1— stops once spend reaches the amount (based on the same client-side estimate).
--bare skips auto-discovery of hooks, skills, subagents, MCP servers and CLAUDE.md. The docs recommend it for scripts so results don't depend on the machine's setup. Before you use it in CI, check locally that a --bare run authenticates through your gateway.
Without --bare, -p runs the hooks in the project's .claude/settings.json and connects servers from .mcp.json without asking. For PRs from forks, that's a reason not to give the workflow more rights than it needs.
GitHub Actions workflow: pull request review
.github/workflows/claude-review.yml:
name: Claude Code review
on:
pull_request:
branches: [main]
permissions:
contents: read
pull-requests: write
jobs:
review:
runs-on: ubuntu-latest
timeout-minutes: 15What matters here:
- The installer puts
claudein~/.local/bin; theGITHUB_PATHline makes it available in later steps.npm install -g @anthropic-ai/claude-codeworks too. - The key lives in a repository secret: Settings → Secrets and variables → Actions → New repository secret, named
ZUKKO_API_KEY. ANTHROPIC_BASE_URLhas no/v1, and the key goes inANTHROPIC_AUTH_TOKEN.- The agent may only read files (
--allowedTools "Read"); the diff is already in a file. A separate step posts the comment withgh, not the agent. - The
permissionsblock limits the workflow to reading code and writing PR comments.
By default GitHub doesn't pass secrets to workflows triggered by PRs from forks. In public repositories that's expected behavior, not a misconfiguration.
Anthropic also publishes a ready-made action, anthropics/claude-code-action@v1, which takes CLI flags through its claude_args input. Its docs describe authentication with an Anthropic API key or a subscription token. If you want to use it with a gateway, check the action's README first. The workflow above doesn't depend on the action.
A separate Zukko key for CI
Create a CI-only key in your dashboard:
- a clear name such as
ci-claude-review; - daily and monthly limits in dollars;
- an allowed model list (
allowed_models), for example onlyclaude-sonnet-5.
If the workflow asks for another model, the gateway returns 403 model_not_allowed_for_key. Insufficient balance gives 402; too many requests gives 429. A separate key is easy to revoke and keeps CI spend apart from yours.
A worked estimate. Say one review run sends 150,000 input tokens (the diff, files it reads, the system prompt) and receives 5,000 output tokens. On claude-sonnet-5 ($0.3 per 1M for both input and output): (150,000 + 5,000) × $0.3 / 1,000,000 ≈ $0.047. At 20 PRs a day, that's about $0.93. Real numbers depend on diff size and the number of turns; check them on the Usage page. A caveat about caching: vendors charge about 10% of the input price for prompt-cache reads, while Zukko bills cached tokens at the normal input price. For agent runs with a large, repeated context, the real gap versus official pricing is smaller than a straight price comparison suggests.
For the current model list, call GET https://api.zukko.pro/v1/models or open the Models page in your dashboard. The basic Claude Code setup is in the Zukko docs; error codes and key limits are on the Key limits and cache page.
Common problems
The agent "hangs" or changes nothing
Most likely the tool it needs isn't allowed: in -p mode with no permission host, permission requests are denied. Add the tool to --allowedTools or set --permission-mode.
Error 401
Check that the secret name matches the workflow and the key has no stray spaces. Make sure you're using ANTHROPIC_AUTH_TOKEN.
The run stopped at the turn limit
--max-turns exits with an error when the limit is reached. Raise it or narrow the task.
FAQ
Can I continue the session from a previous step?
Yes: claude -p --continue "..." continues the most recent conversation in the current directory. For a specific session use --resume <session_id>, taking session_id from the JSON output.
How do I set the model in CI?
With ANTHROPIC_MODEL in the env block, or with --model claude-sonnet-5. The flag takes precedence.
Can the agent commit fixes itself?
It can if you allow the commands it needs, for example --allowedTools "Bash(git diff *),Bash(git commit *)", and give the workflow contents: write. For reviews it's safer to keep the agent read-only.
Do subagents and MCP work in -p mode?
Yes, unless you pass --bare. You can pass servers explicitly with --mcp-config and subagents with --agents.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- Translating subtitles with a neural network: SRT without broken timecodesThe main risk when translating SRT with a neural network is a broken file structure. A scheme where timecodes never reach the model, and a Python script with validation.
- Editing texts with a neural network: proofreading, style and cuttingDifferent kinds of editing need different prompts. Wording for proofreading, style and cutting, how to get edits with explanations and how not to lose the author's voice.
- A neural network for writing scripts: Bash, PowerShell and PythonA model writes scripts for routine fast, but running them blindly is risky. How to state the task, demand a safe dry-run mode and check the result before launch.
- Dify in Docker: installation, first-run setup and connecting modelsInstall Dify with Docker Compose, create the admin account and connect Claude, GPT and DeepSeek models on one key. Plus what to do when containers will not start.