Non-Interactive Mode and CI/CD Integration
- Run Claude Code headlessly using the -p flag with structured output formats and appropriate permission modes
- Build multi-step automated pipelines using --continue, --resume, and session IDs for chained invocations
- Integrate Claude Code into GitHub Actions workflows using the claude-code-action and the Agent SDK approach
Claude as a Command-Line Tool
Everything you can do interactively in Claude Code, you can also do from a shell script. The -p flag (short for --print) runs Claude non-interactively: it takes your prompt, executes the task, prints the result, and exits. No conversation loop, no waiting for input, no terminal UI.
claude -p "Find and fix the bug in auth.py" --allowedTools "Read,Edit,Bash"
This makes Claude Code composable with any shell tooling. Pipe data in, redirect the response out, chain with jq, wrap in conditionals. Claude becomes just another command that fits into your existing scripts and pipelines.
The --bare Flag for CI Consistency
By default, claude -p loads the same context an interactive session would — hooks, skills, plugins, MCP servers, CLAUDE.md files, and auto memory from whatever is configured in the working directory and ~/.claude. On your local machine that's fine, but in CI it's a problem: a hook in a teammate's ~/.claude or an MCP server in the project's .mcp.json will run, giving you different behavior on different machines.
Add --bare to skip all local config discovery:
claude --bare -p "Summarize this file" --allowedTools "Read"
In bare mode, only flags you pass explicitly take effect. There are no hooks, no plugins, no CLAUDE.md, no auto memory. The same prompt produces the same result on every machine. --bare is the recommended mode for CI and scripted calls and will become the default for -p in a future release.
In bare mode, authentication must come from ANTHROPIC_API_KEY or an apiKeyHelper in JSON passed to --settings. Claude Code's OAuth keychain read is skipped.
Output Formats
Control how claude -p returns results with --output-format:
text(default): plain text response, suitable for human reading or simple string capturejson: structured JSON object with the result, session ID, and cost metadata includingtotal_cost_usdand per-model breakdownstream-json: newline-delimited JSON events for real-time streaming — each line is a typed event (stream_event,system,result)
The json format is particularly useful in scripts because it includes cost tracking per invocation and a session ID for continuation:
result=$(claude --bare -p "Summarize this project" --output-format json)
echo "$result" | jq -r '.result'
echo "$result" | jq -r '.total_cost_usd'
For CI pipelines that need to extract specific fields, pair --output-format json with a JSON schema using --json-schema to get structured output in the structured_output field.
Permissions for Headless Runs
Interactive permission prompts don't work in non-interactive mode — there's no one to answer them. Decide before running how to handle permissions:
Use --allowedTools to pre-approve specific tools by name:
claude -p "Run the test suite and fix failures" --allowedTools "Bash,Read,Edit"
Use --permission-mode acceptEdits to auto-approve all file edits and common filesystem commands:
claude -p "Apply the lint fixes" --permission-mode acceptEdits
Use --permission-mode bypassPermissions in isolated containers where you accept that Claude can execute without restriction:
claude --bare -p "Run full build and fix errors" --permission-mode bypassPermissions
In non-interactive mode, if Claude tries to call a tool that isn't permitted, the run aborts rather than waiting for approval. Design your --allowedTools list carefully before running in CI to avoid partial executions.
Multi-Step Pipelines with --continue
For tasks that build on each other, use --continue to chain invocations against the same conversation history:
# First request
claude --bare -p "Review this codebase for performance issues"
# Continue in the same conversation
claude --bare -p "Now focus specifically on the database queries" --continue
claude --bare -p "Generate a prioritized list of all issues found" --continue
Each invocation picks up where the last one left off. --continue uses the most recent conversation in the current directory. To continue a specific session, capture the session ID from the JSON output and pass it with --resume:
session_id=$(claude --bare -p "Start a code review" --output-format json | jq -r '.session_id')
claude --bare -p "Now check security vulnerabilities" --resume "$session_id"
Session IDs are scoped to the current project directory and its git worktrees.
GitHub Actions Integration
Claude Code integrates with GitHub Actions through the claude-code-action, which handles authentication, installs Claude Code, and runs your prompt in the workflow environment. The action exposes Claude's response as an output variable you can use in subsequent steps.
A minimal code review action looks like this:
- uses: anthropics/claude-code-action@v1
with:
prompt: |
Review the PR diff for correctness issues.
Focus on security, null handling, and error paths.
allowed_tools: "Read,Bash(git diff *)"
permission_mode: "dontAsk"
For workflows where Claude needs to push commits or open PRs, add the appropriate GitHub token permissions and include Bash(git *) and Bash(gh *) in your allowed tools.
When -p vs Cloud Routines
Both claude -p and cloud Routines run Claude autonomously without interactive sessions, but they represent different ownership models. With claude -p, your infrastructure (your CI server, your cron job, your script) calls Claude. You control when it runs, what context it receives, and what happens with the output. With cloud Routines, Anthropic's infrastructure runs Claude on your behalf — you configure the trigger, the prompt, and the connectors, and the cloud handles scheduling and execution.
Use -p when you already have CI infrastructure and want to add Claude to it. Use Routines when you want Claude to react to GitHub events, trigger from an API call, or run reliably without any infrastructure of your own.
- -p makes Claude Code a composable CLI tool — pipe data in, capture structured JSON output, chain with jq and shell scripts, and embed Claude in any existing pipeline as a standard command
- --bare skips local config for CI consistency — hooks, plugins, MCP servers, and CLAUDE.md files are not loaded, producing the same result on every machine regardless of individual developer settings
- --output-format json includes cost metadata — total_cost_usd and session_id in the response let scripts track spend per invocation and chain multi-step pipelines by session
- Pre-approve permissions before the run, not during it — --allowedTools and --permission-mode are set at invocation time because there is no one to answer prompts mid-run in non-interactive mode
- Routines differ from -p in who owns the infrastructure — -p embeds Claude in your CI pipeline, Routines are Anthropic's infrastructure running Claude on your behalf triggered by schedules, API calls, or GitHub events