Skip to content

UCG vs bmad-loop

Both UltraCode Goal (UCG) and bmad-loop (formerly bmad-auto; renamed at v0.8.0, with the rename shims removed at v0.10.0: a project still on bmad-auto migrates via v0.9.1, the last release carrying them) automate the BMAD implementation phase without a babysitter. They are siblings, not clones: they make opposite bets on where the control loop lives and how completion is judged. This page compares them honestly, including the places where bmad-loop is the better tool.

Snapshot: UCG v2.2.0 (released 2026-08-15) and bmad-loop v0.10.0 (released 2026-08-14). Both projects are young and moving fast.

bmad-loop’s v0.10.0 is a substantive release cut from main, which its own notes say has not been released since v0.9.0 and does not descend from v0.9.1; the 0.9.x hotfix line (the bmad-build-auto primitive resolution and the skills.base-shim refusal of upstream’s interactive forwarding shim) is brought forward onto main alongside new capability. The headlines: a story owing human-only external actions (a DNS record, an API key) can commit what an agent can do, park at awaiting-operator, and be completed later by a new bmad-loop confirm command, with the park record traveling in the story’s own commit so confirm works from any clone; a deferred-work entry’s gate: line now hard-blocks the stories it names in both validate and run, and a story can close ledger entries at its commit via closes_deferred:; hook events (the run’s control plane) and resume’s config baseline move out of the agent-writable project tree into XDG state, part of an agent-tamper defense family the notes candidly call incomplete against a deliberate bypass; coding-CLI adapter classes can ship out-of-tree against a registry, listed by a new adapters command; the per-story token budget is re-checked at every session boundary (still advisory); and confirm joins the schema-versioned --json family. UCG is not affected by the BMAD-METHOD primitive rename either way: it orchestrates bmad-dev-story, not the auto primitive.

UCG reached v2.2.0 on 2026-08-15. The release is re-loop economics, distilled from a measured story that took seven gate cycles: the re-loop route now generalizes each finding to its defect class against a per-Epic ledger before fixing (five of that story’s six reviews had re-found one class, one seam over each time); mid-loop sweeps may scope to the affected set while the gate refuses to advance any story whose marker does not prove a full-scope sweep; Stage-5 assessors measure a git worktree of the commit under assessment instead of the shared tree, with outputs pinned to the main tree; a delta cycle profile re-runs only the previously failed assessor dimension and is capped so it can never advance; a tracked mutation runner (mutate_check.py) proves every new guard red-able before the gate, its ledger leading with survivors; and heartbeat/stall sidecars timestamp every loop boundary so dead air becomes a record. The new gate flags are additive: their JSON keys appear only when the flags are passed, so pre-flag invocations print the shape they always did. (v2.1.0 and v2.0.0, the computed epic roll-up and the nine-defect fail-open closure, are in the changelog.)

Treat every line below as a point-in-time reading of two released versions, and verify the current state for yourself (links at the bottom); both projects’ main branches run well ahead of their tags.

bmad-loop puts the control loop in plain Python, outside the agent. A deterministic orchestrator picks the next story, spawns a fresh, disposable coding-agent session (over tmux by default) for each step, watches structured hook events the session writes, and decides retries, gates, and completion in code. No LLM sits in the control loop.

UCG puts the control loop inside Claude Code. The run is a Claude Code skill that composes /goal, Auto Mode, Auto Memory, and runtime hooks. The per-story loop is paced by Claude Code’s /goal evaluator (an LLM), while the binding completion verdict is a deterministic script (gate_eval.py) that reads the Test Architect’s (TEA) gate artifact.

The consequence cascades: bmad-loop is a tool you run beside any supported agent; UCG is a capability that lives within one specific agent.

Dimensionbmad-loopUltraCode Goal (UCG)
RuntimeExternal Python process plus a terminal multiplexer, tmux being the bundled default (the OpenCode profile runs over HTTP with no multiplexer window); Linux, macOS, or WSL; native Windows in progress (a psmux backend ships in-tree behind a real-Windows live gate, not yet claimed as shipped)A skill inside Claude Code; no daemon, no multiplexer, no session to attach to. Runs wherever Claude Code does, given Python 3.11+, uv, and git, and a Claude Code new enough for /goal, dynamic workflows, and Auto Memory, the three versions preflight pins and refuses to launch below. One optional exception: a ~900-line driver script that runs one session per story on long Epics
Control loopDeterministic Python, no LLM in the loopLLM-paced /goal spine with a deterministic completion gate
Agent / CLIclaude, codex, gemini, copilot, antigravity, opencode (mix per stage)Claude Code only
ScopeImplementation phase: backlog and ready-for-dev stories from sprint-status.yaml, or opt-in from a typed stories.yaml, through dev, review, verify, commitWhole Epic, six stages: ingest and scope, planning-readiness preflight, ATDD (acceptance-test-driven development) test generation, execute, TEA gate, finalize, whose terminal step is a workflow health check that the skill’s own table numbers as a seventh stage
Completion authorityChecks on the spec and result artifacts, a proof-of-work diff, and your test and lint commands; opt-in TEA gate steps via a bundled plugin (advisory by default)TEA quality gate: gate-decision.json (P0/P1/overall), combined in the default profile with NFR and test-review artifacts, read fail-closed by gate_eval.py; since v2.2.0 the verdict is also capped by evidence scope, so a story only advances off a full-scope sweep (--tests-ran) and a delta-profile mid-loop gate can never advance (--cycle-profile)
Test strategyYour [verify].commands plus adversarial review hunters; opt-in TEA test-design and ATDD workflows via the bundled pluginATDD: acceptance criteria become executable red-phase tests driven to green; TEA traceability; a tracked mutation runner (mutate_check.py) proves every guard a story adds red-able before the gate, with a generated ledger that leads with the mutations that survived
Pre-launch gatevalidate, a registry of named checks whose id families at v0.10.0 span BMAD config, adapter (binary, profile, kind, out-of-tree), deferred work (including an unreadable ledger now failing rather than warning), git, hooks, host, multiplexer, notifications, operator park records, policy, queue (sprint-status and stories manifest), and skills, where skills.base-shim still refuses the forwarding shim BMAD-METHOD’s rename left behindA mechanical preflight script plus a readiness check and a semantic scan that refuse to launch on an undecided product or architecture decision
ObservabilityA live terminal dashboard (built with Textual): runs table, attach to live sessions, journal, cost-weighted token totals, an active-agent indicator naming what is driving the current stage, plus schema-versioned --json documents for scripted readersFiles plus a read-only renderer: .decision-log.md, a run-status.json heartbeat, per-step .heartbeat/.stall sidecars that timestamp every story-loop boundary and turn an unexplained gap into a record at resume, a transcript ticker that prints each gate verdict, a gate-trail.md evidence trail at finalize, and /ucg-status to assemble all of it on demand
Deferred workA triage-and-execute sweep engine plus a decisions workflow; since v0.10.0 a ledger entry’s gate: line hard-blocks the stories it names in both validate and run, and a story can close entries at its commit via closes_deferred:A ledger the gate only appends to, surfaced at finalize and readable mid-run through /ucg-status, with /ucg-resolve able to mark an answered decision row resolved; no execute engine
EscalationTyped (CRITICAL / PREFERENCE) plus an interactive resolve agent that re-arms the spec and re-applies the saved patch, so review resumes on the restored diff; v0.10.0 adds a third outcome with no UCG equivalent, where a story owing human-only external actions commits what an agent can do, parks at awaiting-operator, and bmad-loop confirm completes it later from any cloneAn escalate verdict, a typed escalation-<story-id>.json sidecar (source, kind, decision_needed, evidence), an on_escalation hook, a path-pinned run-result.json for every headless terminal exit that got far enough to resolve its artifacts path, not only blocked ones, and /ucg-resolve to answer what is pending; resume from the decision log
IsolationIn place by default; opt-in git worktree per story or bundle, merged back locallyAt the gate: since v2.2.0, Stage-5 assessors measure a git worktree of the commit under assessment, with assessor outputs pinned to the main tree. Story execution itself stays sequential in one tree (the experimental --parallel worktree mode was retired)
ExtensibilityA plugin system (observe, veto, mutate) with bundled TEA and Unity pluginscustomize.toml knobs, planning-shaping fragments, and two optional third-party integrations configured there, both off by default and neither able to touch a gate verdict: claude-mem recall and a graphify knowledge-graph refresh
Self-improvementNot shippedA health check that files deduplicated GitHub issues about its own friction
MaturityFirst-party (bmad-code-org); v0.10.0, a substantive release bringing the 0.9.x hotfix line onto main plus operator parking, enforced deferred-work gates, and agent-tamper defenses; rich docs; CI + test suiteCommunity module; v2.2.0, re-loop economics from a measured seven-cycle post-mortem (defect-class generalization, scope-capped sweeps, worktree-isolated gating, a tracked mutation runner), additive over the v1.0.0 SemVer contract; docs site; CI + test suite
LicenseMITMIT

This is a genuinely strong tool; pretending otherwise would make this page useless.

  1. A deterministic control loop. Story selection, retry budgets, gates, and completion checks are ordinary Python, so they are debuggable, reproducible, and cost no tokens. UCG’s /goal pacing is LLM-driven; its deterministic pieces (the per-story and epic-level gate reads, the preflight scripts, the commit-guard and budget hooks) bound the loop rather than run it. If you want zero LLM judgment in the orchestration itself, bmad-loop is the cleaner model.
  2. Agent portability. It drives claude, codex, gemini, GitHub Copilot CLI, antigravity, or OpenCode, and can run dev on one model and review on another via per-stage profiles. UCG is deliberately Claude Code only.
  3. Observability and control. A live terminal UI (built with Textual) gives you a runs dashboard, a sprint tree, the deferred-work ledger, per-story token totals, attach-to-session, and a policy editor. UCG’s window is files, the transcript, and a read-only /ucg-status render assembled from those same files: there is still no live view and no session to attach to.
  4. A deferred-work engine, not just a ledger. bmad-loop sweep triages the ledger against the real code, bundles cohesive work, executes it, and has a decisions workflow for the human calls. UCG appends to a ledger, surfaces it at the end, and can render it mid-run through /ucg-status; acting on it is still manual, and there is no execute engine.
  5. Extensibility and reach. It has a real plugin system (observe, veto, mutate the cycle) with bundled plugins: a TEA plugin that can add Test Architect workflows to its pipeline, and a Unity game-engine integration. UCG exposes configuration knobs, not a plugin API.
  6. Operational maturity. It ships disk reclamation (clean and archive, retention windows, worktree teardown), cost-weighted token budgets that discount cache reads, and an adapter-authoring path for new CLIs (out-of-tree adapter classes against a registry since v0.10.0), and it carries the backing of the bmad-code-org org.
  1. The TEA gate is the default, binding completion authority, not an opt-in layer. UCG’s completion authority is the Test Architect’s gate: a traceability matrix that holds acceptance criteria to hard thresholds (P0 coverage at 100%, P1 at 90% or above, overall at 80% or above). UCG’s default profile combines that verdict with an NFR (non-functional requirements) assessment and a test-review score, and gate_eval.py reads the result fail-closed: a missing or unreadable signal downgrades the verdict, never upgrades it. Since v0.5.0 the default sequential path also re-runs the test, lint, and build suite on each story’s committed HEAD before advancing, so a story that is green pre-commit but red once its new files are tracked cannot slip through to the gate; since v2.2.0 that re-verify runs at the cycle’s declared scope, with the gate refusing to advance any story whose .tests-ran marker does not prove a full-scope sweep.

    bmad-loop can reach similar territory, but differently. Its default gate is checks on the spec and result artifacts, a proof-of-work diff (the commit must contain real changes since the story’s baseline), and your test and lint commands; its bundled TEA plugin can add trace, NFR, and test-review steps before every commit. That plugin is opt-in, its gate steps ship advisory (non-blocking), and they fail open when an artifact is missing or unparseable. That gap narrowed in v0.9.0: at v0.8.1 bmad-loop’s independent baseline-commit cross-check could not actually fire, because it read a spec key the dev skill does not write, so a spec claiming a stale or foreign baseline sailed through; v0.9.0 fixed it to accept either key and re-cut the test fixture that had been fabricating the missing one. The advisory-by-default and fail-open-on-missing-artifact properties of the TEA plugin’s gate steps are unchanged. If you want acceptance-criterion-to-test traceability enforced by default, fail-closed, with nothing to configure, that is UCG’s defining bet.

  2. ATDD-first. UCG turns each story’s acceptance criteria into executable acceptance tests (scaffolded as red-phase test.skip placeholders) before any code is written, then un-skips them and drives them to green. The acceptance tests are a first-class generated artifact, not a by-product. One scope note, about what the generator emits rather than what it accepts: the TEA release installed here does detect a backend stack, but its scaffolds are Playwright and TypeScript, and the browser-recording path loads only for a frontend or fullstack project, so a stack with no JS or TS harness still gets nothing runnable. UCG’s preflight therefore steers those runs to --light, where the story’s acceptance criteria (not generated tests) are the trace oracle, or you author the acceptance tests in the stack’s own harness. bmad-loop’s default pipeline relies on whatever tests the dev skill writes while implementing, plus the test commands you supply; TEA test generation exists there only as an opt-in plugin step that runs after dev, not as the default path.

  3. A planning-readiness gate that can refuse to launch. UCG’s preflight hands the PRD, the architecture, and the stories to a throwaway subagent that hunts for undecided product or architecture decisions, contradictions between the PRD and the architecture, and any story whose “done” cannot be pinned down. The scan grades what it finds, and any RED verdict stops the run rather than letting an unattended agent guess; the one way past a RED is an operator recording a close for it, since a defer does not clear one and an unreadable decisions file clears nothing. That scan is itself LLM judgment, the very thing bmad-loop keeps out of its loop; the difference is that it can only block a launch, never pass one, and the readiness kernel beside it is deterministic. That kernel has been the module’s most defect-prone surface, and the honest reading is that it took three releases to make it fail closed: v1.0.0 closed three fail-opens where an Epic with no stories, a story with no acceptance criteria, and a partially seeded story set each scored ready, and v2.0.0 closed two more, where a present-but-unparseable sprint board emptied the in-scope set (silencing both guards that exist to catch exactly that), and where a citation in a story counted as its own declaration, so a dangling reference could never be reported and the judgment branch was unreachable. bmad-loop’s preflight is mechanical and assumes the sprint’s stories are already ready to build.

  4. Almost no moving parts outside the agent. The autonomous run is a skill: no daemon, no multiplexer, no session to attach to. For a Claude Code user that is a smaller operational surface, and it is also exactly why UCG cannot run anywhere else. Two qualifiers, added honestly. Three companion skills ship alongside the run and none is required by one: ucg-formalize (the standalone readiness gate), ucg-status (the read-only run view), and ucg-resolve (the decide-surface for a stopped run). Worth recording rather than quietly fixing: until v2.0.0 all three shipped one directory too deep for the skill loader, which enumerates a single level, so every one of them returned Unknown skill when invoked. Every check the project had verified they were present, and they were; none tested whether they were reachable. And a long Epic accumulates every story’s transcript in one session, so UCG ships an optional driver script that spawns one claude -p per story; use it and you are running a loop outside the agent after all, which is bmad-loop’s model in miniature. The difference is that it is opt-in and about 900 lines, where bmad-loop’s orchestrator is the product; skip it and the skill still runs standalone, since --max-stories is a flag on the skill rather than something the script provides.

  5. A self-improvement loop. UCG’s finalize step can file deduplicated GitHub issues about friction in its own workflow, so the tool reports its own rough edges.

  • A deterministic completion authority the model cannot talk its way past: bmad-loop’s artifact, diff, and command checks; UCG’s TEA gate read. One caveat on the UCG side, narrowed but not removed in v2.0.0: on a non-web stack, under either profile, the trace artifacts are agent-authored under strict honesty rules, so on that path the model writes the file the gate then reads and the guarantee is procedural rather than mechanical. What changed is that the substitution is no longer invisible: the gate now records gate-provenance: tea or hand-authored per story and the run report carries it, so a reader can tell which verdicts rested on artifacts the run produced for itself. Before that, an Epic could complete entirely on hand-authored gate files and read identically to one gated on TEA output.
  • Proof that the commit is real work, not a claim about work. bmad-loop cross-checks the diff against the story’s baseline commit; UCG enforces the equivalent one layer down, in a PreToolUse hook that denies the git commit outright unless a tests-ran marker exists whose recorded baseline SHA matches the story’s character for character, and unless the staged index is non-empty. That hook is only as good as its command parsing, which is worth stating because until v2.0.0 it was not: a commit wrapped in any shell compound form (if, a loop body, a subshell, a brace group) or placed after a background & classified as carrying no git write at all, skipping the protected-branch, marker, freshness and empty-index gates in one go. On a production run it also refuses a commit whose staged acceptance tests are still skipped, though that check reads test.skip( and so does nothing on the non-web stacks the ATDD note above steers to --light. Both projects are also hardening the same flank from opposite sides: v0.10.0 moved bmad-loop’s hook events and resume baselines out of the agent-writable tree, a tamper-defense family its notes call incomplete against a deliberate bypass, and UCG’s guard carries its own bypass history (the v2.0.0 compound-form fix).
  • Fresh-context review separated from implementation, to kill self-review anchoring bias, on both defaults with a caveat each: bmad-loop’s separate session is gated by review.trigger, which defaults to recommended (set it to always for every story), and UCG runs a code-review pass on its production profile but none under --light.
  • Adversarial review passes, bounded so they cannot oscillate forever: bmad-loop by max_review_cycles (default 3), UCG by max_turns_per_story, where a re-loop that would exceed the budget escalates instead.
  • Git worktree use, aimed differently: bmad-loop’s opt-in isolation runs each story or sweep bundle in its own worktree and merges back locally; UCG’s Stage-5 gate measures a worktree of the commit under assessment while story execution stays in the main tree.
  • Resumable runs with a per-story budget: bmad-loop’s is a cost-weighted per-story budget that discounts cache reads (advisory, re-checked at every session boundary since v0.10.0) beside a per-session cap that can terminate; UCG’s is a turn cap, encoded in the /goal condition and enforced at the gate. UCG adds a second axis, --max-stories N, a per-invocation work bound whose exhaustion still ends the run complete with stories remaining, so that status means “this invocation finished”, not “the Epic is done”. Note the asymmetry: UCG has no token or cost bound at all, and story_token_budget is now a deprecated no-op.
  • sprint-status.yaml as the shared planning ledger, and both build on BMAD-METHOD. Neither leaves it write-only to the BMAD skills any more: UCG’s gate writes the story’s done row at the advance route, and bmad-loop’s orchestrator syncs the board itself.

Choose bmad-loop if you use codex, gemini, or GitHub Copilot CLI (or want to mix models per stage), you want a code-only orchestrator you can step through and debug, you want a live dashboard and attach-to-session control, you have a backlog of deferred work to triage and sweep, you need plugin extensibility or game-engine support, or you prefer a first-party tool maintained under the bmad-code-org org.

Choose UCG if you are on Claude Code and any of these fit: you want the Test Architect’s gate as the default, binding, fail-closed completion authority (every P0 criterion traced to a passing test, with P1 at 90% or above and overall at 80% or above) rather than an opt-in layer; you want acceptance criteria compiled into executable tests up front; you want a run that refuses to start while a product or architecture decision is still undecided; or you want the autonomous run itself to be a single skill with no daemon and no session to attach to (the three optional companion skills and the per-story driver above are all opt-in, and a run needs none of them).

They are not mutually exclusive. Both read the same sprint-status.yaml and BMAD artifacts, so an Epic planned and gated UCG’s way is a board bmad-loop can pick up. Their deferred-work ledgers are not interchangeable, though: they share the path but not the schema, since bmad-loop sweep parses ### DW-<n>: sections and UCG never writes one, so a sweep will not see UCG’s parked rows.

Both tools change weekly, so re-check before you rely on anything above:

This snapshot was re-cut on 2026-08-15 against bmad-loop v0.10.0 (released 2026-08-14) and UCG v2.2.0 (released 2026-08-15). Earlier cuts: 2026-08-02 (bmad-loop v0.9.1, UCG v2.0.0, both released that day), 2026-07-28 (bmad-loop v0.9.0, UCG v1.0.0), 2026-07-12 (bmad-loop v0.8.1, UCG v0.5.1), and 2026-06-28 (bmad-auto v0.7.4, UCG v0.4.0), which predates the bmad-auto rename.

One deliberate omission in this cut. Previous versions of this page stated a count of bmad-loop’s registered validate checks. That number could not be reproduced from the pinned source without running their tool, so it has been replaced by the list of check families, which can be (this cut re-derived that list from the check ids in the v0.10.0 source). A number nobody re-derives is a number that quietly goes stale, and this page has no business asserting a precise figure about someone else’s project that its own author cannot check.