Repo-issue–driven autopilot runner
npm install autopilot-codeRepo-issue–driven autopilot runner.
- repos opt in by committing .autopilot/autopilot.json
- work lives in GitHub Issues
- the runner advances issues through a label-based workflow
- the runner is designed to determine “is work still happening?” using durable artifacts (GitHub + repo files), not process inspection (ps, PID checks, etc.)
- .autopilot/autopilot.json with enabled: true
Autopilot supports multiple agent types:
opencode (recommended): Full-featured agent with extensive code understanding
``json`
{
"agent": "opencode"
}
claude: Fast, targeted code changes
`json`
{
"agent": "claude"
}
IMPORTANT: The new Python runner is now the default. The legacy bash script is deprecated and will be removed in a future version.
The new runner provides enhanced progress tracking and session continuity:
`json`
{
"enablePlanningStep": true
}
Deprecation Timeline:
- Current release: New runner is default, deprecation warnings added
- +1 minor release: More prominent warnings for legacy runner
- +1 major release: Bash script will be removed entirely
If you see a deprecation warning, it means you're using the legacy bash runner. To migrate, remove "useNewRunner": false from your config (or set to true).
When using the new runner, issues progress through these labels:
- autopilot:planning - Creating implementation planautopilot:implementing
- - Writing codeautopilot:pr-created
- - Pull request createdautopilot:waiting-checks
- - Waiting for CIautopilot:fixing-checks
- - Fixing failing CIautopilot:merging
- - Merging PR
To create these labels in your repository:
`bash`
autopilot setup-labels --repo owner/repo
Example:
`json`
{
"enabled": true,
"repo": "bakkensoftware/autopilot",
"agent": "opencode",
"autoMerge": true,
"mergeMethod": "squash",
"allowedMergeUsers": ["github-username"],
"issueLabels": {
"queue": ["autopilot:todo"],
"blocked": "autopilot:blocked",
"inProgress": "autopilot:in-progress",
"done": "autopilot:done"
},
"priorityLabels": ["p0", "p1", "p2"],
"minPriority": null,
"ignoreIssueLabels": ["autopilot:backlog"],
"maxParallel": 1,
"heartbeatMaxAgeSecs": 3600,
"branchPrefix": "autopilot/",
"allowedBaseBranch": "main",
"autoResolveConflicts": true,
"conflictResolutionMaxAttempts": 3,
"autoFixChecks": true,
"autoFixChecksMaxAttempts": 3
}
Notes:
- repo must be the GitHub owner/name.agent
- (optional, default "opencode"): set to "opencode" or "claude" to choose which coding agent to use.autoMerge
- (optional, default true): if true, autopilot will automatically merge PRs after checks pass.mergeMethod
- (optional, default "squash"): merge strategy to use. Options: "squash", "merge", or "rebase".allowedMergeUsers
- (required when autoMerge=true): list of GitHub usernames allowed to auto-merge. The runner verifies the authenticated GitHub user is in this list before merging.minPriority
- (optional, default null): minimum priority to work on. For example, set to "p1" to only work on p0 and p1 issues. Uses priorityLabels array for priority order.ignoreIssueLabels
- (optional, default ["autopilot:backlog"]): issues with any of these labels will be ignored by the runner.autoResolveConflicts
- (optional, default true): if true, autopilot will attempt to automatically resolve merge conflicts.conflictResolutionMaxAttempts
- (optional, default 3): maximum number of attempts to resolve merge conflicts.autoFixChecks
- (optional, default true): if true, autopilot will attempt to automatically fix failing CI checks.autoFixChecksMaxAttempts
- (optional, default 3): maximum number of attempts to fix failing checks.enablePlanningStep
- (optional, default true): if true, add an explicit planning phase before implementation.agentPath
- (optional): custom path to agent executable (defaults to searching PATH).
- autopilot:backlog — captured, not readyautopilot:todo
- — ready to be picked up by the runnerautopilot:in-progress
- — claimed by autopilotautopilot:blocked
- — needs human input or missing/stale heartbeatautopilot:done
- — completed
Optional priority labels:
- p0, p1, p2 (lower number = higher priority)
):1. It applies
autopilot:in-progress
2. It removes the queue label(s) (e.g. autopilot:todo)
3. It leaves a comment indicating the claim time and next stepDurable tracking (no process inspection)
This runner intentionally does not check local processes to decide if work is ongoing.Instead it uses durable artifacts:
- GitHub: issue labels + issue comments + (future) PR presence/status
- Repo file heartbeat:
.autopilot/state.jsonThe runner writes/updates
.autopilot/state.json like:`json
{
"activeIssue": {
"number": 2,
"repo": "bakkensoftware/autopilot",
"updatedAt": 1738000000
}
}
`On each loop:
- if an issue is
autopilot:in-progress but the heartbeat is stale/missing, autopilot comments and moves it to autopilot:blocked.Running locally
$3
`bash
Run a single scan/claim/act cycle
python3 scripts/run_autopilot.py --root /mnt/f/SourceRun in foreground loop mode (dev-friendly)
python3 scripts/run_autopilot.py --root /mnt/f/Source --interval-seconds 60
`$3
From the repo root:`bash
npm install
npm run buildsanity checks
node dist/cli.js doctorscan enabled repos without claiming
node dist/cli.js scan --root /mnt/f/Sourceclaim exactly one issue + comment
node dist/cli.js run-once --root /mnt/f/Sourcerun service in foreground mode (dev-friendly)
node dist/cli.js service --foreground --interval-seconds 60 --root /mnt/f/Source
`The foreground service mode runs continuously with the specified interval and logs to stdout. Press Ctrl+C to shut down cleanly.
Roadmap
- ~~Spawn a coding agent (Claude Code / OpenCode) in a worktree per issue~~ (done)
- ~~Create PRs linked to issues; wait for checks to go green~~ (done)
- ~~Merge PRs automatically when mergeable + checks pass~~ (done)
- Close issues + apply autopilot:doneConfig template
See templates/autopilot.json`.