Skip to content

Headless & CI

You tried to wire the agent into a script and the TUI got in the way. It wants to confirm permissions. It wants to draw a status bar. It’s expecting a human to type. The thing that’s effortless interactively is suddenly a fight against the loop you didn’t realise was assumed.

What you were trying to automate is the part the agent is great at when you’re driving it: triaging an incoming bug report, drafting a release-notes summary from a diff, sweeping the codebase for missing test coverage, generating a TL;DR of a long PR description. You’d love this to just happen. On the schedule. On the GitHub event. As part of CI. Without you sitting there.

Headless mode is the entry point with the human assumption removed. The same agent, the same skills, the same model - but invoked as a subprocess that takes input from stdin or a flag, produces output to stdout (often as structured JSON), and exits with a status code.

Now your nightly job, your GitHub Action, your pre-push git hook, your Slack /triage slash-handler - all of them can call the agent like any other command-line tool.

Every CLI in scope has that non-interactive surface: you pass a prompt, the agent runs its loop to completion, prints a result, and exits. There is no interactive TUI or live approval prompt; approval, sandbox, hook, and credential policy must be configured before the run. In other words: call it from a script, get a result back, and make the unattended posture explicit.

The shapes converge - all of them give you a run / exec / -p / --prompt subcommand - but the surrounding ecosystem (SDKs, GitHub Actions, structured-output formats, remote execution, async background agents) differs significantly. That’s usually what tips the decision when you’re choosing one for an automation.

Two tools go further than a local headless command. Copilot’s canonical headless surfaces are cloud agent (background, async, GitHub-native) and the copilot CLI - both non-IDE. Cursor ships three: cursor-agent headless, Cloud Agents (REST API), and Bugbot (PR reviewer).

Real-world examples of headless agent runs:

  • CI code review - on every PR, an Action runs the agent against the diff and posts findings as a PR comment. Catches the easy stuff before a human reviews.
  • Issue triage - incoming GitHub issue triggers a workflow that asks the agent to label it, link related issues, and ping the right code-owner.
  • Release notes - nightly, the agent reads the day’s merged PRs and drafts a CHANGELOG entry. Human edits before publishing.
  • Test-gap audits - scheduled job: “list every public function added this week that has no test.” Output goes to a Slack channel.
  • Doc freshness checks - weekly run that grep’s for TODO: verify markers and asks the agent to confirm each one against current code, opening issues for the stale ones.
  • Cron-style summaries - daily standup digest from git log, weekly velocity report, monthly tech-debt scan.
  • Embedded in tooling - a custom CLI in your repo (bin/team-tool review) that wraps the agent SDK for repeatable, parameterised flows.
  • Background PR work - assign a GitHub Issue to Copilot cloud agent, walk away, come back to a draft PR.

The test: if you’re describing the task to the agent in approximately the same shape every time, and the result is something a script could consume, it belongs in headless mode.

Watch the 2-minute version

Headless & CI. Watch on YouTube

Pick a task, an output format, and a permission posture, and the same CI job assembles into that tool’s command. Watch where the posture ends up: an allowlist flag, a sandbox tier, or a config file the command never mentions.

This builder covers five tools. Pi's headless and JSON modes are documented in the foundations headless chapter.

Task
Output
Posture
Claude Code, Review a PR diff, JSON, Read-only.
claude -p "Review the changes on this branch for regressions. Be terse." \
  --bare --allowedTools "Read,Bash(git diff *)" --permission-mode dontAsk \
  --output-format json
  • postureThe allowlist is the guardrail - tool patterns like Bash(git diff *) scope commands, not just tools. --bare skips auto-discovery of CLAUDE.md, hooks, and MCP servers so CI behaves deterministically, and dontAsk keeps the run from hanging on an approval no one will answer.
  • outputOne structured object with result, session_id, cost, and usage. Capture session_id if a later run should --resume this one.
  • beyondFirst-party CI: anthropics/claude-code-action@v1 wraps all of this in a GitHub Action - pass any of these flags via claude_args.
You want to… Reach for Not
Run the agent unattended from a script or CI job Headless / run / exec / --prompt Interactive TUI
Build a long-running custom automation around the agent SDK (Claude Agent SDK / Codex SDK / OpenCode SDK) Shelling out every time
Run the agent on a remote machine / sandboxed env Codex Cloud, OpenCode + Docker, a hosted Claude Agent SDK application, Cursor Cloud Agents Local headless alone
Get structured JSON output for scripts to parse --output-format json / --json / --format json Grepping plaintext
Resume a previous session non-interactively claude -c/--resume (Claude Code), codex exec resume (Codex - use this, not bare codex resume, for scripts), session APIs in SDKs Restarting from scratch
Run unattended and keep humans in the loop on risky actions Headless + tight permissions + hooks Headless with full access
Embed the agent inside another product SDK Wrapping the CLI binary
Trigger an agent from a GitHub Issue or @-mention Copilot cloud agent Polling for events from a local headless run

The TUI is for driving the agent. Headless mode is for the agent being driven by something else. SDKs are for the agent being part of a bigger program. Pick by how much orchestration you need around the call.

Showing: Claude Code pick a tab to change

Command: claude -p "<prompt>" (or claude --print "<prompt>").

Runs the agent loop until it produces a final answer, prints stdout, exits. Suitable for shell pipelines. From v2.1.302, -p runs with no permission mode set start in manual (default) mode: a tool call that needs approval is denied unless --allowedTools, a hook or a rule allows it, or you pass --permission-mode. Add --bare in CI so the run skips the host’s hooks, plugins, auto memory and CLAUDE.md.

CI integration: use the official Claude Code GitHub Action for the supported GitHub-native path. The Claude Agent SDK is a standalone embeddable package for applications that need programmatic control; if you use it in CI, your workflow still hosts and invokes that application.

Streaming output: --output-format json for structured output; --output-format stream-json for line-delimited streaming.

SDK packages:

  • npm: @anthropic-ai/claude-agent-sdk (renamed from @anthropic-ai/claude-code in late 2025)
  • PyPI: claude-agent-sdk
Aspect Claude Code Codex OpenCode Cursor Copilot Pi
Headless command claude -p codex exec opencode run cursor-agent -p copilot --prompt pi -p
Structured output --output-format json --json / --experimental-json + optional --output-schema --format json json, stream-json, --stream-partial-output --output-format json (JSONL) --mode json
Streaming output stream-json NDJSON (default with --json) line-delimited JSON via --format json stream-json / partial output --stream=on|off (default on) --mode json (streamed JSONL), or RPC mode
Session resume/fork -c/--continue, -r/--resume <id>, --fork-session (all headless) codex exec resume --last / resume <id>, codex exec fork <id>; bare resume and fork are interactive only -c/--continue, -s/--session <id>, --fork (undo/redo are TUI-only) --resume (CLI) --resume[=id], --continue pi -r, --session <id>, -c
Remote / async execution Agent SDK codex cloud exec Docker / self-hosted Cloud Agents API (REST) Cloud agent (background, GitHub-native) -
First-party CI integration Claude Code GitHub Action GitHub Action GitHub / GitLab integrations Bugbot (PR reviewer) GitHub Actions, cloud agent, PR review pi -p scripted into any CI runner
Programmatic SDK Claude Agent SDK Codex SDK OpenCode SDK Cloud Agents REST API GitHub REST/CLI surfaces; task dispatch depends on the documented Copilot surface Pi SDK + RPC mode
  • “Headless” in Claude Code (claude -p) is the same idea as Codex’s exec, OpenCode’s run, Cursor’s cursor-agent -p, and Copilot CLI’s --prompt - but each tool’s SDK or background-agent surface is the more powerful path for non-trivial automation.
  • Codex Cloud is not the same as “remote MCP” - Cloud runs the whole CLI remotely; remote MCP just connects a local CLI to a remote tool server.
  • Copilot cloud agent (background async PR work, formerly called Coding Agent) is a different surface from Copilot CLI headless (copilot --prompt). The older gh copilot GitHub-CLI extension was retired in October 2025 - don’t confuse it with either of the two live surfaces.
  • Cursor Cloud Agents (REST API, GitHub-native) ≠ cursor-agent headless (local CLI) ≠ Bugbot (PR reviewer service).

Start smaller than a GitHub Action. Take one task you already run by hand, invoke it once with your tool’s headless flag and JSON output, and read what lands on stdout - that tells you whether the automation wants a shell script, a scheduled job, or the SDK. Tighten permissions before you put it on a trigger: an unattended run has nobody left to say no.