- Step 10 of 12 in the series "Claude Code and Codex, in order"
Headless and CI Use of Coding Agents

On your laptop, a coding agent stops and asks before it runs a command. In CI, the system that runs checks automatically on every pull request, nobody is there to answer. So you decide the answers ahead of time: which tools run without asking, which are refused, and which secrets the agent can see. Get that right and the rest is flags.
Below are the flags for running Claude Code and Codex without a person at the keyboard (often called headless), the GitHub integrations each vendor offers, how to handle keys, and a read-only review workflow for each tool. Everything is from the vendor docs as of September 26, 2026, starting with Claude Code's non-interactive mode page. The two workflows combine documented settings, and the page says where they go beyond a copied example.
Claude Code in a script
Add -p to any claude command and it runs once, prints the result, and exits (non-interactive docs):
claude -p "What does the auth module do?"
You can pipe text into it like any command-line tool. When something fails, it exits with a non-zero code, so a script can tell whether it worked. These are the flags that matter in automation:
| Flag | What it does |
|---|---|
--allowedTools "Read,Edit,Bash(git diff *)" | Pre-approves these tools. Uses permission-rule syntax. The trailing space-star allows any command that starts with that prefix |
--permission-mode dontAsk | Denies anything that would prompt, except what allow rules cover. The docs call it useful for locked-down CI |
--permission-mode acceptEdits | Writes files without prompting. Other shell commands still need an allow rule |
--output-format json | Returns the result, session ID, and cost estimate as JSON |
--json-schema '...' | Forces the result into your schema, in a structured_output field |
--bare | Skips hooks, skills, plugins, MCP servers, memory, and CLAUDE.md from the machine and repo |
--resume "$session_id" | Continues a specific earlier run |
--bare is worth a closer look. Without it, the docs say a -p session runs the hooks in the repo's .claude/settings.json and connects the servers listed in its .mcp.json. It does this with no trust prompt and no approval per server, even in a folder you've never trusted.
In CI, that means whoever wrote the branch being checked decides what runs. The docs recommend --bare for scripted calls and say it will become the default for -p in a future release. Bare mode also ignores your subscription login and needs ANTHROPIC_API_KEY.
One example from the docs shows what a useful script check looks like. It pipes a diff in, so Claude doesn't need permission to run Bash just to read it:
git diff main | claude -p "you are a typo linter. for each typo in this diff, report filename:line on one line and the issue on the next. return nothing else."
Codex in a script
codex exec is the Codex version (Codex non-interactive docs). Progress messages go to stderr, and only the final message goes to stdout, so you can capture the answer on its own.
The default is the important part. codex exec runs in a read-only sandbox, a fenced-off space where it can look but not change files. You turn on writes with --sandbox workspace-write, or --sandbox danger-full-access for broader access, which the docs reserve for controlled environments. The older --full-auto flag is deprecated and prints a warning.
Other flags you'll use:
--jsonfor a stream of events, one JSON object per line-oor--output-last-messageto write the final message to a file--output-schemato make the answer match a JSON Schema--ephemeralto skip saving session filescodex exec resume --lastto continue the last run
For logging in from CI, the docs show setting CODEX_API_KEY for that one command. For GitHub Actions they point to the Codex action instead, which keeps the key behind a proxy.
Cursor's CLI follows the same pattern: agent -p for print mode, and changes are only proposed unless you add --force (Cursor headless docs).
The GitHub integrations
Claude Code GitHub Actions. The action is anthropics/claude-code-action@v1 (docs). The quick setup is /install-github-app inside Claude Code. It installs the Claude GitHub app, stores the secret, and opens a pull request with the workflow.
The action has two modes. With no prompt input, Claude waits for someone to mention @claude in an issue or pull request comment and replies there. With a prompt, it runs on whatever event starts the workflow.
Two checks run before Claude starts. The person who triggered the run needs write access to the repo, and bots are turned away unless they're listed in allowed_bots. On public repositories, GitHub doesn't hand secrets to runs started by pull requests from forks, so reviews only run on branches in the same repository.
The app's permissions are broad. Installing the official Claude GitHub app grants read and write on Actions, Checks, Contents, Discussions, Issues, Pull requests, Repository hooks, and Workflows, because one app serves several Claude features. GitHub doesn't let you accept only some of them. For organizations that only need the action, the docs describe making your own GitHub app with just Contents, Issues, and Pull requests.
Codex. Codex has two routes. The first is Codex cloud, which runs tasks in cloud environments and returns diffs or pull requests. You can start a task from the web, the IDE, the CLI, or by mentioning @codex on GitHub, and @codex review asks for a code review (Codex cloud docs). By default, Codex blocks internet access while the agent works. Setup scripts still get internet so dependencies can install (internet access docs).
The second route is openai/codex-action@v1, which runs codex exec inside your own workflow (openai/codex-action).
Secrets and permissions
The docs from both vendors agree on the basics, and one detail from each is easy to miss.
- Store keys as repository or organization secrets. Never commit them. Claude's action takes
ANTHROPIC_API_KEYorCLAUDE_CODE_OAUTH_TOKEN(a subscription token fromclaude setup-token). For a secret shared across an organization, the docs recommend an API key, because an OAuth token is tied to one person's subscription. - Set the workflow's
permissionsblock to the minimum. A review job needscontents: read. Only jobs that push needcontents: write. - Claude:
id-token: writeis required for the action's default GitHub app authentication, per the docs' own examples. - Codex: the key is readable in the job. The codex-action README warns that the API key can still be reached through the proxy even in read-only mode. It recommends against running on pull requests you don't trust. By default it uses a
drop-sudosetting that takes away admin rights from the job's user before Codex starts. - Cap the run. Claude's docs suggest
--max-turnsinclaude_args, workflow timeouts, and GitHub's concurrency controls so a run can't keep spending. Runs on an API key bill at API rates plus your Actions minutes.
Worked workflow: a read-only rules check on pull requests
Here's the goal. On every pull request, the agent reads the changes against the base branch, checks them against the repo's instruction file, and writes what it finds to the job log. It can't edit, push, or comment.
This example was put together for this page. The settings and permission values come from the docs. The prompt and tool list were written here.
Claude Code version. Save as .github/workflows/agent-rules-check.yml:
name: Agent rules check
on:
pull_request:
types: [opened, synchronize, ready_for_review]
concurrency:
group: agent-rules-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
check:
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
pull-requests: read
id-token: write
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: |
Compare this pull request's changes to origin/${{ github.base_ref }}
with git diff. Check them against the rules in CLAUDE.md.
List each rule the change breaks, with file and line.
If it breaks none, say so in one line. Do not edit files.
claude_args: |
--max-turns 10
--allowedTools "Read,Grep,Glob,Bash(git diff *),Bash(git log *)"
What each choice does:
fetch-depth: 0downloads the base branch history sogit diffhas something to compare against. The docs' examples usefetch-depth: 1, which only grabs the latest commit. That's enough for replying to a mention, but not for a diff against the base.- The
permissionsblock grants read only, plus theid-token: writethe action needs to authenticate. --allowedToolslists read tools and two git prefixes. The docs say that in automation mode Claude has no shell access until you grant the tools the prompt needs, so nothing else runs.concurrencycancels an old run when new commits land, andtimeout-minutesstops one that gets stuck.
Findings show up in the workflow run log, which is the documented default for automation mode. To post a comment instead, the docs' code-review example shows the extra tool and flag it needs.
Codex version. Here's the same check with the Codex action. The checkout and fetch steps follow the action's README example. :read-only is the permission profile the README names for read-only workflows:
name: Codex rules check
on:
pull_request:
types: [opened, synchronize]
jobs:
check:
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- uses: actions/checkout@v5
with:
ref: refs/pull/${{ github.event.pull_request.number }}/merge
persist-credentials: false
- name: Fetch base and head
env:
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: |
git fetch --no-tags origin "$PR_BASE_REF" "+refs/pull/$PR_NUMBER/head"
- uses: openai/codex-action@v1
with:
openai-api-key: ${{ secrets.OPENAI_API_KEY }}
permission-profile: ":read-only"
prompt: |
Compare the changes between origin/${{ github.base_ref }} and HEAD.
Check them against the rules in AGENTS.md. List each rule the
change breaks, with file and line. Do not edit files.
The README notes that permission profiles are beta and need Codex CLI 0.138.0 or later, so don't pin an older codex-version with this input. The final message is available as the step's final-message output if you want a later job to post it.
What to automate first
Start read-only. A check that only writes to the log costs little when it's wrong. A week of its output tells you whether it's worth letting it comment, and later push. The diff review guide in this series covers what to look for when it does start writing code. For deployment concerns beyond coding agents, deploying AI agents to production covers monitoring and rollback.
Previous in the series: Skills and reusable instructions for coding agents. Next: Codex vs Claude Code vs Cursor.


