| title | status | date | parents | tags | input | output | position | ||
|---|---|---|---|---|---|---|---|---|---|
dagain |
active |
2026-02-02 |
|
GitHub/npm readers and CLI users |
User-facing docs for `dagain` |
Repo/package README and primary usage reference |
DAG-based orchestration for coding agents (Codex, Claude Code, Gemini).
Dagain runs a work graph (nodes + deps) stored in SQLite, and executes each node with a configured runner. It’s built to keep agents “fresh”: context is loaded from the graph/DB when needed, not carried indefinitely in prompts.
Once published to npm:
npx dagain --helpOr install globally:
npm i -g dagain
dagain --help# 1) init state + config (creates .dagain/)
dagain init --goal "Add a CLI flag --foo and tests" --no-refine
# 2) run the supervisor (defaults to 3 workers; drops into chat on completion)
dagain run --live
# disable post-run chat:
dagain run --no-post-chat
# 3) in another terminal: check status / interact
dagain status
dagain chat # TUI by default on a real terminal
dagain chat --plain # force the plain readline REPL (useful for piping / non-TTY)
dagain control resume # enqueue resume (auto-starts supervisor if stopped; add --no-start to enqueue only)
# 4) optional: live dashboards
dagain tui # terminal dashboard + chat (shows a GUI URL)
dagain ui # web dashboard (chat left + DAG + node logs, runs drawer, pan/zoom+fit, controls)Note: if you run dagain as root (e.g. via sudo) inside a repo, it will prefer executing runners as the repo owner to avoid root-owned outputs.
Inside dagain chat (both TUI and --plain):
/status— print graph status/run— start supervisor/pause//resume— stop/resume launching new nodes (in-flight nodes finish)/workers <n>— set concurrency (default: 3)/replan— force plan node (plan-000) to reopen and block launches until it completes/cancel <nodeId>— cancel a running node (best-effort)/answer [nodeId] <answer...>— answer a checkpoint and reopen aneeds_humannode/artifacts [nodeId]— show run artifact paths (and last stdout/result for a node)/memory//forget— inspect/reset chat memory stored in SQLite KV
Dagain is a DAG of nodes:
plannodes decompose goals into taskstasknodes do work (code, analysis, etc)verifynodes check task outputsintegratenodes merge/roll up resultsfinal_verifynodes do final checks
Dependencies live in the deps table. A dep can require:
done(default): upstream must bedoneterminal: upstream must be terminal (doneorfailed) — useful for “investigate failure” / escalation flows
All durable state is in .dagain/state.sqlite:
nodes/deps— the DAG and statuseskv_latest/kv_history— durable “memory” and artifactsmailbox— supervisor control queue (pause/resume/workers/replan/cancel)
Chat memory is stored in KV under node_id="__run__":
chat.rollup— rolling summary (router-maintained)chat.turns— last ~10 turnschat.last_ops— last emitted ops JSONchat.summary— last assistant reply
Dagain keeps the model from directly mutating state by having it emit ops. The host applies them safely.
In dagain chat, the router can emit:
control.*ops (pause/resume/workers/replan/cancel)ctx.*ops (read-only context requests likectx.readFile,ctx.rg,ctx.gitStatus) — Dagain executes these and re-invokes the router with resultsnode.add,node.update,node.setStatusdep.add,dep.removerun.start,run.stop,status
Runners are just shell commands that receive a {packet} filepath and should print:
<result>{...json...}</result>
Configure them in .dagain/config.json:
{
"version": 1,
"runners": {
"codex": { "cmd": "codex exec --yolo --skip-git-repo-check -" },
"claude": { "cmd": "claude --dangerously-skip-permissions -p \"$(cat {packet})\"" },
"gemini": { "cmd": "gemini -y -p \"$(cat {packet})\"" }
},
"roles": {
"planner": "codex",
"executor": "codex",
"verifier": "codex",
"integrator": "codex",
"finalVerifier": "codex"
}
}Notes:
- Dagain strips Claude’s
--dangerously-skip-permissionswhen running as root. - For speed, you can set
defaults.verifyRunnertoshellVerifyso verification doesn’t use an LLM.
dagain run --workers Nruns up toNnodes concurrently (subject to ownership locks). If you omit--workers, Dagain defaults to at least 3 workers.- For conflict-prone code edits, set
supervisor.worktrees.mode="always"to run executors in worktrees and merge serially. - If a node reaches
needs_humanin a non-interactive context, the supervisor waits up tosupervisor.needsHumanTimeoutMs(default: 30 minutes), then auto-answers with “decide safest default” and reopens the node so planning can continue. - To unblock
needs_humanimmediately, usedagain answer --node <id> --answer "..."or (in the web UI chat) send/answer [nodeId] <answer...>.
Dagain stores state in:
.dagain/config.json— runner + role configuration.dagain/state.sqlite— workgraph + KV + mailbox.dagain/workgraph.json— human-readable graph snapshot (mirrors SQLite).dagain/lock— supervisor lock (used bydagain stop).dagain/runs/— per-node packets + logs + results- The UI “Log” panel shows human-readable result output (status/summary, checkpoint question) derived from
result.jsonby default; raw stdout is still available in.dagain/runs/*/stdout.logand the Runs drawer. .dagain/artifacts/— non-source outputs (reports, scratch notes, generated data).dagain/checkpoints/— human-in-the-loop checkpoints.dagain/memory/— durable notes + logs (task_plan.md,findings.md,progress.md)
gh repo create knot0-com/dagain --public --source=. --remote=origin --pushIf you don’t have permission to create repos in knot0-com, create a staging repo under your user and transfer it:
gh repo create <you>/dagain --public --source=. --remote=origin --pushThen transfer via GitHub UI: Settings → General → Transfer ownership.
Publishing is automated via GitHub Actions on version tags (vX.Y.Z). The tag must match package.json.version.
-
Configure npm Trusted Publishing (OIDC) for
knot0-com/dagainand workflow filenamenpm-publish.yml(npmjs.com → package Settings → Trusted Publisher). -
Cut a release:
npm version patch
git push --follow-tags- Verify:
npx dagain --help- Ensure you’re logged in:
npm whoami- Publish:
npm publish --access publicThen:
npx dagain --help