๐ reference โ overview/guide, not tied to a code symbol
Validation by Beadloom
doc_syncโ same source assync-check.
Agentic Dev Flow (packaged) โ
Beadloom's #1 value is a solo multi-agent development flow: Claude Code + Beadloom + Beads + GitHub, run as waves of role subagents (dev โ test โ review โ tech-writer) gated by bead dependencies. That flow is the process that built Beadloom itself. BDL-048 packages it so any repo can adopt it with one command, and exposes its deterministic steps as MCP tools any MCP client can call.
This guide covers:
- the canonical flow:
task-init โ coordinator โ dev/test/review/tech-writer โ push โ Beadloom Gate, - what the packaged flow is and how to scaffold it (
beadloom setup-agentic-flow), - the role configurator (BDL-052):
.beadloom/flow.yml+ the--tool/--stack/--architectureflags,dddvsfsd, the CORE + overlay set composed into per-tool adapters, the drift-guard, and "roles are composer-owned", - the pre-push Beadloom Gate (BDL-052): blocks a push on a red
beadloom ci(--no-verifyis the escape hatch), - the trunk-based development model the flow runs on (BDL-049),
- how
beadloom config-checkkeeps the scaffolded flow honest (--fixrestores it), - the four MCP process-tools (
task_init/bead_context/complete_bead/checkpoint), - the tool-agnostic angle (Claude Code + Cursor adapters; any MCP client via
beadloom setup-mcp), - the honest boundary: orchestration stays in the harness; CI is the true enforcement.
The canonical flow โ
One work item flows through the same wave sequence regardless of tool or stack:
/task-init scaffold the docs folder + a 4-role bead DAG
โ /coordinator orchestrate the waves, gated by bead dependencies
โ dev TDD implementation
โ test tests + coverage
โ review read-only quality gate
โ tech-writer doc refresh
โ git push local authoring (the primary path)
โ Beadloom Gate (pre-push hook) runs `beadloom ci`; blocks the push on red
โ PR to main CI re-runs the Gate as a required check (the true enforcement)The flow is local-primary, CI-fallback: the pre-push Gate catches drift on the author's machine before a push leaves it, while CI re-runs the same beadloom ci on the PR as the authoritative, un-routable enforcement (see the honest boundary). The roles, the coordinator, and the Gate are all generated from one canonical source per the role configurator below.
Trunk-based development (BDL-049 ยท BDL-050 consolidated CI) โ
The coordinator flow is trunk-based: main is the integration point and is branch-protected (no direct push). Each epic/feature runs on a short-lived branch and integrates via a single PR:
- Branch off main โ
git switch -c features/<ISSUE-KEY>. - Commit per wave onto that branch (dev โ test โ review โ tech-writer).
- Open ONE PR to
mainper epic/feature (or shippable slice) โ not one PR per commit. - The PR triggers the consolidated CI pipeline (
.github/workflows/ci.yml, BDL-050):gate(thebeadloom civerdict) โฅtests(the 3.10โ3.13 matrix) โฅsite-build(the VitePress build) run in parallel, then the AI tech-writer job runs only after all three are green (needs: [gate, tests, site-build]) and commits its doc refresh into the PR branch โ code + docs in one reviewable PR, no orphan doc-PRs. - Merge when green โ a human merges once CI is green and any doc refresh has landed. No auto-merge; no direct push to
main, somainstays always-green.
Protect main once per repo (idempotent; safe to re-run):
beadloom setup-branch-protection --repo OWNER/NAMEThis requires a PR to main with the consolidated ci.yml's 7 check-runs as required status checks โ gate, tests (3.10), tests (3.11), tests (3.12), tests (3.13), site-build, ai-techwriter (BDL-050). Strict trunk-based keeps enforce_admins: true (even the owner integrates via a PR) with 0 required reviews, so the solo maintainer self-merges but main is never bypassed (BDL-049). The vendored .claude/CLAUDE.md ยง6 (Git) and .claude/commands/coordinator.md describe this same model, so a scaffolded repo gets the trunk-based flow by default. CI on the PR is the true enforcement โ the agent's refresh and the deterministic gate are proposals/checks; the human merges.
What the packaged flow is โ
The flow lives in a project's tool tree (.claude/ for Claude Code, .cursor/ for Cursor), in two kinds of unit:
- Role subagents โ
<tool>/agents/{dev,test,review,tech-writer}.md. The role protocols (TDD dev, test, read-only review, doc-refresh tech-writer), launched as isolated subagents. As of BDL-052 these are composed per-project from CORE + the repo's architecture + stack overlays (see the role configurator) โ they are no longer one fixed monolith. - Slash skills โ
.claude/commands/{coordinator,task-init,checkpoint,templates}.md.task-initscaffolds a work item,coordinatororchestrates the waves,checkpointsaves progress,templatesholds the doc templates. The slash-command set is vendored byte-identical (the configurator owns the role agents, not the commands).
Plus a .claude/CLAUDE.md entry point whose auto-regions carry the per-project facts (name / stack / version / commands).
The effectiveness of this flow lives in the exact wording of those files, refined over many epics. So Beadloom does not rewrite or summarize them. For the slash commands it vendors them byte-identical from its own live .claude/ and templates only the per-project facts in the CLAUDE.md auto-regions; for the role agents it composes them deterministically from versioned CORE + overlay fragments. In both cases a drift-guard asserts the on-disk file equals the recomputed source byte-for-byte, so the scaffold always ships the latest proven flow.
The role configurator (BDL-052) โ
The flow is no longer hardcoded to Python + Claude Code. A repo declares its tools, architecture methodology, stack/frameworks, and quality bars, and Beadloom composes the matching role files for each tool.
.beadloom/flow.yml โ
tools: [claude, cursor] # which IDE adapter sets to generate
architecture: [ddd] # exactly one methodology: ddd | fsd
stack: [python, fastapi] # one+ stack/framework overlays
quality: [clean-code, tdd] # quality bars (informational)flow_config.py loads + validates this into an immutable FlowConfig. Validation is strict and agent-actionable: an unknown tool / architecture / stack, an architecture that is not exactly one methodology, or an empty tools/stack raises a FlowConfigError naming the offending value and the allowed set (the config-check signal). For Beadloom itself the config is tools: [claude], architecture: [ddd], stack: [python].
Supported values: tools claude / cursor; architecture ddd / fsd (peers โ pick one); stack python / fastapi / javascript / typescript / vuejs.
Composition: CORE + overlays โ
role_composer.compose_role(role, architecture=โฆ, stack=โฆ) assembles a role file deterministically, in a fixed order:
- CORE โ the universal, stack/tool-neutral role protocol (the single source of truth).
- one ARCHITECTURE overlay โ
dddorfsd(peers): the methodology's layer/boundary rules + the# beadloom:annotation vocabulary. FSD is at parity with DDD (every role has both overlays). - one+ STACK overlays in sorted order: stack idioms + lint/type/test commands.
A missing per-role overlay fragment contributes nothing (overlays are additive and never break an unrelated role). Because the stack overlays are sorted, the same (role, architecture, stack) always yields byte-identical output โ the determinism the drift-guard relies on.
Per-tool adapters โ
role_adapters.generate_adapters(config, project_root) is the single output writer: it composes each role once and writes a per-tool adapter set for every configured tool, with each adapter body exactly compose_role(...):
- claude โ
.claude/agents/<role>.md(the slash-command set in.claude/commands/*is vendored separately and is not regenerated here). - cursor โ
.cursor/agents/<role>.md(same composed body) plus a thin.cursor/rules/beadloom-flow.mdorchestrator pointer โ the coordinator-as-Cursor-mode entry point, so Cursor runs the same flow at parity with Claude Code.
beadloom setup-agentic-flow (configurator front-end) โ
beadloom setup-agentic-flow [--project DIR] [--force] \
[--tool claude|cursor]... # repeatable; default: flow.yml or claude
[--architecture ddd|fsd] # default: flow.yml or ddd
[--stack python,fastapi,...] # default: flow.yml or auto-detectedSelection follows flag โ flow.yml โ default precedence: an explicit flag overrides the corresponding flow.yml field; fields neither flagged nor present fall back to the defaults (claude / ddd / a stack auto-detected from the repo's source-file extensions). It echoes the resolved architecture / stack / tools, writes every configured tool's adapter set, then drops the vendored slash commands + the per-project CLAUDE.md.
Roles are composer-owned โ
Once a flow.yml exists, the composer owns .claude/agents/* and .cursor/agents/*. Do not hand-edit a role adapter: config-check byte-compares every existing <tool>/agents/<role>.md against the freshly recomposed body and flags a hand-edit, a stale CORE, or a stale overlay as drift.
beadloom config-check [--project DIR] # exit 1 on drift, 0 when clean
beadloom config-check --fix [--project DIR] # recompose drifted adapters + restoreconfig-check --fix recomposes every configured tool's adapter set from CORE + overlays (and re-drops the vendored commands + CLAUDE.md auto-regions). An invalid flow.yml is itself reported as drift; an absent one is not (a repo may never adopt the configurator โ the composer drift-check is then a no-op).
Known limitation โ orphaned adapters. The composed-adapter drift-check iterates only over the tools named in
flow.yml. If you narrowflow.ymlto a subset (e.g. dropcursor) after a previously-scaffoldedcursoradapter set was written, those now-orphaned.cursor/agents/*files are left un-drift-guarded โ they neither fail the check nor get recomposed. A follow-up bead tracks adding an orphaned-adapter lint; until then, remove a dropped tool's adapter directory by hand.
The pre-push Beadloom Gate (BDL-052) โ
beadloom install-hooks --pre-push installs the Beadloom Gate โ the authoritative blocking enforcement of the hard invariant "no code in main without current docs." On every git push it runs the full Gate (beadloom ci โ incremental reindex โ lint --strict โ sync-check โ config-check โ doctor) and exits non-zero to block the push on red, printing an actionable message that points at the tech-writer / /coordinator to fix the drift, then re-push.
--no-verifyis the documented (discouraged) escape hatch โgit push --no-verifyskips the hook.- Fail-safe: in any repo without
beadloomonPATHthe hook is a safe no-op and never blocks. - The full Gate lives in pre-push (not on every commit) because pushes are less frequent than commits; the lighter pre-commit hook stays the warn/block
sync-check+ ACTIVE/tracker coherence step.
The pre-push Gate is the local half of local-primary / CI-fallback: it is the same beadloom ci that runs on the PR as a required check, so a clean push is almost always a clean PR. See the CLI reference for both hooks.
Scaffold contents + idempotency โ
beadloom setup-agentic-flow (in the setup-* family alongside setup-rules / setup-mcp / setup-ai-techwriter) drops, idempotently:
<tool>/agents/{dev,test,review,tech-writer}.mdโ composed from CORE + overlays for each configured tool (see the configurator);.cursor/agents/*plus the Cursor orchestrator pointer whencursoris configured..claude/commands/{coordinator,task-init,checkpoint,templates}.mdโ vendored byte-identical..claude/CLAUDE.mdโ the base file (only when absent, or with--force), then itsproject-infoauto-region is regenerated for this project via the samerefresh_claude_mdmachinerysetup-rules --refreshuses. The scaffolded CLAUDE.md version comes from Beadloom's own__version__(BDL-UX #92).
Idempotent. Re-running re-drops the composed adapters + vendored commands and re-refreshes the auto-regions; a file that already matches is left alone. A hand-edited command is skipped (reported as such); --force overwrites it. Composed role adapters are owned by the configurator โ re-running recomposes them. User prose outside the CLAUDE.md auto-regions is never touched. --project DIR targets a different repo root (default: current directory).
config-check (the AgentConfigAsCode freshness gate) keeps all of this honest โ it byte-checks the composed adapters, the vendored commands, and the CLAUDE.md auto-regions; config-check --fix restores them. See Roles are composer-owned above.
The four MCP process-tools โ
The flow's deterministic steps are also exposed as action tools on Beadloom's MCP server (services/mcp_server.py), next to the existing read/write tools โ the catalog is now 18 tools (was 14). These are single deterministic operations that reuse existing substrate code; they do not orchestrate or spawn subagents.
The three bead-touching tools (task_init, complete_bead, checkpoint) drive the bd (beads) CLI through a thin, mockable seam (services/bd_seam.py, run_bd). If bd is not installed they return a clear error (the flow already requires bd).
task_init(type, key) โ
Scaffolds a work item: creates .claude/development/docs/features/<key>/ with the per-type doc skeletons (PRD/RFC/CONTEXT/PLAN/ACTIVE for epic/feature; BRIEF/ACTIVE for bug/task/chore) and a valid 4-role bead DAG (dev โ test โ review โ tech-writer, wired with the standard dependencies) via bd. Returns the created bead ids + doc paths.
bead_context(bead) โ
Returns one structured payload for a bead: graph context (ctx) + impact analysis (why) + a CONTEXT.md/ACTIVE.md excerpt (when present) + the active architecture rules for the bead's area. It resolves the bead's graph ref from a ref: (or area:) token in the bead's design/description via bd show. Read-only and deterministic; reuses context_oracle (ctx/why) and graph/rule_engine (active rules).
complete_bead(bead, run_tests=true) โ
The refusing completion gate. It runs beadloom ci (reindex โ lint โ sync-check โ config-check โ doctor, via application/gate.run_ci_gate) and, by default, the test suite. Then:
- On PASS it closes the bead (
bd close --suggest-next) and returns the next-ready output. - On FAIL it does NOT close the bead โ it returns the structured findings so the agent must fix them first.
Set run_tests=false for a fast gate-only check (skips the suite). This tool is advisory-strong, not the true enforcement point โ see the honest boundary below.
checkpoint(bead, text) โ
Records a checkpoint: adds text as a bead comment (bd comments add, preserving history) and, best-effort, appends a timestamped progress note to the bead's ACTIVE.md (skipped cleanly if the file cannot be located). Deterministic; no orchestration.
ACTIVE.md stays honest by construction (BDL-053) โ
Each epic's ACTIVE.md carries a bead-status table (| Bead | Role | Status | โฆ |) the coordinator reads to know where the wave stands. Historically the coordinator hand-edited those Status cells, which drifted from bd (the source of truth) whenever a row was missed. BDL-053 makes the table correct by construction instead of by discipline:
beadloom active-syncreconciles every epic's bead-status table FROMbd(rewrites each Status cell to match the bead'sbdstatus; a richer coordinator note is preserved when its state agrees) and re-exports the tracked.beads/issues.jsonl. See the CLI reference for the--epic/--check/--json/--no-exportflags.- The pre-commit hook runs it as a guarded auto-fix step. After the lint / mypy / sync-check steps, the hook calls
active-syncand restages the touchedfeatures/**/ACTIVE.md+.beads/issues.jsonl, so the committed table matchesbdon every commit โ the coordinator no longer maintains rows by hand. The step never blocks the commit and runs only when bothbdandbeadloomare installed. - Safe no-op for every adopter. With no
ACTIVE.mdtable, nobd, or an untracked jsonl,active-sync(and the hook step) exits 0 and changes nothing โ so a repo that has not adopted the flow is never affected; it works out-of-the-box.
The reconcile core (application/active_table.py) is the same tolerant, fail-safe parser/updater the checkpoint / complete_bead MCP process-tools use to flip a single row โ so single-row updates and full reconcile share one format (the active-table component).
Tool-agnostic: native adapters + MCP โ
Tool-agnosticism has two layers:
- Native role adapters for the first-class tools. The configurator generates
.claude/agents/*(Claude Code) and.cursor/agents/*+.cursor/rules/beadloom-flow.md(Cursor) from the same composed bodies, so Cursor runs the same waves at parity with Claude Code. - MCP process-tools for everything else. The process-tools are plain MCP tools, so any MCP client โ Claude Code, Cursor, Continue, Windsurf โ gets the same deterministic operations over the Beadloom substrate. This is the inline floor: on a tool without a native adapter set, an agent can still follow the role protocols inline and call the deterministic process-tools.
beadloom setup-mcp --tool {claude-code,cursor,windsurf}This is the "one context for everyone" angle: the native scaffolds deliver the Claude-Code / Cursor personas + coordinator at parity, while the MCP tools deliver the tool-agnostic substrate any client can call.
The honest boundary โ
This is stated deliberately, not glossed over:
- Orchestration stays in the harness. MCP serves tools, not orchestration โ it cannot spawn subagents or run the main loop. The coordinator and the
Agent-spawn waves remain Claude-Code-native/harness concerns (scaffolded bysetup-agentic-flow). The MCP process-tools are the deterministic substrate the flow calls, not a replacement for the harness. complete_beadis advisory-strong, not the source of truth. The model still chooses to call it. It is stronger than Markdown instructions (it actually refuses a red gate) but weaker than CI.- The pre-push Gate is local-primary, not the final word. The Beadloom Gate hook blocks a red push on the author's machine โ strong, but
git push --no-verifycan skip it, so it is a fast local catch, not the un-routable gate. - CI is the single source of true enforcement.
beadloom ciruns independently in CI (reindex โ lint โ sync-check โ config-check โ doctor) as a required check onmain; that is the gate nothing can route around (no--no-verify).
See also โ
- CLI reference โ
setup-agentic-flow,config-check,ci,setup-mcp,setup-branch-protection,install-hooks,active-sync. - Active Table component โ the shared ACTIVE.md bead-status table parser/updater + reconcile-from-
bdcore. - AI tech-writer guide โ the PR-triggered doc-refresh loop on the trunk-based model.
- MCP server โ the full tool catalog (18 tools).
- Onboarding domain โ the scaffold + config-sync internals.
- Flow Config SPEC โ
.beadloom/flow.yml+ theFlowConfigloader/validator. - Role Composer SPEC โ CORE + architecture + stack overlay composition.
- Role Adapters SPEC โ per-tool adapter generation + the drift-guard.
- CI setup guide โ
beadloom cias the enforcement gate.