@naxodev/apnea
v0.2.1
Published
Host-neutral multi-role workflow engine and standalone Bun CLI
Maintainers
Readme
@naxodev/apnea
Apnea drives a multi-role development loop — plan, review, code, review, verify, commit — where each role runs in its own real terminal pane and hands off work through files on disk instead of a hidden subagent. Any harness that can run a shell command can hold the orchestrator seat.
The loop
plan → plan review → phase package → code → code review → verify+commit → …
→ pr-descriptionRoles can be different harnesses (Pi, Claude, Codex, …) via global profiles. Project config only rebinds roles to profile names that already exist.
Requirements
- bun
>=1.3.7. Needed to run the tool, not just to build it: the installedbinisdist/cli.jswith a#!/usr/bin/env bunshebang, and npm does not enforce theengines.bunkey. If you install@naxodev/apneaglobally with onlynodeonPATH, theapneacommand will fail on first invocation — this is the most likely first-run failure for a new user. - herdr, for reusable interactive pane dispatch.
- jj or git. Per ADR 0007, if neither is present auto-commit is refused.
- At least one agent CLI —
pi,claude, orcodex.
Install
bun install -g @naxodev/apnea
# or
npm install -g @naxodev/apneaFor Pi, install the separate adapter:
pi install npm:@naxodev/pi-apneaFrom source, for contributors:
cd packages/apnea
bun install
bun run build
./dist/cli.js helpOptionally put it on PATH, e.g. ln -s "$(pwd)/dist/cli.js" ~/.local/bin/apnea.
Sixty-second quickstart
apnea setup— writes global profiles to~/.config/apnea/config.json.apnea start "<goal>"— starts a run against your working copy.apnea status— a read-only snapshot of where the run stands and what to call next.
apnea status with no run in progress looks like this:
$ apnea status
OK: no active run
next: apnea start
{
"has_state": false
}CLI reference
Any harness that can run a shell command can hold the orchestrator seat — the CLI and the Pi
tools share one definition in extension/registry.ts, so they cannot drift apart (see
ADR 0009).
Operations
One row per operation. The CLI verb and the /apnea subcommand are the same word — they share a
single definition in extension/registry.ts, so they cannot drift apart (see
ADR 0009). The two were listed as separate tables until one
of them went stale; a reader could not tell which.
| Operation | Pi tool | Flags | Purpose |
| --------------------- | ----------------------- | -------------------------------------------- | -------------------------------------------------------------- |
| setup | — | [--project] [--force] [--agents-md] | global profiles, optional project bindings, AGENTS.md primer |
| start <goal> | workflow_start | [--allow-dirty] [--slug=name] (CLI only) | start a run |
| resume / abandon | workflow_start | | resume or abandon |
| status | workflow_status | | read-only snapshot |
| dispatch <kind> | dispatch_role | [--rework] [--redeliver] | launch or explicitly redeliver a role |
| wait | workflow_wait | [--poll=<ms>] [--budget=<ms>] (CLI only) | wait for the pending artifact |
| commit [message] | workflow_commit_phase | [--done] | verify + commit phase |
| reset-rounds <gate> | — | [--i-am-human] (CLI only) | human only |
Prefix with / inside Pi (/apnea status), or run it as a shell command (apnea status).
/apnea-start and /apnea-status are short aliases.
--rework remains through 0.2.x as a deprecated assertion. Persisted review state selects and
authorizes rework even when callers omit the flag. Caller input grants authority only for
ambiguous version-1 plan or code migration. --redeliver reuses matching pending ownership without
advancing the round. Use it only after proving the prior pane is dead; a manual dispatch with no
pane requires the operator to request redelivery explicitly. Apnea persists whether pending work
crossed a manual or interactive boundary. Interactive ownership without a saved pane id refuses as
ambiguous. Legacy null-pane ownership has no safe discriminator and also refuses redelivery.
Before any redelivery checks or mutations, Apnea reads the pending artifact. A complete artifact
refuses redelivery and directs the caller to workflow_wait; review artifacts count as complete only
with a valid verdict and legal, schema-valid rework metadata. Malformed or incomplete artifacts
continue through normal liveness validation.
reset-rounds is not a Pi tool. It exists only as apnea reset-rounds and /apnea reset-rounds.
Only the CLI gates it — it refuses unless stdin/stdout are a terminal and a human retypes the gate
key, or passes --i-am-human. The slash command has no such gate: /apnea is already a human at
a terminal. See ADR 0002.
apnea wait is resumable: exit 3 means the call's budget ran out but the role hasn't timed out,
so call apnea wait again. Exit codes: 0 ok, 1 refused/error, 2 usage, 3 still waiting.
See docs/protocol/config.md for the budget-floor arithmetic behind
--poll and --budget.
Setup flags
/apnea setup # ~/.config/apnea/config.json from PATH
/apnea setup --project # also .apnea/config.json role→profile only
/apnea setup --force # replace profiles; required to replace malformed global JSON
/apnea setup --agents-md # also write/refresh an AGENTS.md loop primer at the repo rootSetup never silently destroys malformed JSON. Without --force, malformed existing global JSON
is left byte-for-byte unchanged and setup refuses. --force atomically replaces it and reports
the replacement. Malformed existing project config always fails closed.
After upgrading from a version with floating panes, old copied
~/.config/apnea/herdr-plugin files are inert. Apnea does not unlink or delete them; remove that
directory manually if you no longer need it.
The @naxodev/pi-apnea adapter applies Pi-specific role launch behavior. The core package remains
host-neutral.
Fallback: skill apnea-setup or prompt /apnea-init (both point at the same rules). No config
UI in v1.
Maturity status
What you can rely on: the loop, the artifact contract, and the CLI are implemented, and the extension suite is green — CI runs it on every pull request.
What may still change: the command surface and config shape may move before 1.0. Breaking
changes will land in minor bumps, not patches.
Non-goals for v1: worktrees, parallel coders, push/PR automation, memory store, native CLAUDE.md injection, force-approve, config UI.
Docs
| Doc | Purpose |
| -------------------------------------------------------------- | ---------------------- |
| CONTEXT.md | Glossary |
| docs/protocol/overview.md | Loop, steps, tools |
| docs/protocol/artifacts.md | Paths + front-matter |
| docs/protocol/config.md | Profiles + trust model |
| docs/protocol/manual-gate.md | Bootstrap acceptance |
| docs/adr/ | Decisions |
| briefs/ | Role briefs |
Contributing
Build, test, typecheck commands, version-control conventions, and what CI enforces are in
CONTRIBUTING.md.
Security
Apnea runs repo-controlled text through agent CLIs by design — read
SECURITY.md for the trust model before pointing it at a repository you don't
trust, and for how to report a vulnerability.
License
MIT — see LICENSE.
