Files
redwoodjs__local-ci/packages/cli

Agent CI

Agent CI is local CI for agents. It pauses when a workflow fails, allowing your agent to fix the issue and resume the workflow. Think of it as "live-reload for CI."

Agent CI runs your GitHub Actions workflows locally using the same official GitHub Action runners — the exact same binaries that power GitHub-hosted CI. What Agent CI emulates is the GitHub.com API itself, so actions like actions/checkout, actions/setup-node, and actions/cache work out of the box without hitting GitHub's servers.

Why Agent CI?

Traditional CI is a fire-and-forget loop: push, wait, fail, read logs, push again. Every retry pays the full cost of a new run.

Agent CI runs on any machine that can run a container. When a step fails the run pauses — the container stays alive with all state intact. Your edits are synced into the container on retry, so you can fix the issue and retry just the failed step — no checkout, no reinstall, no waiting. This makes it ideal for AI agents: point an agent at the failure, let it fix and retry in a tight loop — without the cost of a full remote CI cycle each time.

Prerequisites

  • Docker — A running Docker provider:
    • macOS: OrbStack (recommended) or Docker Desktop
    • Linux: Native Docker Engine or Docker Desktop

Usage

# Run a specific workflow
npx @redwoodjs/agent-ci run --workflow .github/workflows/ci.yml

# Run all relevant workflows for the current branch
npx @redwoodjs/agent-ci run --all

Remote Docker

Agent CI connects to Docker via the DOCKER_HOST environment variable. By default it uses the local socket (unix:///var/run/docker.sock), but you can point it at any remote Docker daemon:

DOCKER_HOST=ssh://user@remote-server npx @redwoodjs/agent-ci run --workflow .github/workflows/ci.yml

Docker host resolution for job containers

By default, Agent CI uses host.docker.internal for container-to-host DTU traffic and adds a default Docker host mapping:

  • host.docker.internal:host-gateway

This keeps behavior OS-agnostic and works on Docker Desktop and modern native Docker.

If your setup is custom, use environment overrides:

  • AGENT_CI_DTU_HOST - override the hostname/IP used by runner containers to reach DTU
  • AGENT_CI_DOCKER_EXTRA_HOSTS - comma-separated host:ip entries passed to Docker ExtraHosts (full replacement for defaults)
  • AGENT_CI_DOCKER_HOST_GATEWAY - override the default host-gateway token/IP for automatic mapping
  • AGENT_CI_DOCKER_DISABLE_DEFAULT_EXTRA_HOSTS=1 - disable the default host.docker.internal mapping
  • AGENT_CI_DOCKER_BRIDGE_GATEWAY - fallback gateway IP used when Agent CI runs inside Docker and cannot detect its container IP, and as an explicit DTU host override outside Docker when AGENT_CI_DTU_HOST is not set

When using a remote daemon (DOCKER_HOST=ssh://...), host-gateway resolves relative to the remote Docker host. If DTU is not reachable from that host, set AGENT_CI_DTU_HOST and AGENT_CI_DOCKER_EXTRA_HOSTS explicitly for your network.

agent-ci run

Run GitHub Actions workflow jobs locally.

Flag Short Description
--workflow <path> -w Path to the workflow file
--all -a Discover and run all relevant workflows for the current branch
--jobs <n> -j Max concurrent containers (overrides auto-detection)
--pause-on-failure -p Pause on step failure for interactive debugging
--quiet -q Suppress animated rendering (also enabled by AI_AGENT=1)
--no-matrix Collapse all matrix combinations into a single job (uses first value of each key)
--github-token [<token>] GitHub token for fetching remote reusable workflows (auto-resolves via gh auth token if no value given). Also available as AGENT_CI_GITHUB_TOKEN env var
--commit-status Post a GitHub commit status after the run (requires --github-token)

agent-ci retry

Retry a paused runner after fixing the failure.

Flag Short Description
--name <name> -n Name of the paused runner to retry (required)
--from-step <N> Re-run from step N, skipping earlier steps
--from-start Re-run all steps from the beginning

Without --from-step or --from-start, retry re-runs only the failed step (the default).

agent-ci abort

Abort a paused runner and tear down its container.

Flag Short Description
--name <name> -n Name of the paused runner to abort (required)

Concurrency

When running multiple workflows (--all), Agent CI limits how many containers run at the same time to avoid running out of memory.

The limit is auto-detected using two factors:

  • CPU: floor(cpuCount / 2)
  • Memory: floor(availableDockerMemory / 4GB)

Whichever is lower wins. For example, on a machine with 14 CPUs and a Docker VM with 12 GB of RAM, the CPU limit is 7 and the memory limit is 2 — so 2 containers run at a time.

To check available memory, Agent CI reads MemAvailable from /proc/meminfo inside the Docker VM. This accounts for the VM's kernel, daemon, and any other running containers. If that fails, it falls back to docker info total memory minus 4 GB.

You can override the auto-detected limit with --jobs:

# Run at most 4 containers at a time
npx @redwoodjs/agent-ci run --all --jobs 4

# Run one at a time (safest, slowest)
npx @redwoodjs/agent-ci run --all --jobs 1

YAML Compatibility

See compatibility.md for detailed GitHub Actions workflow syntax support.

Debugging

Set the DEBUG environment variable to enable verbose debug logging. It accepts a comma-separated list of glob patterns matching the namespaces you want to see:

Value What it shows
DEBUG=agent-ci:* All debug output
DEBUG=agent-ci:cli CLI-level logs only
DEBUG=agent-ci:runner Runner/container logs only
DEBUG=agent-ci:dtu DTU mock-server logs only
DEBUG=agent-ci:boot Boot/startup timing logs only
DEBUG=agent-ci:cli,agent-ci:dtu Multiple namespaces
  • Output goes to stderr so stdout stays clean for piping.
  • If DEBUG is unset or empty, all debug loggers become no-ops (zero overhead).
  • Pattern matching uses minimatch globs, so agent-ci:* matches all four namespaces.
DEBUG=agent-ci:* npx @redwoodjs/agent-ci run