@pimmesz/afterburner
v2.7.4
Published
Convert idle AI-subscription quota (Claude or Codex) into shippable engineering work: budget-aware trigger, bounded task selection, PR-only output.
Maintainers
Readme
You pay a flat monthly fee for Claude or ChatGPT, and each week's unused quota expires. There's no rollover. Afterburner spends that leftover headroom on your own repos.
When there's quota to spare, it picks one small, well-scoped task (a missing test, a stale
TODO in a README, a loose any to tighten), hands it to the coding agent you already have
installed (claude or codex), and leaves the change on a throwaway afterburner/ branch,
ready for you to open as a pull request. You merge what's good and ignore the rest.
Why it's handy: capacity you've already paid for becomes steady, incremental improvements — one small task at a time, on a branch you review before anything merges. (The full safety story is below.)
┌─ at a glance ─────────────────────────────────────────────
│ Safety human review by default, --dry-run previews any run
│ Output PR-only, on an afterburner/ branch
│ Scope one bounded task per run, hard token ceiling
│ Budget both-caps gate + safety margin
│ Privacy no telemetry, no phone-home
└────────────────────────────────────────────────────────────Fair use: Afterburner is for spending your own subscription quota on your own repos. It doesn't get around provider limits; it keeps capacity you've already paid for from going to waste.
Quickstart (60 seconds)
Needs Node.js 22.12 or newer and git on your PATH.
Heads up before you copy-paste: the unscoped afterburner name on npm is a different,
unrelated package, so always use the scoped @pimmesz/afterburner.
npm install -g @pimmesz/afterburner
afterburner init # interactive setup, writes afterburner.config.mjs
afterburner doctor # checks prerequisites and prints fixes
afterburner run-once --dry-runPoint init at a repo (or add one to repos in the config later), and a dry run shows
exactly what a live run would do:
Mode: DRY-RUN (no side effects)
Budget (manual: budget.manual / flags): session=available weekly=100% (~3,000,000 Sonnet-eq tokens remaining)
repo /path/to/repo
[discovery] Discover new work for the backlog
branch afterburner/discovery-9f2a1c4b8e07
PR title Discover new work for the backlog [afterburner:9f2a1c4b8e07]
est cost 200,000 Sonnet-equivalent tokens
[dry-run] Would check out …, create branch afterburner/discovery-9f2a1c4b8e07, … No side effects were performed.
Next
This was a preview. To run it live, set agent.backend to a live engine
('claude-code' or 'codex') in afterburner.config.mjs, then: afterburner run-onceOn a fresh repo the backlog is empty, so the first pass is discovery — a read-mostly analysis
that proposes a prioritized backlog on a branch you review (it spends quota but writes no code). Once you
merge that, later runs execute the highest-priority items as concrete fixes ([tests], [docs],
[security], …). Discovery is the primary work source — turning off agent.discovery and
agent.backlog stops it. Two opt-in sources add to it: issue-driven work (agent.issues —
open GitHub issues labeled agent.issueLabel become PRs that close them; the label is your gate,
needs gh) and the goal-planner (agent.goalPlanner, claude-code only: set goals and it
proposes goal-directed steps). A truly preview-only config leaves all of them off.
Claude Code skill
afterburner skill install # copies the skill to ~/.claude/skills/afterburner/Then you can ask Claude Code to "run an afterburner dry run", or use /afterburner. Both
drive the same CLI.
The economics
Flat-rate AI subscriptions are use-it-or-lose-it. The claude-code backend runs tasks through your local Claude Code login,
and the codex backend through your local codex (OpenAI/ChatGPT) login. Both spend quota
you're already paying for and cost nothing extra (Codex budget reads your local codex usage).
Afterburner has no per-token API-key engine — spending real money at API rates is off-mission.
One cost caveat worth knowing: Fable-family models cost real money. Outside promotional windows they're excluded from subscription plan limits and bill usage credits at API rates. That's why Afterburner blocks them by default (see Safety model).
Use at your own risk
Afterburner runs on your machine, under your accounts, against your repositories. Whatever it uses is yours to pay for: it spends your AI-subscription quota (Claude Code or Codex), and with a Fable/Mythos model it can spend real money billed to your own Anthropic account. The maintainers don't run it for you and don't cover anything it does.
You're responsible for what it does on your behalf, including the budgets you set, the repos
you allowlist, the backend you choose, and reviewing any pull request before you merge it.
A live run happens only with a live agent.backend (the dry-run backend never executes), and
--dry-run previews any run — precisely so nothing costs you anything until you decide it should.
The software is provided "as is", without warranty of any kind, as set out in the
Apache-2.0 license.
Where to run it. A live claude-code (or codex) run gives the agent a full shell on the
target repo's contents, unattended. Afterburner's enforced guarantees are git-level (PR-only, the
default branch is asserted unchanged) — they don't sandbox the agent's filesystem or network. So
prefer running live Afterburner on a dedicated or sandboxed machine, not your primary workstation
with all your credentials (~/.ssh, cloud tokens) in reach.
Why no built-in OS sandbox? The threat that matters for an unattended agent is exfiltration — read a secret, send it out — and that needs per-host egress control, which
sandbox-exec/bwrapprofiles can't express (they allow or deny network wholesale, and the agent genuinely needs its model API). A profile could only confine filesystem writes, which doesn't close the exfil hole and risks a false sense of safety. Doing it right means routing the agent through an egress-filtering proxy or network namespace — host-level infrastructure that belongs around Afterburner (the dedicated/sandboxed machine above), not bolted inside it.
Safety model
These rules live in the code, not just in this README:
- Live needs a live engine. A live engine in
agent.backendruns live by default; pass--dry-runto preview, and adry-runbackend (the schema default) never executes. Thecodexbackend adds a gate,agent.allowCodexLive, because its agent runs a full shell. (Theclaude-codeinteractive session also runs the agent with a full shell — its containment is the prompt plus the enforced PR-only / tip-assertion rules below; see Backends.) - PR-only. Live work lands on an
afterburner/-prefixed branch. By default it never merges and never pushes to your default branch — you open and merge the PR. Withagent.mergePolicy('on-green'/'auto') afterburner opens the PR and merges it for you.'on-green'first polls the PR's check rollup and only merges once every check is green (a failing or still-running check leaves the branch for review) — so it gates on CI even on a repo with no branch protection; it also requires a localverifygate. It waits out an initially-empty rollup (checks can take a few seconds to register after the PR opens) rather than racing them; a repo with genuinely no checks merges on theverifygate alone, once the poll window confirms none appear.'auto'skips that wait andgh pr merge --autos immediately (still honoring branch protection if any). Theclaude-codebackend needs the extraagent.allowClaudeAutoMergeopt-in (its agent is unsandboxed).agent.autoPushBranchpushes theafterburner/branch without merging. The agent never touches the default branch in any policy — the merge is afterburner's, via the forge. - One task per run. The task has to fit inside the budget or be abandoned cleanly. A killed
run leaves a resumable
afterburner/branch, never a half-broken state. - Verified before it's claimed (opt-in). With
repos[].verifyset (e.g.['pnpm typecheck', 'pnpm test']), a live run runs those commands in the worktree after the agent commits; a non-zero exit yields averify-failedbranch instead of a clean one, so a run never hands you a branch that doesn't build. - Both caps are checked. A run only fires when a 5-hour session window is available and the estimated cost plus a safety margin fits inside the remaining weekly budget.
- Idempotent. Each task gets a deterministic fingerprint that names its
afterburner/branch. A run is skipped without spending quota when that branch already exists locally or on origin (and, withagent.checkRemotePrs, when the forge already has a PR for it). The run log also remembers every task it already delivered, so a merged-then-deleted (or closed) branch is never rebuilt — the dedup survives branch deletion, not just branch existence. - Fable is gated. Any Fable/Mythos-tier model is refused unless you explicitly set
agent.allowFable: true, so an unattended scheduler can't quietly spend at API rates. - Untrusted input stays data. Repo contents, issue titles, and PR text never get interpolated into shell commands. They go through stdin and environment variables instead.
- No telemetry, and no repos configured out of the box. The only network call the CLI makes
on its own is a once-daily npm version check (skipped off-TTY and in CI; disable with
NO_UPDATE_NOTIFIER=1).
Commands
| Command | What it does |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| afterburner init | Interactive setup; writes afterburner.config.mjs (alias: setup) |
| afterburner config | Interactive settings editor (--edit opens $EDITOR, --path prints path); alias: settings |
| afterburner doctor | Check prerequisites and config; failures print an actionable fix (--json for CI, --only/--skip to filter checks, --strict to also fail on warnings) |
| afterburner auth | Store a long-lived subscription token so scheduled/headless runs authenticate without the keychain |
| afterburner status | Quick readout: budget gate, reset times, next run, PR merge rate, whether it's armed live (--all prints a redacted, safe-to-paste diagnostics bundle) |
| afterburner run-once --dry-run | Preview the next task: branch, PR title, est cost (no changes made) |
| afterburner run-once | Run the next task for real: a live backend runs live by default |
| afterburner watch | Foreground scheduler daemon on your configured cron |
| afterburner schedule install | Native launchd / systemd / schtasks entry (recommended for unattended) |
| afterburner log | Append-only history of what ran (--json machine output, --summary totals + PR merge rate) |
| afterburner backlog | Show the prioritized work backlog (.afterburner/backlog.jsonl) per repo |
| afterburner review | Review & merge afterburner's open PRs: an advisory read-only LLM verdict, then a SHA-pinned, CI-gated, human-confirmed merge (--json lists non-interactively) |
| afterburner notify test | Fire a test notification on each configured channel and show what it uses |
| afterburner update | Update to the latest release (--print to just show the command) |
| afterburner statusline install | Hook that caches your real /usage numbers for the claude-usage budget |
| afterburner statusline print | Compact usage line for a shell prompt / tmux (auto-detects Codex or Claude) |
| afterburner skill install | Install the Claude Code skill into ~/.claude/skills |
Backends
agent.backend chooses the engine. The dry-run backend (the schema default) never executes; a
configured live engine runs live by default — pass --dry-run to preview (codex adds a third
opt-in). Set it once in your config.
| Backend | Spends | Opt-in | Notes |
| ------------- | ---------------------------------------------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| dry-run | nothing, simulates everything | — | the safe default; previews the exact branch + change it would create (and, under on-green/auto, open as a PR) |
| claude-code | your Claude subscription's interactive weekly limits | live backend | drives a real interactive claude session (not -p); full shell, no per-tool deny; strips ANTHROPIC_API_KEY |
| codex | your OpenAI/ChatGPT subscription, via local codex | live backend + allowCodexLive | reads ~/.codex usage for budgeting; strips OPENAI_API_KEY/CODEX_API_KEY |
Both live engines (claude-code, codex) share the same safety machinery. The change lands on
an isolated afterburner/ worktree branch; what happens next follows agent.mergePolicy: with the
default 'review' afterburner leaves the branch for you to open and merge (it never opens or
merges the PR itself), while 'on-green'/'auto' have afterburner open and merge the PR for you via
gh. In every policy the agent never pushes your default branch directly, and afterburner asserts
the default branch (local and remote) is unchanged after the run. Both run the agent with a full
shell, so its only in-agent guardrail is the prompt — the enforced containment is the worktree
isolation + the default-branch tip assertion. codex also needs the extra allowCodexLive opt-in (its network boundary is its own
sandbox). See Live execution status for the per-backend auth setup.
Updating
Afterburner checks npm at most once per day before interactive commands and prints an update
nudge when a newer version is available. The notice goes to stderr, so JSON output from
commands like afterburner log --json stays parseable. Machine-invoked commands such as
statusline stay quiet; update skips the pre-check because it performs the update itself.
afterburner update # installs the latest release
afterburner update --print # only print the command
afterburner update --registry=https://registry.npmjs.org/
afterburner doctor --check-updates # verifyFor an npm install, update runs npm install -g @pimmesz/afterburner@latest. For a source
checkout it rebuilds and reinstalls that checkout in place; it does not run git, so git pull
first if you want new code.
If a company npm proxy shadows public packages, point the install at the public registry with
afterburner update --registry https://registry.npmjs.org/, or set it once globally:
npm config set @pimmesz:registry https://registry.npmjs.org/Scheduling
afterburner schedule install # recommended: native launchd / systemd / schtasks entry
afterburner watch # foreground daemon, useful for dev or temporary runs
afterburner stop # stop scheduled runs (alias: afterburner schedule uninstall)Use schedule install for normal unattended use. It lets the OS restart the cadence after
login/reboot and is more reliable than keeping a terminal process alive. It figures out your
platform, writes the unit or plist files, and prints the command to activate them.
watch is still there for foreground runs and for cron expressions that native schedulers
can't express. If your cron expression is too complex for the native scheduler, schedule
install says so and points you at watch.
Configuration
afterburner init writes afterburner.config.mjs. cosmiconfig loads it, and .js, .cjs,
and .ts variants of afterburner.config.* work too (JSON only as .afterburnerrc.json).
A .ts config also needs the typescript package available at runtime, which is why init
writes .mjs by default. There's a commented example in
afterburner.config.example.ts.
| Key | Default | What it does |
| ------------------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| repos[] | [] | Allowlist: url (remote or local path), defaultBranch (main), branchPrefix (must stay in afterburner/), enabledTaskCategories, and optional verify (commands run after the agent commits — a non-zero exit leaves a verify-failed branch instead of a clean one, so a run never claims work that doesn't build) |
| budget.provider | manual | Claude backends: manual, claude-code-transcripts, or claude-usage (automatic ones described below). The codex backend ignores this and reads ~/.codex usage automatically, falling back to budget.manual. |
| budget.weeklyAllowanceSonnetTokens | 5_000_000 | Your plan's weekly capacity estimate, used by the automatic providers |
| budget.usageCacheMaxAgeHours | 12 | claude-usage only: a cache older than this falls back to the transcript estimate |
| budget.minWeeklyHeadroomPct | 20 | Don't fire below this much of the weekly cap remaining |
| budget.safetyMarginTokens | 200_000 | Sonnet-equivalent tokens kept untouched on every decision |
| budget.requireSessionAvailable | true | Also require a 5-hour session window |
| budget.sweepBeforeResetMinutes | 0 | Sweep mode: only run within this many minutes before the weekly reset (0 = off / opportunistic); needs claude-usage |
| budget.pacedBurndown | false | Paced burn-down: spread spend evenly across the week toward minWeeklyHeadroomPct instead of draining as fast as sessions allow (the "across the week" onboarding option); needs claude-usage for reset times |
| budget.manual | session ✓ / 100% / 3M | Inputs for the manual provider; you can override them per run with flags |
| schedule.cron / schedule.timezone | 17 */4 * * * / UTC | When watch and native schedules fire |
| agent.backend | dry-run | dry-run, claude-code, or codex |
| agent.modelByCategory | backend flagship | Per-category model routing. Defaults to the backend's flagship for every category (Opus 4.8 for Claude, gpt-5-codex for Codex): spend idle quota on the best model. The selector downgrades to a cheaper model (and lower --effort) when the budget won't fit. Plain strings, so a new model never breaks the config. |
| agent.maxTaskTokens | 300_000 | Hard per-task ceiling in Sonnet-equivalent tokens (300k fits an Opus run of the heaviest categories) |
| agent.taskTimeoutMs | 1_800_000 | Live runs only: absolute wall-clock cap (ms) on one turn even while it is progressing — shared by every backend and the verify command |
| agent.inactivityTimeoutMs | 900_000 | Interactive Claude driver only: kill the turn as wedged after this much zero transcript growth (distinct from taskTimeoutMs, which caps a turn that IS progressing) |
| agent.adaptive | false | Opt-in: upgrade to maxEffortModel when weekly headroom is high (≥60%); cost still flows through the cost table |
| agent.maxEffortModel | '' | The model adaptive routing upgrades to ('' = no upgrade); gated by allowFable like the rest |
| agent.allowFable | false | Explicit opt-in for Fable-family models |
| agent.allowCodexLive | false | Required to run codex live, alongside agent.backend: 'codex' and no --dry-run; Codex's agent has a real shell contained by its own sandbox |
| agent.autoPushBranch | false | Opt-in: push the committed afterburner/ branch to origin after a live run (never the default branch), so cross-instance coordination sees it without a manual push |
| agent.checkRemotePrs | false | Opt-in: before a live run, skip when the forge already has a PR for this task's branch (GitHub via gh; best-effort) |
| agent.mergePolicy | 'review' | How a finished afterburner/ branch merges: 'review' (you merge), 'on-green' (afterburner opens the PR, polls the check rollup, and merges once every check is green — requires a local verify gate too), 'auto' (opens + gh pr merge --auto immediately, no check wait, no local gate). Forge-only; per-repo mergePolicy overrides this |
| agent.allowClaudeAutoMerge | false | Extra opt-in required for the claude-code backend to auto-merge (its agent is unsandboxed); without it, on-green/auto fall back to commit-for-review |
| agent.backlog | true | Draw work from a curated, prioritized queue (.afterburner/backlog.jsonl, most important first) populated by the discovery pass; afterburner backlog shows it |
| agent.discovery | true | Spend some idle quota on an LLM analysis pass (security / performance / infrastructure / accessibility / error-handling / feature / tests / types-lint / dead-code / docs lenses) that curates the backlog — this is how every enabled subject becomes real, executable work |
| agent.discoveryStalenessDays | 7 | Re-run the discovery pass only once the repo's backlog is this many days stale |
| agent.issues | false | Opt-in: draw work from OPEN GitHub issues labeled agent.issueLabel. A labeled issue is worked into a PR that closes it (Closes #N, reliable when afterburner opens the PR). The label is the human gate; needs gh. Outranks backlog/discovery; untrusted issue text rides env vars |
| agent.issueLabel | 'afterburner' | The issue label agent.issues watches (per-repo repos[].issueLabel overrides it) |
| agent.goalPlanner | false | Opt-in (claude-code backend only): with goals set, a planning turn proposes the next bounded step toward a goal — a secondary, goal-directed work source, bounded by open-PR back-pressure |
| agent.effort | 'cruise' | Work SCOPE per task (not model reasoning): cruise (just the change), boost (done well), afterburner (full thrust); scales the prompt, the budget estimate, and the tool-call ceiling |
| goals | [] | Optional objectives that focus selection (used with agent.goalPlanner): each narrows by category and/or path glob; runs advance the top unfinished goal one reviewable PR at a time |
| notify.desktop | false | Desktop banner per completed run (macOS/Linux/Windows), opt-in; the PR stays the primary signal |
| notify.ntfy.topic | '' | ntfy.sh push per completed run, active once set; reaches you where desktop banners can't (managed machines), via the ntfy app |
| notify.ntfy.server | https://ntfy.sh | Base ntfy URL (self-hosted ok); a bearer token from AFTERBURNER_NTFY_TOKEN is attached only over an https server, never plaintext |
| repos[].enabledTaskCategories | per repo | The subjects discovery analyzes for that repo — the real category control (pick any number) |
Task categories are security, tests, types-lint, dead-code, performance,
infrastructure, accessibility, error-handling, docs, and feature. Work comes primarily from
the LLM discovery pass (the opt-in goal-planner above is the one secondary source). When
agent.discovery is on (the default), it analyzes the repo
across the enabled subjects and curates .afterburner/backlog.jsonl — adding high-value items,
re-prioritizing, and pruning ones that are done or stale — so every category becomes real, executable
work. You enable any number of categories per repo (repos[].enabledTaskCategories); that scopes
what discovery analyzes — there's no per-category rotation. Discovery folds all the selected
subjects into one prioritized backlog, and the single highest-priority item runs next whatever
its category (a P5 security hole beats a P1 docs nit). Later runs work down the queue;
afterburner backlog shows it, most important first. (The deterministic selector remains only as the
cost/fingerprint authority, not a work producer.) Each category comes with a built-in note on how a
reviewer confirms it's done.
Note on feature: it finishes work you already scoped (a throw "not implemented"
stub or a // TODO: implement … comment in your source) and never invents new features from
scratch. That keeps every run a single bounded task (the core safety rule), and gives the
agent a clear, verifiable definition of done instead of an open-ended brief.
The budget model
Everything is measured in Sonnet-equivalent tokens, normalized through one cost table built from published API price ratios (Haiku 1/3x, Sonnet 1x, Opus 1.67x, Fable 3.33x). There's no official API for how much subscription quota you have left, so there are three estimate-driven providers:
claude-usage(automatic, most accurate). Reads the same numbers the/usagepanel shows: your real 5-hour and 7-day usage percentages and the exact reset times. Claude Code hands these to its statusLine feature, andafterburner statusline installadds a hook that caches them. This provider reads that cache. The reset timestamps let a slightly-stale cache correct itself (a 5-hour window that has already reset reads as available again), and it falls back to the transcript estimate if the cache is missing or older thanbudget.usageCacheMaxAgeHours. Setup:afterburner statusline install # wraps any existing status line without clobbering it # use Claude Code once so it reports usage after the first API response # then set budget.provider: 'claude-usage' in your configYou still set
budget.weeklyAllowanceSonnetTokensonce. The percentage is authoritative, but turning it into a token figure needs to know your plan's size. The cache refreshes whenever you use Claude Code interactively.claude-code-transcripts(automatic). Reads your local Claude Code session transcripts (~/.claude/projects/**/*.jsonl, written live by every session), adds up what you actually spent over the last rolling 7 days, converts it through the cost table, and subtracts it frombudget.weeklyAllowanceSonnetTokens. Set the allowance once against/usage, and after that the remaining budget tracks itself. Session availability stays a manual input, since the 5-hour cap isn't exposed locally.manual. You supply thebudget.manualnumbers (check/usage), or override them per run:
afterburner run-once --weekly-remaining-pct 45 --weekly-remaining-tokens 1500000 --session-available trueFlags override whichever provider you've configured, so you can spot-check the automatic numbers whenever you want.
Live execution status
- Pick an engine in
afterburner init(it explains the cost of each one inline), or setagent.backendin the config. - For
claude-code: install Claude Code, log in withclaude /login, and make sureANTHROPIC_API_KEYis unset — a present API key can take priority over your subscription and bill the API instead. Afterburner strips it from the child as a defense, andafterburner doctorchecks your environment and which auth method is actually in use. For scheduled or headless runs — a background launchd/systemd job can't read your interactive keychain login — runafterburner auth: it mints a long-lived token withclaude setup-tokenand stores it (0600) so runs authenticate without the keychain (or setCLAUDE_CODE_OAUTH_TOKENyourself). The backend drives a real interactiveclaudesession (over a pty), so a run draws from the interactive weekly limits Afterburner's budget tracks. - For
codex(OpenAI/ChatGPT subscription): install thecodexCLI, log in withcodex login, and make sureOPENAI_API_KEYandCODEX_API_KEYare unset. Afterburner strips them so a run spends subscription quota, never the metered API. Budget reads the Codex CLI's own local rate-limit data (~/.codex/sessions, the 5h + weekly windows thatcodex's/statusshows), falling back tobudget.manualwhen that data is missing or stale (e.g. if you only ever run Codex headless). Model ids are plain strings; overrideagent.modelByCategoryif your Codex model names differ from thegpt-5-codexdefault. Live Codex needs the extraagent.allowCodexLive: trueopt-in (its agent runs a real shell contained by Codex's own sandbox, so it sits belowclaude-code's default trust). - Run it: with a live backend configured,
afterburner run-onceruns live (use--dry-runto preview);afterburner watchruns the scheduled daemon.
The claude-code and codex backends run for real: each makes the change on an isolated
afterburner/ worktree branch. Under the default mergePolicy: 'review' it stops there and
leaves the branch for you to open and merge; with 'on-green'/'auto' Afterburner opens and
merges the PR itself via gh. Both backends share the same safety machinery (PR-only, the local
AND remote default-branch tips are asserted unchanged, untrusted input goes via stdin/env,
Afterburner owns all git). The dry-run path works end to end.
Uninstall
afterburner stop # stop scheduled runs + remove scheduler entries first
rm -rf ~/.claude/skills/afterburner # remove the skill if you installed it
npm uninstall -g @pimmesz/afterburner # also how a source install (`npm install -g .`) is removedThe run store lives in your OS data directory; afterburner doctor prints the exact path.
Delete that directory to clear the audit trail.
Threat model
- Prompt injection. A malicious repo, issue title, or PR body could try to run commands.
Afterburner never drops untrusted text into shell strings or CI
run:blocks; it travels via stdin andprocess.env, and the invocation builder is unit-tested against hostile input. Residual risk: a hostile repo can still burn one bounded run's quota and propose a junk PR you then reject. - Blast radius. Output is confined to one
afterburner/branch per run from an allowlisted repo, and the default branch (local and remote) is asserted unchanged — the agent never touches it. Residual risk: a bad change can land in an open PR. The defaultmergePolicy: 'review'keeps a human merge gate for exactly this reason; opt into'on-green'/'auto'(afterburner merges via the forge) only for repos you trust, and pair'on-green'with averifygate so a red build can't land. - Spending. Capped by the live-backend opt-in (dry-run unless
agent.backendis a live engine;codexalso needsallowCodexLive), the both-caps budget gate plus safety margin, the per-task token ceiling, and the Fable gate;afterburner logis an append-only record of every run. Residual risk: with a Fable model explicitly armed, a run bills real money up to your configured caps. - Secrets. Environment variables only (
.env.exampledocuments them); subscription runs strip API-key auth from the child process so billing can't be hijacked. Residual risk: anything in the allowlisted repo or your.envis readable by the agent.
Naming
The short alias is abr, not ab. On most macOS and Linux systems ab is ApacheBench, and
shadowing it would break benchmarking setups.
Roadmap (out of scope for now)
Forge support beyond GitHub (gh), prebuilt single binaries and a
Homebrew tap (the build is set up so these are easy to add later), a standalone MCP server, and any
web dashboard or vendor notification integration. The Notifier interface is the extension point for that last one.
Star history
If Afterburner turned some idle quota into something useful, a star helps other people find it.
Contributing and license
See CONTRIBUTING.md (and DECISIONS.md for the reasoning behind the less obvious choices), SECURITY.md, and CODE_OF_CONDUCT.md. Licensed under Apache-2.0.
