Skip to content

中文 · English

CI PyPI Downloads License codecov

agent-runner

A restart-on-exit supervisor for autonomous coding CLIs. Ships presets for Claude Code, aider, gemini, codewhale, kimi and pi; any prompt-arg CLI via custom config. Spawn the agent round-after-round under defenses that prevent the failure modes that bite in production: stuck rounds, orphan commits, OAuth burn loops, full disks, runaway memory.

┌──────────────────────────────────────────┐
│ Layer 3: The Witness (monitor)           │  11 detectors + auto-stop
├──────────────────────────────────────────┤
│ Layer 2: The Loop (serve, ~120 LOC)      │  signal-trapping restart loop
├──────────────────────────────────────────┤
│ Layer 1: The Round (round)               │  one agent invocation
└──────────────────────────────────────────┘

Install

pip install cli-agent-runner

The installed CLI command is agent-runner (the PyPI distribution name is prefixed for namespace disambiguation; the import name and command are not).

Quick start

cd your-project
agent-runner init                 # scaffold agent-runner.toml + prompts/main.md
$EDITOR agent-runner.toml         # point agent.command at your CLI
agent-runner install --monitor    # systemd user units for serve + monitor
agent-runner status               # confirm running
agent-runner peek                 # snapshot of project state
agent-runner monitor              # live anomaly detection

Full walkthrough: docs/quickstart.md.

15 verbs

Lifecycle Observation
init / install / uninstall peek — state snapshot
start / stop / kill watch — peek in a refresh loop
restart / status monitor — 11 detectors, alerts, auto-stop
round / serve / upgrade events — query / stream events.jsonl

Verb reference: docs/commands.md.

Defenses (built in)

13 named defenses, structured as data — see agent-runner peek --select defenses. Each carries the historical incident it codifies and the invariant test that guards it. Highlights:

  • round_timeout_s — hard wall, never the agent's word on when to stop
  • process_group_isolation — kill the round, not just the parent
  • orphan_stash_idempotency_s — no 3-stashes-per-second pile-ups
  • sha_locked_stashstash@{N} indices drift; SHAs don't
  • set_diff_classification — line-set comparison, not unified-diff +/- scan
  • startup_smoke_check — refuse to run with a clearly-truncated prompt

Full list and rationale: docs/architecture.md.

Monitor: 11 detectors

Notify only: timeout_rate, hung, orphan_chain, disk_warning, mem_pressure, network_fail, rate_limit_active, anomaly_repetitive_active, supervisor_stale.

Auto-stop the service (continuing is harmful):

  • oauth_fail — burning API quota on auth-rejected rounds
  • disk_critical — writing to a near-full disk risks corruption

Runs against the supervised project's local logs:

agent-runner monitor                  # 30s poll
agent-runner monitor --json | jq -c   # pipe to downstream consumers

Watch a remote host's event stream from your laptop — one command instead of a hand-rolled ssh … ; sleep loop:

agent-runner monitor --host pi --mode events   # managed ssh relay, JSONL stdout

The relay reconnects with --since <last ts> so a dropped link replays its gap, gives up (exit 1) once the outage passes remote_failure_tolerance_s, and kills the ssh process group on exit so no orphan tree is left behind.

Detection stays on the host. --host with --mode anomaly | narrate | http exits with an error: the detectors read the supervised host's logs and auto-stop its service, which must keep working with your laptop closed. Run the monitor there (ssh <alias>, then agent-runner monitor) and relay its events here. See docs/runbook.md § "Remote event relay & SSH trust" — the SSH trust boundary applies to any agent-runner command you drive over ssh.

Documentation

Development

git clone https://github.com/wan9yu/cli-agent-runner.git
cd cli-agent-runner
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"

./build.sh check                          # full local-CI sweep
./build.sh test                           # unit + integration only
AGENT_RUNNER_E2E_PI=1 ./build.sh e2e      # opt-in pi e2e (needs ssh alias `pi`)

Some docs/*.md blocks are generated from code — ./build.sh docs rewrites the <!-- gen:* --> regions, and ./build.sh check verifies they are fresh.

POSIX-only (Linux, macOS). Tested under Python 3.11+ on x86_64 and aarch64.

License

Apache License 2.0.

About

Keep agent CLIs running 7×24 — supervise Claude Code / aider / any prompt-arg agent with 11-layer defenses and structured observability.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages