CI/CD, GitHub Actions & Background Agents

Claude Code in the pipeline and on the cloud

Advanced 13 minBuilder
What you'll be able to do
  • Authenticate Claude Code in CI using CLAUDE_CODE_OAUTH_TOKEN from claude setup-token
  • Bound a headless run with --permission-mode dontAsk, --max-turns, and --max-budget-usd
  • Dispatch, monitor, and clean up background agents and the daemon supervisor that hosts them
  • Wire up PR autofix and scheduled cron routines that run on Anthropic's cloud
  • Move a live session between claude.ai and your terminal with remote control and teleport
At a glance

Run Claude Code without a human at the keyboard: authenticate in CI with a long-lived token, bound every headless run, dispatch and supervise background agents, schedule cron routines on Anthropic's cloud, and move sessions between the web and your terminal.

  1. 1The mental model: where the agent runs and who watches it
  2. 2CI authentication: a token, not a browser
  3. 3Bounding a headless run: three guardrails
  4. 4Background agents and the daemon supervisor
  5. 5PR workflows: autofix and resuming from a PR
  6. 6Scheduled routines on Anthropic's cloud
  7. 7Remote control and teleport: moving between web and terminal

The mental model: where the agent runs and who watches it

Interactive Claude Code assumes a human is present to approve edits and steer. Automation removes that human, so every unattended run needs two things the interactive session gave you for free: non-interactive auth (no browser login) and explicit bounds (so a runaway loop can't burn your CI minutes or your budget).

There are three places an unattended agent can live, and they differ in who supervises it:

Where it runsStarted bySupervised byUse it for
CI / headlessclaude -p in a GitHub Actions step or scriptThe CI runner itself (process exits, job ends)One-shot checks, fixes, code review gated by exit code
Background agentclaude --bg / Ctrl+B / /backgroundThe local daemon supervisor on your machineLong tasks you dispatch and check on later
Anthropic cloud--remote, /schedule, /autofix-prAnthropic's hosted runners (claude.ai)Cron routines, PR watching, web sessions you teleport in

The rest of this lesson walks each of these. The throughline: bounded, observable runs. You always know how to stop it, how much it can spend, and where to read its output.

Watch out

Claude Code needs a paid plan

Automation still consumes a real subscription or API quota. Claude Code is not on the free tier — you need Pro, Max, Team Premium, Enterprise, or a Console API key. From June 15, 2026, claude -p and Agent SDK usage on subscriptions draw from a separate monthly Agent SDK credit pool, distinct from your interactive limits.

CI authentication: a token, not a browser

Interactive login opens a browser. A CI runner has no browser, so you pre-mint a long-lived OAuth token and hand it to the runner as a secret.

Generate it once, on a machine where you're logged in:

bash
claude setup-token

This prints a one-year OAuth token scoped to inference. It is printed, never saved to disk — copy it immediately and store it in your CI provider's secret store (e.g. a GitHub Actions repository secret). It requires an active Claude subscription, and it does not work in --bare mode.

In the runner, expose it as the environment variable Claude Code reads in CI:

yaml
# .github/workflows/claude.yml
jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install Claude Code
        run: curl -fsSL https://claude.ai/install.sh | bash
      - name: Run agent
        env:
          CLAUDE_CODE_OAUTH_TOKEN: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
        run: |
          claude -p "Summarize what changed in this PR and flag risky diffs" \
            --permission-mode dontAsk --max-turns 6 --max-budget-usd 2.00

Why CLAUDE_CODE_OAUTH_TOKEN and not ANTHROPIC_API_KEY? Both work, but the OAuth token bills against your subscription, while an API key bills your Console account pay-as-you-go. Pick the one that matches how you want to pay. In the auth precedence order, CLAUDE_CODE_OAUTH_TOKEN sits just above interactive subscription OAuth, so setting it is enough — no /login needed.

Tip

Verify auth without a session

claude auth status prints your auth state (add --text for human-readable). It exits 0 when logged in and 1 when not, so you can gate a CI step on it before spending tokens.

Watch out

Never hardcode the token

Do not write the token into a workflow file, a committed .env, or a shell profile — a profile leaks it to every child process. Always inject it from the secret store at step scope, as in the env: block above.

Bounding a headless run: three guardrails

A headless agent with no human will keep working until it decides it's done — or until it loops. Three flags (all print-mode only, i.e. they require -p) put hard walls around it:

FlagWhat it capsBehavior at the limit
--permission-mode dontAskPermissions — auto-denies anything not in your allow rulesAny action that would normally ask becomes a deny; the agent can't escalate scope
--max-turns 3Agentic turnsExits with an error when the limit is reached
--max-budget-usd 5.00Dollars spent on API callsStops cleanly when spend hits the amount

Use them together. dontAsk is the key choice for CI: unlike bypassPermissions (which skips all checks and is only safe in a throwaway container), dontAsk is restrictive — it only permits what you've explicitly allowed and denies everything else, including actions that would otherwise prompt.

Pair dontAsk with an allowlist so the agent can actually do its job:

bash
claude -p "Fix the failing unit tests, then commit" \
  --permission-mode dontAsk \
  --allowedTools "Read" "Edit" "Bash(npm test *)" "Bash(git commit *)" \
  --max-turns 12 --max-budget-usd 3.00 \
  --output-format json

Add --output-format json (or stream-json) when a downstream step needs to parse the result, and --json-schema '{...}' when you want the output validated against a schema.

Key insight

dontAsk vs bypassPermissions

They sound similar but are opposites. dontAsk = deny by default, allow only your rules — safe for CI. bypassPermissions (= --dangerously-skip-permissions) = skip all checks — only for isolated containers/VMs with no network. Reach for dontAsk plus --allowedTools in pipelines.

Tip

Gate the pipeline on exit code

claude -p and claude ultrareview return exit 0/1, so a review or test-fix step naturally fails the job when something's wrong. --max-turns exiting with an error is a feature here: a stuck agent fails loudly instead of silently spending.

Background agents and the daemon supervisor

Background agents are for long tasks you want to fire and check on later from your own machine — not block your terminal waiting. Start one three ways:

  • claude --bg "<task>" — start from the shell, print the session ID, return immediately
  • Ctrl+B — background the current interactive session (or the running bash command)
  • /background (alias /bg) — detach the current session as a background agent

Once running, you manage the fleet from the shell:

CommandWhat it does
claude agentsOpen agent view to monitor/dispatch parallel sessions (--json to script, --cwd to filter)
claude logs <id>Print recent output from a session
claude attach <id>Attach to a running session in this terminal
claude stop <id>Stop a session (also claude kill)
claude respawn <id>Restart a stopped or running session, conversation intact (--all to restart every running one)
claude rm <id>Remove from the list — the transcript stays and is resumable via claude --resume

All of these are hosted by a single local process: the daemon supervisor. It must be running for background sessions to exist. Two commands keep you out of trouble:

bash
claude daemon status              # supervisor state, version, socket dir, worker count; exits 1 if down
claude daemon stop --any          # stop the supervisor and the sessions it hosts
claude daemon stop --any --keep-workers   # stop supervisor but leave agents running

respawn --all is the trick for picking up an updated Claude Code binary — it restarts every running agent on the new version without losing their conversations.

Note

Background tasks run shell commands too

claude --bg --exec 'pytest -x' runs a shell command as a PTY-backed background job instead of a Claude session — handy for kicking off a long build or test run you'll check with claude logs <id>.

Watch out

"Background service did not respond"

If agent view or claude agents reports an unresponsive supervisor, recover with claude daemon stop --any (add --keep-workers to preserve in-flight sessions), then re-open agent view to spin up a fresh supervisor.

PR workflows: autofix and resuming from a PR

/autofix-pr turns Claude into a CI watchdog for a branch's pull request. It watches the PR, and when CI fails or a reviewer leaves comments, it pushes fixes to the branch automatically — closing the iterate-on-feedback loop without you babysitting it.

text
/autofix-pr make sure all checks stay green and address review comments

It has two hard requirements: the gh CLI must be installed and authenticated (so Claude can read PR/CI state and push), and you need Claude on the web (claude.ai), because the watching runs on Anthropic's cloud rather than tying up your terminal.

The complementary command runs locally. When Claude creates a PR, it links the session to that PR automatically. Later, from any machine, resume that linked work:

bash
claude --from-pr 123
# or a full URL — GitHub, GitHub Enterprise, GitLab MR, or Bitbucket PR
claude --from-pr https://github.com/acme/app/pull/123

This pulls up the session(s) tied to that PR so you can keep working with full context, instead of re-explaining the change.

Tip

The autofix loop

/autofix-pr is the cloud-side mirror of the local Explore-Plan-Implement-Commit loop: push → CI runs → fail/review → Claude fixes → push again, until checks are green. Scope it with a clear prompt so it fixes your failures and doesn't wander.

Note

Sessions link automatically

You don't tag a session to a PR manually. When Claude opens the pull request, the link is recorded for you — --from-pr just looks it up by number or URL.

Scheduled routines on Anthropic's cloud

Some agents shouldn't wait for you to start them — a nightly dependency audit, a weekly changelog draft, a morning triage of new issues. /schedule and /routines create and manage cron agents that run on Anthropic's cloud, not your laptop. That means they fire on schedule even when your machine is asleep.

text
/schedule every weekday at 9am, summarize new issues opened overnight and post a triage list
/routines

/schedule [description] creates a routine from a natural-language schedule + task; /routines lists and manages the ones you've created. Because they run in the cloud, they pair naturally with /autofix-pr and --remote: the work happens server-side, and you check results from any surface — terminal, web, or the desktop app.

Key insight

Cloud cron vs local loop

Don't confuse /schedule with /loop. /loop [interval] [prompt] repeats a prompt only while your session is open on your machine. /schedule registers a cloud routine that runs independently on Anthropic's infrastructure on a cron schedule — survives reboots and closed laptops.

Remote control and teleport: moving between web and terminal

The same engine runs in your terminal and at claude.ai. These flags let a single session cross that boundary, so you can start work on one surface and continue on another.

Flag / commandWhat it does
claude --remote "<task>"Create a new web session on claude.ai with this task description
claude --remote-control "<name>" (--rc)Start an interactive local session that you can also drive from claude.ai or the Claude app
claude remote-control [name]Run a Remote Control server with no local interactive session
claude --teleport / /teleport (/tp)Pull a web session into your local terminal to keep going there

The two directions to keep straight:

  • --remote pushes a task out to the cloud (starts fresh on the web).
  • --teleport pulls an existing web session in to your terminal.
  • --remote-control keeps the session local but mirrors control to the web — useful when you start at your desk and want to nudge it from your phone.

This is what makes the cloud features practical: a /schedule routine or --remote task runs server-side, and when you want to take the wheel, --teleport brings it down to your terminal with full context.

Example

Start on web, finish in terminal

Kick off claude --remote "Migrate the auth module to the new SDK" from your phone on the train. At your desk, run claude --teleport, pick the session, and continue locally with your editor, tests, and debugger attached.

Try it: Wire a bounded autofix into CI

Build a safe, unattended pipeline end to end.

  1. Mint auth. On a logged-in machine, run claude setup-token. Add the printed token to your repo's secret store as CLAUDE_CODE_OAUTH_TOKEN. Do not paste it anywhere committed.
  2. Add a workflow. Create .github/workflows/claude.yml with a job that checks out the repo, installs Claude Code (curl -fsSL https://claude.ai/install.sh | bash), and runs a bounded headless command. Inject the token via an env: block at step scope.
  3. Bound it. Use claude -p "<task>" --permission-mode dontAsk --allowedTools "Read" "Edit" "Bash(npm test *)" "Bash(git commit *)" --max-turns 10 --max-budget-usd 2.00 --output-format json. Confirm the job fails (non-zero exit) when the agent can't finish.
  4. Verify the guardrails. Temporarily lower --max-turns to 1 and re-run; confirm it exits with an error rather than continuing.
  5. Add a watchdog (optional, needs gh + Claude on web). From an interactive session on a PR branch, run /autofix-pr keep checks green and address review comments, push a deliberately failing commit, and watch it push a fix.
  6. Schedule it (optional). Run /schedule every weekday at 9am, run the test suite and open an issue if anything is red, then /routines to confirm it registered.

Deliverable: a committed workflow file (token referenced only via secret), plus notes on which flag stopped the run in step 4 and why.

Key takeaways

  1. 1CI needs non-interactive auth: mint a one-year token with `claude setup-token`, store it as a secret, and expose it as `CLAUDE_CODE_OAUTH_TOKEN` (subscription billing) or use `ANTHROPIC_API_KEY` (Console billing).
  2. 2Bound every headless run with `--permission-mode dontAsk` (deny-by-default), `--max-turns`, and `--max-budget-usd` — all print-mode flags requiring `-p`.
  3. 3`dontAsk` is restrictive (allow only your rules); `bypassPermissions` skips all checks and is for throwaway containers only.
  4. 4Background agents (`claude --bg` / Ctrl+B / `/background`) are hosted by a local **daemon supervisor** that must be running; manage them with `claude agents/logs/attach/stop/respawn/rm` and `claude daemon status/stop --any`.
  5. 5`/autofix-pr` (needs `gh` CLI + Claude on web) watches a PR and pushes fixes on CI fail/review; `--from-pr` resumes the session linked to a PR; `/schedule` and `/routines` run cron agents on Anthropic's cloud.
  6. 6`--remote` pushes a task to the cloud, `--teleport` pulls a web session into your terminal, and `--remote-control` mirrors a local session to the web.

Quiz

Lock in what you learned

Check your understanding

0 / 4 answered

1.Your GitHub Actions job runs `claude -p` but fails with an authentication error. Which setup is correct for CI?

2.You want a headless agent in CI to only do what you've explicitly allowed and to deny everything else. Which flag fits, and how does it differ from the alternative?

3.Your `claude agents` view reports that the background service didn't respond, and your background sessions seem stuck. What's the right recovery?

4.You want Claude to keep a pull request green by fixing failures whenever CI breaks or a reviewer comments. Which mechanism does this, and what does it require?

Go deeper

Hand-picked sources to keep learning