Running Claude Code in CI: Headless Mode & GitHub Actions
Claude Code without the terminal — claude -p flags, JSON and structured output, safe permission scoping, and the official GitHub Action responding to @claude.
Claude Code runs headless with claude -p — script it like any CLI, get machine-readable results with --output-format json or --json-schema, and scope it with --allowedTools and --permission-mode. In GitHub Actions, claude /install-github-app wires up anthropics/claude-code-action@v1, which answers @claude mentions or runs prompts on any workflow trigger.
Steps at a glance
- Prove the task headless, locally. Run claude -p "your task" in the repo before touching CI. If it needs interactive clarification locally, it will fail in CI — tighten the prompt until one shot works.
- Pick the output format. Default is plain text. Use --output-format json for scripting (result, session_id, total_cost_usd, usage), stream-json for live token streams, or --json-schema '<schema>' when downstream code consumes the answer.
- Scope permissions for unattended runs. Pass --allowedTools with the narrowest set that works, e.g. "Read,Edit,Bash(npm run test:*)", plus --max-turns as a circuit breaker. Add --bare for speed and determinism when project hooks/plugins/CLAUDE.md aren't needed.
- Install the GitHub app. Run claude /install-github-app from the repo — it installs the GitHub App, sets the ANTHROPIC_API_KEY secret, and scaffolds the workflow file for you.
- Or write the workflow by hand. Add a job using anthropics/claude-code-action@v1 with anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}. Give it a prompt input for automatic runs, or omit it to respond to @claude mentions.
- Tune with claude_args. The action forwards CLI flags via claude_args (e.g. "--max-turns 10 --model claude-sonnet-4-6"), and can load plugins and MCP servers — same knobs as local headless runs.
Key takeaways
- claude -p "prompt" is the whole headless API: same agent, no UI. Pipe data in (cat log.txt | claude -p "…"), get text, JSON (with cost and session id), or streaming JSON out.
- --json-schema turns Claude Code into a structured-output tool — the result includes a validated structured_output field, no parsing prompts needed.
- Scope CI runs explicitly: --allowedTools "Read,Edit,Bash(npm test:*)", --permission-mode, --max-turns. CI is also where --bare shines: skip hooks, plugins, CLAUDE.md, and MCP discovery for fast, deterministic startup.
- The GitHub Action (anthropics/claude-code-action@v1) auto-detects its mode: with a prompt input it runs immediately; without one it responds to @claude mentions on issues and PRs.
- It can write code and open PRs but deliberately can't approve them — keep a human on the merge button.
Everything Claude Code does interactively, it can do unattended: triage an issue, fix a failing test, review a PR, draft release notes on a schedule. The interactive session is one frontend; this guide covers the other two — the headless CLI and the GitHub Action — and the permission discipline that makes unattended runs safe.
Headless mode: claude -p
claude -p "Find and fix the failing test in auth.test.ts"That's the whole interface. The full agent runs — searching files, editing, executing commands under your permission rules — and prints the result. It composes like a Unix tool:
cat error.log | claude -p "Explain the root cause in two sentences"Output formats are where headless gets practical:
--output-format json— the result plus metadata your script wants:result,session_id,usage, andtotal_cost_usd(track spend per CI run).--output-format stream-json— newline-delimited events for live streaming.--json-schema '<schema>'— enforce a shape; the response includes a validatedstructured_outputfield. Extraction tasks stop being prompt-and-pray.
Session flags carry over from interactive use: --continue resumes the most recent session in the directory, --resume <id> picks a specific one — so a multi-step pipeline can keep one conversation across steps.
Scoping flags are the safety story:
claude -p "Fix the lint errors" \
--allowedTools "Read,Edit,Bash(npm run lint:*)" \
--permission-mode acceptEdits \
--max-turns 10--allowedTools/--disallowedTools pre-approve exactly what the run may do (same rule syntax as settings), and --max-turns is the circuit breaker. One more flag earns its keep in CI: --bare skips hooks, skills, plugins, CLAUDE.md, and MCP auto-discovery for a fast, deterministic start — then you add back only what the job needs via --settings, --mcp-config, or --append-system-prompt. Auth in CI is ANTHROPIC_API_KEY (or Bedrock/Vertex credentials); piped stdin is capped at 10MB; transient API errors retry automatically.
The GitHub Action
The official integration is anthropics/claude-code-action@v1, and the fastest setup is one command from the repo:
claude /install-github-appIt installs the GitHub App, stores the ANTHROPIC_API_KEY secret, and scaffolds the workflow. The minimal file it produces looks like:
name: Claude Code
on:
issue_comment:
types: [created]
jobs:
claude:
runs-on: ubuntu-latest
steps:
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}The action auto-detects its mode: with no prompt input, it listens for @claude mentions on issues, PRs, and review comments — "@claude fix the type error in this file" gets a commit on a branch and a PR. With a prompt input, it runs immediately on whatever trigger you chose, which is how you build scheduled jobs (nightly dependency audit), PR-opened reviewers, or release-notes generators.
Tuning happens through claude_args, which forwards the same CLI flags you proved out locally:
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: "Review this PR for security issues and comment your findings"
claude_args: "--max-turns 12 --model claude-sonnet-4-6"It can also load plugins and MCP servers (plugins:, plugin_marketplaces: inputs), run skills with prompt: "/skill-name", and authenticate via Bedrock or Vertex (use_bedrock / use_vertex with OIDC) instead of a static key.
NOTE
Upgrading from the beta? @beta became @v1, direct_prompt is now prompt, and mode is gone (auto-detected). max_turns/model moved into claude_args.
The safety model for unattended runs
A CI agent is code with write access to your repo. The discipline:
- Minimum tools. The narrowest
--allowedToolsthat completes the task. A reviewer needsReadand a comment path — notBash. - Bounded runs.
--max-turnsalways; treat a hit limit as a failed job, not a retry loop. - Trusted triggers only.
@claudementions are gated by the App's permissions, but be deliberate about workflows that run on fork PRs with secrets in scope. - Human merge gate. The action deliberately cannot approve PRs — it writes code, you keep review. Don't engineer around that.
- Same guardrails as local. Permission rules and hooks checked into the repo apply to CI runs too — a deny-rule on secrets protects the bot exactly as it protects you.
TIP
The Setup Claude CI command scaffolds all of this — workflow file, secret checklist, scoped permissions — from a one-line description of what you want the bot to do.
When a workflow outgrows YAML — multi-step pipelines, custom tools, your own orchestration — the same engine is available as a library: that's the Claude Agent SDK.
Frequently asked questions
- How do I run Claude Code in GitHub Actions?
- Use the official action: anthropics/claude-code-action@v1. The fastest setup is running claude /install-github-app locally — it installs the GitHub App, stores your ANTHROPIC_API_KEY secret, and creates the workflow. After that, commenting @claude on an issue or PR triggers it, or you can give the action a prompt to run on any workflow event.
- What is headless mode in Claude Code?
- The -p (print) flag: claude -p "task" runs the full agent — tools, file edits, command execution — without the interactive UI, then prints the result and exits. It's the same engine the GitHub Action and the Claude Agent SDK drive, and it composes like any CLI: pipe input in, choose text or JSON out, script it in CI.
- How do I get structured/JSON output from Claude Code?
- --output-format json wraps the run in JSON with result, session_id, usage, and total_cost_usd. To enforce a shape, pass --json-schema with a JSON Schema — the response then carries a validated structured_output field. For token-by-token processing, use --output-format stream-json.
- Is it safe to run Claude Code unattended in CI?
- Treat it like any code with repo write access: pin --allowedTools to the minimum, set --max-turns, run on trusted triggers (not arbitrary fork PRs), and scope the runner's credentials. The action can't approve PRs by design, so a human review gate stays intact. Permission rules and hooks apply in CI exactly as they do locally.
- Can I use Bedrock or Vertex instead of the Anthropic API in CI?
- Yes — the action accepts use_bedrock: "true" or use_vertex: "true", authenticating via GitHub OIDC with an AWS IAM role or GCP Workload Identity Federation instead of a static API key.
Related
- Setup Claude CIWire Claude Code into this repo's CI the safe way — install the GitHub App or scaffold the workflow YAML, scope permissions to the minimum, set secrets correctly, and verify with a real trigger.
- Building Agents with the Claude Agent SDKA working tutorial for the Claude Agent SDK in TypeScript and Python — query(), tool permissions, custom in-process MCP tools, subagents, hooks, and auth.
- Claude Code Settings & Permissions: settings.json ExplainedEvery Claude Code settings file and which one wins, the permission-rule syntax with its Bash matching gotchas, permission modes, and a safe starter settings.json.
- Claude Code Hooks: Automate Formatting, Tests, and GuardrailsHow Claude Code hooks work — the major hook events, the settings.json configuration shape, exit codes and JSON output, plus three hooks worth copying.
- Adding MCP Servers to Claude Code: Local, Remote, and Project-ScopedThe complete claude mcp add reference — stdio vs HTTP transports, local/project/user scopes, .mcp.json with env expansion, OAuth via /mcp, and the gotchas.
- Create PRPush the current branch and open a GitHub pull request with a generated title and body.
- Review PRReview a pull request for correctness, security, and style, and summarize findings.
- Claude CodeAnthropic’s official agentic coding tool that runs in the terminal, IDE, and web.
- Best AI Code Review Tools in 2026The AI code reviewers worth running in 2026 — CodeRabbit, Greptile, and Qodo compared, plus the open-source PR-Agent and when Copilot's built-in review is enough.
- Claude Code Troubleshooting: Fixes for the Most Common ProblemsPractical fixes for the Claude Code issues people actually hit — install and auth failures, context-limit errors, MCP servers that won't connect, permission loops, and CI quirks.
- Github MCP ServerGitHub's official MCP server — repos, issues, PRs, Actions, and security data for your agent, as a free hosted remote or a local Docker server.
- GreptileAn AI code review agent that reviews pull requests with full-codebase context — catching multi-file logical bugs and learning your team's standards.