Server data from the Official MCP Registry
Work-queue kernel for AI coding agents: dependencies, worktree isolation, quality gates, recovery
About
Work-queue kernel for AI coding agents: dependencies, worktree isolation, quality gates, recovery
Security Report
Valid MCP server (1 strong, 1 medium validity signals). No known CVEs in dependencies. Package registry verified. Imported from the Official MCP Registry.
3 files analyzed · 1 issue found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
What You'll Need
Set these up before or after installing:
Environment variable: DDFLOW_REPO
Environment variable: DDFLOW_AGENT
How to Install
Add this to your MCP configuration file:
{
"mcpServers": {
"io-github-delian-ddflow-mcp": {
"env": {
"DDFLOW_REPO": "your-ddflow-repo-here",
"DDFLOW_AGENT": "your-ddflow-agent-here"
},
"args": [
"ddflow-mcp"
],
"command": "uvx"
}
}
}Documentation
View on GitHubFrom the project's GitHub README.
ddflow
A portable, agent-agnostic work-queue kernel for AI coding agents.
You keep a queue of phases and tasks with declared dependencies. You say "implement phase P2". Independent tasks fan out to parallel agents in isolated git worktrees; dependent ones wait. Every task passes a quality pipeline whose gates cannot be passed by assertion. If an agent crashes, its work is found rather than lost. If everything except the log is destroyed, the project's decision history rebuilds from the log alone.
Two dependencies beyond python3 and git (Jinja2, for the prompt templates, see
Extending it by writing text, not code; and
tomlkit, which edits .ddflow/config.toml without losing its comments). Everything else is an optional extra, none needed for the core: ddflow[search] (rapidfuzz) and ddflow[rag] (model2vec) are in use, with BM25 and difflib as the fallback; sqlite-vec (also in ddflow[rag]), ddflow[watch] (watchfiles) and ddflow[mcp-sdk] (the MCP SDK, for a future network transport) are declared and not yet used. A check that needs an absent extra is recorded unavailable, never passed. Works with Claude Code, Gemini CLI,
Codex, Copilot, Cursor, Kimi, opencode, Aider, a CI job, a Makefile, or a human at a
terminal — over a CLI
and an MCP server that are the same implementation.
Instruction for an agent reader
If you are an AI agent and were asked to read this README, this section is your shorthand. Everything below it is detail.
What ddflow is. A work queue with rules the tools enforce, for projects that agents
build. Work is phases and tasks with dependencies and declared file globs. Each task gets
a lease and its own git worktree, then passes a gate pipeline: a check that could not run
is unavailable, never passed; one reviewer must be from another model family; a bug
closes only with a regression test that failed first. Everything is recorded in an
append-only log in .ddflow/events/, committed with the code. ddflow writes none of your
project's code — you do; it adds only its own config, a rules block and git hooks.
Every operation is both a shell command (ddflow …) and an MCP tool (ddflow_…).
If the project already uses it (.ddflow/ exists): call ddflow_brief (or run
ddflow brief) first and follow it. It replaces reading the project's rule and lesson
files. Then: ddflow_next → ddflow_claim → work only in the worktree it returns →
ddflow_gate_status, satisfy each gate → ddflow_merge → ddflow_complete. The full
driver is docs/ddflow/drivers/implement-phase.md in that project.
To onboard a project, ask the user first: it installs a tool, registers an MCP server and writes files in their repository.
- Install:
uv tool install git+https://github.com/delian/ddflow-mcp(not on PyPI yet). - In the project root:
ddflow adopt --agents claude(your agent's name; see Wiring it into your agent). It writes.ddflow/, the MCP registration, the commit hook and a rules block inAGENTS.md. Restart the agent session so it loads the MCP server. ddflow importlists the plans, lessons, decisions and unmerged branches the repository already has, and writes nothing. Runddflow import --applyonly once the user agrees with that list.ddflow config --set gate.unit_tests.command "<their test command>". Thenddflow companionslists the tools the gates expect that are missing: propose them, never install one unasked.- Put the user's plan in the queue (
ddflow phase add …,ddflow task add … --globs …) and finish withddflow doctor.
Exit codes, everywhere: 0 ok · 1 failure · 2 could not run / nothing to do · 3
refused. Never treat 2 as 0.
Everything is yours to change, per project
ddflow ships defaults, never a fixed process. Every part of how it works is a file or a
setting in your repository, and each project can differ from the next: the gate
pipeline and each gate's command or prompt, which reviewers run, the rules your agents
follow, every prompt an agent is handed (including the instructions it receives the
moment it connects), the slash-command workflows, your own [[macro]] modes, the export
document templates, the branching and release model, parallelism and lease limits,
cadences, enforcement strictness, and the per-agent driver docs. Nothing is hard-wired
except the four enforced rules at the top of this page, and even those are tuned through
documented knobs, never silently bypassed.
Three ways to change anything, all validated before anything is written:
- Edit the file. It is plain TOML or Markdown under
.ddflow/(committed, shared by every clone) or.ddflow/local/(git-ignored, yours alone). - Use the CLI (
ddflow config --set,ddflow workflow …,ddflow prompts eject,ddflow rule …,ddflow export eject). - Ask your agent, which has the same operations as MCP tools (
ddflow_configure,ddflow_workflow_*,ddflow_rule_*). It changes a project's workflow only with your agreement.
The complete list of what can be changed, and where, is the Customisation reference at the end of this page.
Introduction
The problem it solves
An AI coding agent is good at a task and weak at a project. One agent in one session mostly works. Run it for weeks, or run three at once, and the same failures come back:
- Work disappears. A session crashes or is closed mid-task, and the half-finished change sits in a directory nobody remembers.
- Agents collide. Two of them edit the same file, and the second merge quietly undoes the first.
- Checks that never ran look like checks that passed. The linter was missing, the reviewer endpoint was down, the tests were "run" in a summary. The agent reports done, and nothing on record says otherwise.
- The project forgets. Last week's hard-won lesson, the reason behind a design choice, the bug that was already fixed once — gone at the next session, or at the next context compaction in this one.
- Nobody can say what happened. Which instruction led to which change, and which review looked at it, lives in a chat transcript that no longer exists.
ddflow is the layer between you and your agents that makes those failures structurally hard rather than a matter of discipline. It does not write code and it is not an agent. It is a queue, a set of rules the tools enforce, and a log of everything that happened.
What changes for you
| Without it | With ddflow |
|---|---|
| You decide what each agent does next, and keep the plan in your head or a chat. | The plan is a queue of phases and tasks with dependencies. ddflow next says what can start now and why everything else is blocked. |
| Parallel agents step on each other. | ddflow claim gives each task a lease and its own git worktree; tasks that declare overlapping files are refused, not merged over. |
| "Done" means the agent said so. | Every task passes a gate pipeline you configure. A gate that could not run is recorded unavailable, never passed; at least one reviewer must come from a different model family than the author; a bug cannot be closed without a regression test that failed first. |
| A crash loses work. | ddflow recover finds orphaned worktrees and reports what each holds. It never deletes work. |
| Every session starts from zero. | Lessons, decisions, research verdicts, bugs and your own prompts are recorded as you go. ddflow brief hands the agent the ones relevant to this task in a bounded amount of context, and ddflow recall searches all of it. The same brief also names the project's own skills, commands and rules files (.claude/skills, .claude/commands, .cursor/rules, .clinerules, AGENTS.md/CLAUDE.md) that bear on the task, by name and path only. |
| History is a transcript. | An append-only event log, committed in git. The board, the index and the reports are rebuilt from it; ddflow replay reconstructs the project's decisions from the log alone. |
Who it is for
- One developer with one agent. A plan that survives the session, a memory that survives compaction, and a record of which checks really ran. The queue is useful even with no parallelism at all.
- Several agents in parallel — subagents, several terminals, several vendors. The dependency graph says which tasks are independent, worktrees keep them apart, and the merge step lands them without anyone switching the main checkout's branch.
- A team or a CI pipeline. The log is committed with the code, so a fresh clone
knows the queue and its history. Read commands have a machine-readable
--jsonform and every command returns the same four exit codes, so a Makefile or a CI job can drive it exactly as an agent does.
It works with the agent you already use, because everything it does is reachable both ways: as a shell command and as an MCP tool. Use whichever your agent, script or CI job has. Your workflow is text, not code — the gate pipeline, the reviewer instructions and the agent-facing prompts are files in your repository that you can edit.
What it is not
- Not an agent or a model. Your agent does the work; ddflow decides what may start, checks what was claimed, and remembers.
- Not a hosted service. Everything is files in your repository and a disposable local cache. No account, no server to run beyond the local MCP process.
- Not a replacement for your tests or CI. It runs the commands you configure and records their real exit codes and output.
A first run
# ddflow-mcp is not on PyPI yet; until the first release, install from the repository:
uv tool install git+https://github.com/delian/ddflow-mcp # or: pipx install git+https://github.com/delian/ddflow-mcp
cd /path/to/your/project
ddflow adopt # registers the MCP server with your agents, writes .ddflow/ and a block in AGENTS.md
ddflow phase add P1 --title "Password reset"
ddflow task add P1.T1 --phase P1 --title "Reset-token endpoint" --globs 'src/auth/**'
ddflow next # what can start now, and why the rest is blocked
adopt registers the server you just installed, by its full path: an install that did
not come from a package index (from git, a local directory or an archive) carries a
direct_url.json in its metadata (PEP 610), and
for one of those adopt writes the ddflow-mcp installed beside its interpreter rather
than uvx ddflow-mcp, which would fetch from PyPI. Only an install from an index gets
uvx. --launch python still forces the interpreter-plus-PYTHONPATH form.
Then tell your agent "implement phase P1". The driver adopt installed tells it to
start with ddflow_brief, claim the task, work in its own worktree, satisfy each gate
and land the change. ddflow cannot make an agent follow instructions, but it makes
skipping them visible: the commit hook adopt installs flags a commit made without a
lease (or refuses it, if you set [enforce].commit_without_lease = "block"), and
ddflow complete refuses an item whose gates carry no outcome. Watch it with
ddflow board, and ask ddflow doctor at any point whether the project is healthy.
How do I…?
Every row is a command you can run in a terminal and a tool an agent can call over MCP — the same implementation, so neither drifts from the other.
| I want to… | CLI | MCP tool |
|---|---|---|
| see what the workflow is | ddflow workflow | ddflow_workflow |
| onboard an existing project | ddflow onboard status (standing drift report; also preflight, legacy, memory, test-gate, verify; propose by default, --apply acts, --accept NAME approves one item) | ddflow_onboard (stage, apply, accept) |
| the pre-push checks, on the merge result | ddflow ci run (the ci gate; ddflow ci status shows what would run): a scratch worktree of your branch merged with the base, then the project's own pre-commit run --hook-stage pre-push (or [ci].command, run as written; with the default, a language: fail tripwire hook runs on the diff being checked, not over every file); exit 0 passed, 1 failed, 2 could not run (never a pass). After a merge lands, [ci].on_merge (fast default: the pre-commit set without the test hooks; full; off) checks the base, records a ci.result and files a bug and fix task per failing check; the pre-push hook reports with ddflow ci record | ddflow_ci (run, status) |
| check a done task really is done | ddflow verify <id> (or --all / --phase P to sweep every done task, worst first, --file-bugs to file what fails; --reopen sends a completion that fails back to the queue with its gates cleared (--reason says why; --force reopens one that holds); --pack prints the evidence pack (requirement fenced as data, what landed, mechanical findings) for an independent verifier and --judge hands it to the cross-family reviewer (gate verify, optional, never part of the default pipeline); on a task that is not done it names work that landed anyway): landed on main, declared files exist, tests exist, no gate failed or skipped without a reason (exit 1 = a claim does not hold) | ddflow_verify |
| what a finished task required and changed | ddflow show <id> on a done task prints its completion ledger: requirement digest, files and tests the landing changed, skipped gates, forced flag, later amendments | ddflow_show |
| one-page state of the project | ddflow workflow state | ddflow_workflow_state |
| project rules | ddflow rule add|edit|list|search|show|remove | ddflow_rule_add · _edit · _list · _search · _show · _remove |
| change the workflow | ddflow workflow pipeline task … · workflow gate <id> … · workflow drop <id> | ddflow_workflow_pipeline · _gate · _drop |
| change any setting | ddflow config --explain · --set <key> <value> | ddflow_configure |
| add a phase / a task | ddflow phase add P1 --title … · ddflow task add P1.T1 --phase P1 --globs 'src/**' | ddflow_phase_add · ddflow_task_add |
| get a plan into the queue | see From plan mode to the queue | same |
| know what to work on | ddflow next | ddflow_next |
| start a task | ddflow claim <id> → work → ddflow gate … → ddflow merge → ddflow complete | ddflow_claim, ddflow_gate_*, ddflow_merge, ddflow_complete |
| see everything about one item or bug | ddflow show <id> (phase, task or bug id) | ddflow_show |
| see progress / effort | ddflow progress · ddflow status · ddflow board | ddflow_progress · ddflow_status · ddflow_board |
| find out if we're going in circles | ddflow loops | ddflow_loops |
| see which agents are working, and what each needs next | ddflow lanes [--watch] · ddflow lanes brief <lane> · ddflow lanes advise (read-only; see Lanes) | ddflow_lanes (view, lane) |
| see where the time went, and when a phase will end | ddflow metrics · ddflow metrics forecast [--phase P] · ddflow metrics retro <id> · ddflow metrics skips · ddflow metrics lanes (read-only, from the log; a figure under [metrics] min_samples is n/a, never 0) | ddflow_metrics (view, item, phase, since, group_by) |
| record a lesson / decision / research / bug | ddflow lesson add · decision add · research · bug found|fixed | ddflow_lesson_add · ddflow_decision_add · ddflow_research_add · ddflow_bug_* |
| search everything the project remembers | ddflow recall '<regex>' | ddflow_recall |
| search for people: tasks, bugs, research, decisions, lessons, sessions, prompts, rules, skills, agents, jobs, schedules, log | ddflow search '<text>' [--exact|--regex] [--kind K] [--source S] [--state S] [--phase P] [--owner A] [--since D] [--limit N] [--json] -- see Searching everything | ddflow_list kind=search (query, mode, sources, source) |
| check a text against what is already filed (read-only) | ddflow similar '<text>' [--kind bug,task,...] [--json] -- exit 0 with candidates, 2 with none | ddflow_similar |
| find records filed twice | ddflow dupes [--kind bug,task,...] [--open-only] [--floor F] [--limit N] [--json] -- exit 0 with pairs, 2 with none | ddflow_dupes |
| settle a near-duplicate pair | ddflow link <a> --duplicate-of|--extends|--related|--distinct <b> [--reason ...] | ddflow_link |
| record what happened this session | ddflow session start|prompt|note|end | ddflow_session_* |
| list tasks / phases / bugs / research | ddflow task|phase|bug|research list [--state S] [--phase P] [--tag T] [--owner A] [--since D] [--limit N] [--offset N] [--json] -- see Listing; bug list shows open bugs unless --all | ddflow_list (kind, state, phase, tag, owner, since, limit, offset, all) |
| read the engineering log | ddflow history [--item X] [--kind K] [--agent A] [--tail N] [--json] -- compact line per event (time, agent, subject, verb, summary); --agent keeps one agent's shard, --tail N the last N oldest-first, --json cuts payload strings over 500 chars and marks the event truncated | ddflow_history |
| check the tooling around the gates | ddflow companions | ddflow_companions |
| find which earlier test file makes a test fail only in full-suite order | ddflow bisect VICTIM --cmd 'pytest -q {tests}' [--candidates a,b] [--glob G] [--timeout S] [--repeat N] [--max-runs N] -- delta-debugs the files before the victim, running your command many times (exit 0 = found, 2 = nothing to report); see Finding a test polluter | ddflow_bisect (glob, repeat and max_runs are CLI-only) |
| check a companion really is an MCP server | ddflow companions --verify [--id X] -- launches each registered or installed MCP companion and requires a JSON-RPC answer to initialize (spawns processes; opt-in; exit 1 = not a server, 2 = could not tell) | ddflow_companions_verify |
| find work a crashed agent left | ddflow recover | ddflow_recover |
| check the project's integrity | ddflow doctor · ddflow doctor --accept-lost-events (the operator's word that events a history rewrite took out of a shard are known, see Events that vanished from a shard) | ddflow_doctor (--accept-lost-events is CLI-only) |
| see what upgrading this project to the running ddflow would change | ddflow upgrade [--plan] (alias ddflow doctor --upgrade) -- the plan, by category: data repairs, migrations (registered breaking-change migrations and the files each would rewrite), contested records (a decision, lesson or research id two agents defined differently: each is listed with its rivals and the ddflow resolve command; an apply prints it and resolves nothing, the MCP connect proposal and the upgrade notice mention it), config (new knobs, changed defaults; a value anyone set is marked needs operator confirmation), instructions (drifted driver docs and rules, stale after a release or hand-edited), hooks, MCP launch, opt-in features. Writes nothing; exit 0 up to date, 1 while the plan has items. Do it: ddflow upgrade --apply [CATEGORIES] [--snapshot] [--confirm KEY ... --reason WHY]; undo it: ddflow upgrade --restore [NAME] (see "Applying an upgrade") | ddflow_upgrade (apply, confirm, reason, snapshot, restore) |
| rebuild everything from the log | ddflow replay --verify | ddflow_replay |
| invoke a workflow / a mode of your own | ddflow prompts list · prompts get <name> [--arg KEY=VALUE] (rendered, exactly as prompts/get gives it) · prompts show <name> (its source) | prompts/list · prompts/get |
| see what this project left undone | ddflow doctor · ddflow status | the footer on tool results |
| ask the tool to explain itself | ddflow help [topic] | ddflow_help |
Every read command takes --json. Every exit code means the same thing everywhere:
0 healthy · 1 real failure · 2 could not run / nothing to do · 3 coordination
refused. 2 is never collapsed into 0 — "nothing is ready" and "everything is
fine" are different facts, and an agent that cannot tell them apart invents work.
What --json and the MCP tools return has a name. A result that is a JSON object carries a
top-level "schema": "<command>@<n>" -- for example "claim@1"; the command is the MCP tool's
name without ddflow_, and --json of the CLI command that tool serves says the same. Within
a version fields are only ever added; removing or retyping one bumps n. On a refusal the
refusal object still leads and the tag follows it. A result that is a bare array
(progress, loops, lesson search, ...) keeps its exact shape and has no tag, and text
bodies (board, doctor) have none. python -m ddflow.surfaces.tool_table --schemas prints
every tool's declared result schema; tests/golden/json/result_schemas.json pins them.
Table of contents
- Instruction for an agent reader
- Everything is yours to change, per project
- Introduction
- How do I…?
- Help: what it can do, and the workflow
- The default workflow at a glance
- Two ways to drive it
- The workflow, and changing it
- Why it is built this way
- Install into any project
- Pin files regenerate; they are never hand-merged
- Finding a test polluter
- Wiring it into your agent
- From plan mode to the queue
- When a companion is missing
- Adopting a project that already has history
- The model: phases, tasks, dependencies, globs
- Work that changes shape while you do it
- Architectural decisions
- Recall — "have we been here before?"
- Operational memory
- Resources and long-running jobs
- Dependencies on another repository
- Status, progress, and loops
- The task pipeline
- The phase pipeline
- Human approval: a gate the agent cannot clear
- Parallelism and coordination
- Gitflow, pull requests and version tags
- Many agents, one server: identity, state and sharing
- Crash recovery
- Reconstruction from logs alone
- Lessons that check themselves
- Checking that the checks are working
- Reading the log, and why it is never compacted
- Events that vanished from a shard
- Managed definitions: the
def.*event kinds - A log from a newer ddflow, and the link event kinds
- The compatibility contract
- Upgrading ddflow
- Upgrading a project: the whole picture
- The version stamp and the skew guard
- Versioned data repairs
- The upgrade manifest: what changed since your version
- Migrations: breaking changes P-unify makes to what a project holds
- Applying an upgrade
- The compaction that was declined
- Lessons, research and bugs
- Cadences
- Exporting documents
- Keeping AGENTS.md true
- Surviving a compaction
- Keeping session-start cost flat
- Agent portability
- Keeping the two surfaces honest
- Command reference
- Configuration
- Id schemes
- What is automated, and what is not
- Customisation reference
- Testing
- Documentation index
Help: what it can do, and the workflow
$ ddflow help # what this is, the loop, every capability grouped
$ ddflow help workflow # workflow · import · gates · parallel · memory · recovery · config
Reachable as ddflow_help over MCP, and that is the point: an agent connecting had 59
tool descriptions and a state-aware handshake, neither of which answers "what is this,
and how am I meant to work here". A tool description explains one tool to someone who
already picked it; the handshake describes this repository right now.
Two halves, deliberately:
- The narrative is a template under
ddflow/templates/prompts/help/, soddflow prompts eject-style overriding applies — put your own.ddflow/prompts/help/workflow.mdin place and the tool teaches your workflow. - The capability inventory is generated from the live tool table. A hand-kept command list in a second place is the documentation-drift class, and this project has paid for it twice.
Three ratchets keep the prose honest, because a page recommending a flag that was renamed is worse than no page — whoever finds nothing reads the code, and whoever finds a wrong answer trusts it. Every command a page names must exist as a CLI leaf or an MCP tool; every topic the index offers must resolve; and every tool must fall into a group, so a new capability has to be classified rather than quietly dropped from an inventory that claims to be complete.
The default workflow at a glance
Three pictures of what ships by default. Every step is configurable (see
The workflow, and changing it); ddflow workflow
prints what this project actually runs.
The agent's loop. One item at a time: pick it, lease it, clear its gates, land it.
Each arrow labelled with an exit code is what the tool says, not a convention —
2 means nothing to do, 3 means refused, and neither is ever read as success.
flowchart TD
S["Session start<br/>ddflow brief · recover"] --> R{"Crashed agent's<br/>work left over?"}
R -- yes --> SV["Inspect the worktree, salvage,<br/>ddflow release"] --> N
R -- no --> N["ddflow next"]
N -- "exit 2: nothing ready" --> W["ddflow wait<br/>sleeps until a holder lets go"] --> N
N -- "exit 0: items ready" --> C["ddflow claim<br/>lease + isolated git worktree"]
C -- "exit 3: refused<br/>(lease or file-glob conflict)" --> N
C --> P["Task pipeline<br/>satisfy every gate in order"]
P --> M["ddflow merge<br/>lands the branch from the primary checkout"]
M --> D["ddflow complete<br/>checks every gate has an outcome<br/>+ a different-family review"]
D -- "exit 3: refused" --> P
D -- done --> N
With [flow].integration = "pr", merge opens a pull request and parks the item in
review instead; next completes it when the request merges.
A lease is evidence of intent, not a lock, but a LIVE lease held from another clone is not
overwritten by accident: release and gate run|record|skip on it exit 3 naming the holder,
unless you pass --force --reason "<why>" (CLI only; recorded as forced on the event).
Agents of the same clone, an expired lease and a lease with no recorded clone are unaffected.
The task pipeline. Ten gates, in order. Heavy borders are the gates
gates.required names by default (implement, unit_tests, merge); the rest still
need some outcome — passed, failed, unavailable, partial, or an explicit skip with a
reason — because silence is not a pass.
flowchart LR
subgraph A["You, the agent"]
direction TB
g1["1 · research<br/>falsifiable claim + probe"] --> g2["2 · rules<br/>ddflow brief --item"] --> g3["3 · implement<br/>in the item's worktree"]
end
subgraph X["A different model family"]
direction TB
g4["4 · rubber_duck<br/>try to refute it"] --> g5["5 · critic<br/>diff vs. stated intent"]
end
subgraph T["Tooling"]
direction TB
g6["6 · standards<br/>linters, architecture"] --> g7["7 · unit_tests<br/>the suite, executed"]
end
subgraph B["You, again"]
direction TB
g8["8 · bug_hunt<br/>recurring bug classes"] --> g9["9 · dedupe<br/>already exists?"]
end
g10(["10 · merge<br/>ddflow lands it"])
A --> X --> T --> B --> g10
classDef req stroke-width:3px
class g3,g7,g10 req
The phase pipeline. A phase wraps its tasks and checks the whole before it lands:
flowchart LR
p1["research<br/>the phase's open questions"] --> p2["tasks<br/>each runs its own<br/>ten-gate pipeline,<br/>in parallel where<br/>globs allow"]
p2 --> p3["unit_tests"] --> p4["bug_hunt"] --> p5["dedupe"]
p5 --> p6["live_test<br/>run the real thing"] --> p7["corrections"] --> p8["docs<br/>README and docs<br/>match the change"] --> p9(["merge"])
Details: The task pipeline · The phase pipeline · Parallelism and coordination · Crash recovery.
Two ways to drive it
The CLI is the whole product. The MCP server is a second surface over the same
commands, and tests/test_mcp_parity.py fails if the two diverge — every subcommand has
a tool, every flag is reachable, and each exemption carries a written reason.
Standalone: a terminal, a Makefile, CI
$ ddflow init
$ ddflow config --set gate.unit_tests.command "python -m pytest -q"
$ ddflow phase add P1 --title "Billing" --globs "src/billing/**"
$ ddflow task add P1.T1 --phase P1 --title "Tax rules" --globs "src/billing/tax.py"
$ ddflow next # exit 2 = nothing actionable; exit 1 = unknown --phase
$ ddflow claim P1.T1 # exit 3 = refused, with the reason
leased P1.T1 · worktree .ddflow/worktrees/P1.T1 · branch ddflow/P1.T1
$ cd .ddflow/worktrees/P1.T1 && ... # do the work
$ ddflow gate status P1.T1 # what the pipeline wants next
$ ddflow gate run P1.T1 unit_tests # runs it; the exit code IS the evidence
$ ddflow gate record P1.T1 implement --outcome passed --evidence "added tax.py"
# failed/unavailable/partial/skipped also need --reason
$ ddflow complete P1.T1 # exit 3 lists whatever is unsatisfied
$ ddflow merge P1.T1
You get everything except the judgement. Command gates run themselves; agent gates wait
for a human to record an outcome, and ddflow gate skip <id> <gate> --reason "..." is
the escape hatch — recorded as a skip, never as a pass.
Merge queue. Where several agents land work at once, ddflow queue add <id> enqueues an item,
ddflow queue run (any agent may) integrates the head of the queue — one entry's ci at a time,
--max-batch N entries per run, --unit-tests / --no-unit-tests to run or skip each entry's
unit_tests gate on the merged result — ddflow queue status (the default) prints the line, and
ddflow queue remove <id> drops an entry. Defaults live in [merge_queue].
Changelog line (optional). ddflow complete P1.T1 --changelog "Added: tax rounding" (and
ddflow bug fixed B1 --regression-test ... --changelog "Security: ...", MCP changelog on
ddflow_complete / ddflow_bug_fixed) records one line for the project's changelog on the
completion event. The category is one of Added, Changed, Deprecated, Removed, Fixed, Security
(case-insensitive; anything else is refused with that list); --changelog skip (or internal)
marks work that must not appear in the changelog. complete never asks for it and never
requires it, and logs without it fold exactly as before.
In CI, the exit codes are the interface:
check:
ddflow doctor # 1 = integrity problems, each named
ddflow workflow # 1 = the pipeline does not hang together
ddflow cadence # 2 = no periodic pass is due
2 is never "no problem". A job that treats it as success reports a green build for a
suite that never ran.
Every command
Every top-level command, with the first line of its --help. The list is generated from the
command parser (python -m ddflow.surfaces.command_table README.md rewrites it, and
ddflow pins regenerate does so after a merge), so a command added on another branch never
needs a line written by hand here.
Documentation truncated — see the full README on GitHub.
Reviews
No reviews yet
Be the first to review this server!
More Developer Tools MCP Servers
Rea
Freeby Morluto · Developer Tools
Reverse engineer anything from your terminal or agent with one CLI and MCP server.
Paperclip
Freeby Paperclipai · Developer Tools
Trending hip-hop artist momentum scores across four cultural dimensions.
Git
Freeby Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
Fetch
Freeby Modelcontextprotocol · Developer Tools
Web content fetching and conversion for efficient LLM usage
Toleno
Freeby Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
MCP Marketplace
Freeby mcp-marketplace · Developer Tools
Search and install MCP servers from inside your AI client.
