Loop orchestrator daemon for autonomous software engineering.
Runmill watches your backlog, gives issues to coding agents, verifies their work, and delivers reviewed pull requests. It runs Codex or Claude Code; Runmill owns the loop around them.
The dashboard follows an issue from backlog claim through implementation, checks, an independent fresh-context review, and PR delivery—then shows the daemon returning to watch for more work.
Documentation · Configuration · Daemon operations
A coding agent can edit a repository. That is only one part of shipping software unattended. Something still has to decide what to work on, prevent duplicate work, run the right checks, review the result independently, and decide whether it is safe to merge.
Runmill handles that control loop:
backlog → select → claim → implement → verify → fresh-context review → PR → merge policy
↑ │
└──────────────────────────── poll for more work ────────────────────────┘
When the queue is empty, the daemon waits. When a new eligible issue appears, it starts another
run. While run or daemon is active, Runmill asks macOS or Linux to keep the machine awake.
Runmill:
- Selects an eligible issue and routes it to a repository.
- Claims it with a Git-backed lease, so another worker cannot take it.
- Creates an isolated workspace and starts the implementer.
- Runs the repository's required checks against the candidate commit.
- Starts a reviewer with brand-new context. The reviewer sees the task and diff, not the implementer's conversation.
- Opens a pull request, waits for CI, and applies the configured merge policy.
- Records the result in SQLite and appends a readable entry to
.runmill/log.md.
Runmill stops a run when evidence is missing or policy says a person must decide. Agents never own backlog mutations, pushes, pull requests, or merges; deterministic orchestration code does.
Runmill is not published to npm yet:
git clone https://github.com/mikigraf/runmill.git
cd runmill
npm ci
npm run build
npm linkDirect runtime and development dependencies are pinned to exact versions. npm ci installs the
lockfile without silently moving the agent harness underneath you.
In the repository you want it to manage:
runmill config create # guided setup with discovered GitHub, Linear and agent options
runmill init # add the check manifest and review rules
runmill doctor # verify credentials, CLIs, Git and sandbox support
runmill next # preview selection without changing anything
runmill daemon --detach # start the backlog worker in the background
runmill tui # open the live interface from any directoryThe setup wizard uses authenticated gh, Linear credentials, Codex, and Claude when available. It
lets you use installed CLI subscriptions or API keys, preloads repositories and Linear workflow
values, and writes conservative defaults. Secrets are never written to runmill.yaml.
For CI or scripted setup:
runmill config create --defaults
runmill config validate
runmill daemon --once--once drains the work that is eligible now and exits. Without it, daemon checks the backlog
every 30 seconds while idle. Change that with --poll-seconds; use --max-runs for a bounded
session.
runmill tui is an OpenTUI dashboard for the running daemon. It discovers a user-private local
socket, so it works from any directory and does not need runmill.yaml. The dashboard shows live
daemon status and logs, recent runs, the active orchestration pipeline, transitions, agent events,
and pending external effects. It can also request a safe stop at the next run boundary. Runmill
automatically launches this one command with Bun because OpenTUI's native renderer needs it on the
Node versions Runmill otherwise supports.
The included demo uses in-memory integrations:
cd examples/quickstart
RUNMILL_DEMO=1 npx tsx ../../src/cli/main.ts next --dry-run
RUNMILL_DEMO=1 npx tsx ../../src/cli/main.ts daemon --onceDemo mode is explicit. Runmill never silently substitutes a fake integration in production.
A minimal runmill.yaml:
# yaml-language-server: $schema=./runmill.schema.json
version: 1
autonomy: pr-only
providers:
implementer:
implementation: codex
reviewer:
implementation: claude
backlog:
provider: linear
team: ENG
eligible_states: [Todo, Ready]
claim_state: In Progress
delivered_state: In Review
github:
repositories:
- match: { team: ENG }
repo: acme/platform
base_branch: mainThe implementer and reviewer may use the same CLI, different models, or different providers. A different provider is useful, but not required: every review starts without the implementer's history either way.
See the configuration reference for checks, budgets, risk paths, repository routing, credentials, and merge policy.
- A real idle state.
daemonwaits for new Linear issues instead of exiting when the queue is empty. GitHub is currently the repository, CI, and pull-request integration; GitHub Issues is a declared backlog type but does not yet have a live adapter. - No laptop naps mid-run. Runmill starts
caffeinateon macOS orsystemd-inhibiton Linux and releases it when the process stops. - Safe stopping.
SIGINTandSIGTERMfinish the in-flight run boundary before exiting. - Circuit breakers. Repeated failures, quarantines, escalation rates, and daily spend can stop the daemon before one bad condition is repeated across the backlog.
- Durable state. Leases, transitions, check evidence, and intended side effects survive a restart.
- Operator-friendly output. Human-readable commands by default;
--json, stable exit codes,inspect,list --needs-attention, anddoctor --reportfor automation and support. - A remote terminal UI. Start with
runmill daemon --detach, then userunmill tuianywhere on the same machine. The client reads daemon state over a0600Unix socket rather than guessing paths or opening the database itself.
| Mode | Behavior |
|---|---|
observe |
Select and plan without claiming work or changing a repository |
pr-only |
Implement, verify, review, and open a pull request; never merge |
guarded-merge |
Merge eligible low-risk changes after every gate passes |
continuous |
Use guarded merge policy across repeated daemon runs |
pr-only is the default. A daemon can run continuously in any active mode; the autonomy setting
controls what each run may do, not whether the process stays alive.
- Git-ref leases prevent two workers from taking the same issue.
- Agent workspaces run under Seatbelt on macOS or bubblewrap on Linux.
- Required checks run against the exact candidate commit in a clean checkout.
- Reviews run with fresh context and must account for every acceptance criterion.
- Sensitive paths and incomplete evidence escalate instead of merging.
- Only the orchestrator can change backlog state, push, open a PR, or merge.
Runmill does not claim that an agent's code is correct. It records what was checked, what was reviewed, which policy ran, and why the change was allowed to continue.
| Command | Purpose |
|---|---|
runmill config create |
Create a config from discovered tools and integrations |
runmill config validate |
Validate the config and check manifest |
runmill config show |
Print the resolved config and defaults |
runmill doctor |
Check the host, credentials, agent CLIs, and sandbox |
runmill next |
Show the next issue and explain rejected candidates |
runmill prepare <issue> |
Check whether one issue is ready |
runmill run [issue] |
Process one issue |
runmill daemon |
Watch the backlog and process work continuously |
runmill daemon --detach |
Start the daemon in the background |
runmill daemon --once |
Drain eligible work and exit |
runmill tui |
Open the live OpenTUI dashboard from any directory |
runmill list --needs-attention |
Show runs waiting for a person |
runmill inspect <run-id> |
Show transitions, evidence, and pending effects |
runmill resume <run-id> |
Resume a paused run |
runmill policy explain <run-id> |
Explain a merge decision |
runmill auth status |
Show available credentials |
runmill auth login / runmill auth logout |
Add or remove a stored credential |
runmill skills eject / runmill skills validate |
Customize or validate review rules |
runmill state |
Check the local state store |
runmill gc |
Reconcile workspaces left by interrupted runs |
runmill eval validate <suite> |
Validate an evaluation suite |
runmill eval replay <suite> |
Replay historical tasks through the harness |
runmill feedback |
Create a support issue with diagnostics |
Every command supports --json, --quiet, and --config <path>. Run runmill --help for the
complete list.
- macOS or Linux, arm64 or x64
- Node.js 20.11 or newer
- Git and an authenticated GitHub account
- An authenticated Codex or Claude Code CLI
- Seatbelt on macOS or bubblewrap on Linux
caffeinateon macOS orsystemd-inhibiton Linux for sleep prevention- Bun for
runmill tui(the daemon and other commands only require Node)
Linear is currently the live backlog provider. GitHub handles source, pull requests, CI, branch protection, and merges.
| Variable | Purpose |
|---|---|
RUNMILL_DEMO=1 |
Use the bundled in-memory integrations |
RUNMILL_FAKE_BACKLOG=<file> |
Load backlog issues from a JSON fixture |
RUNMILL_SOURCE_REPO=<path> |
Override the repository used to create run workspaces |
RUNMILL_DATA_DIR=<path> |
Override the state and workspace directory |
RUNMILL_DAEMON_REGISTRY=<path> |
Override daemon discovery, mainly for isolation and testing |
- Daemon operation
- Configuration
- Run lifecycle and recovery
- Verification and check coverage
- Autonomy and merge gates
- Issue leases
- Sandboxing
- Historical evaluation
- Errors
- Contributing
MIT. See LICENSE.
