π Enterprise 4-level LLM multi-agent orchestration plugin for superpowers. Combines Claude Desktop GUI strategy (Opus 5/Fable 5) with OpenCode CLI TDD background workers (Kimi K3/Minimax M3), cutting token costs by 5x-10x.
An enterprise-grade, cost-optimized multi-agent orchestration framework extending
obra/superpowers.

superpowers-multiagents separates strategic product design from heavy task planning and TDD code execution. By leveraging specialized LLM cost tiers, configurable CLI harnesses, and non-blocking background execution, it cuts token costs by 5x-10x while maintaining strict architectural quality.
The core obra/superpowers methodology fundamentally transforms coding agents from chaotic code generators into disciplined software engineers:
While Superpowers provides the core engineering discipline, executing large TDD plans solely on frontier models introduces severe cost bottlenecks and timeout crashes. superpowers-multiagents extends Superpowers into an enterprise-ready, N-level multi-agent pipeline:
[!TIP]
5xβ10x Token Cost Reduction: By separating high-reasoning strategy from heavy TDD code execution, high-volume output runs under flat-rate subscriptions while top models focus on architecture and audit.
| Dimension | π΄ Traditional API Orchestrators (CrewAI, AutoGen, LangGraph) |
β‘ Superpowers Multi-Agents (Claude Desktop + Configurable CLI) |
Value & Impact |
|---|---|---|---|
| π° Billing Model | Pure Pay-Per-Token API Every loop and test run bills input/output tokens. |
Flat-Rate Subscription Heavy execution runs on configurable CLI harnesses. |
80β90% Cost Reduction |
| π§ Strategic Layer | API Code Loop Expensive models used for repetitive text outputs. |
Claude Desktop GUI Top models focus purely on architecture and diff audit. |
High Reasoning, Low Cost |
| β‘ Execution Layer | Per-Token Metered API 3,000-line plans bill heavily per token. |
Background CLI Tasks Unlimited TDD planning and testing at $0 extra cost. |
Uncapped Code Output |
| π‘ System Stability | 60-Second Timeout Limits Prone to crashes on long tasks. |
Non-Blocking OS Processes Tasks run background for 1β2+ hours smoothly. |
Zero Timeout Crashes |
| π State Audit | Black-Box Database / Memory State hidden inside framework memory. |
Single Source of Truth Status derived from supervisor exit code; full agent transcript captured to .superpowers/logs/. |
100% Transparency |
The framework implements a configurable N-level agent hierarchy. Agents, harnesses, providers, and models are all defined declaratively in .superpowers/agents.yaml. See docs/architecture.md for the full module breakdown.
flowchart TD
subgraph GUI ["Claude Desktop (Strategic Layer)"]
A1["π€ Agent 1: Fable 5 (Milestone & Track Architect)"]
A2["π§ Agent 2: Opus 5 (Slice Architect & Auditor)"]
end
subgraph SUP ["Orchestrator (Supervision Layer)"]
W["π create worktree<br/>.worktrees/<slice_id>"]
SB["π³ sandbox up<br/>per-slice docker stack, LOOPBACK_IP"]
R["π‘ runner.py β captures the log, holds the lock,<br/>derives status from the exit code"]
end
subgraph CLI ["Configurable CLI Harness (Execution Layer)"]
A3["π Agent 3: Planner (default: Kimi K3)"]
A4["π» Agent 4: Executor (default: Minimax M3)"]
end
Human["π€ Human Product Owner"] -->|"Milestone Vision"| A1
A1 -->|"Milestone + Tracks"| A2
A2 -->|"Slice Spec"| Human
Human -->|"SPEC_APPROVED"| A2
A2 -->|"dispatch-agent --role planner"| R
A2 -->|"dispatch-agent --role executor"| W
W --> SB
SB --> R
R --> A3
R --> A4
A3 -->|"exit code"| R
A4 -->|"exit code"| R
R -->|"exit 0 β PLAN_GENERATED / EXECUTION_COMPLETE"| A2
R -->|"the run died β back to<br/>SPEC_APPROVED / PLAN_APPROVED"| F["β©οΈ its gate"]
F --> A2
F -->|"teardown (isolated agents only,<br/>e.g. executor by default)"| TD1["π§Ή down (containers)"]
A2 -->|"Diff Audit"| Human
Human -->|"VERIFIED_CLOSED"| Done["β
Closed Slice"]
Done -->|"teardown"| TD2["π§Ή down -v (volumes)"]
The agent never sets its own terminal status.
dispatch-agentreturns as
soon as the supervisor is spawned; the supervisor waits for the agent, writes
its transcript to.superpowers/logs/, and converts the exit code into a
status. An agent that crashes β or simply forgets to report β therefore
cannot leave a slice stranded.
The lifecycle of every feature slice is tracked transparently inside Markdown YAML Frontmatter. Both statuses and transitions are configurable via .superpowers/agents.yaml. See docs/configuration.md for the full schema.
| State | Responsible Agent | Action / Gate |
|---|---|---|
DRAFT_SPEC |
Opus 5 | Drafting design spec and interface contracts. |
SPEC_APPROVED |
Human Gate | Human approves the design spec. |
PLANNING |
Planner (configurable) | Background worker generating detailed TDD plan. |
PLAN_DRAFTING |
Planner | The plan file exists and is being written. Says nothing about completion. |
PLAN_GENERATED |
Orchestrator (from exit code) | slice-N-plan.md finished β written on both the spec and the plan. |
PLAN_APPROVED |
Opus 5 Gate | Opus 5 audits plan against spec contracts. |
EXECUTING |
Executor (configurable) | Background TDD execution (Red β Green β Commit). |
EXECUTION_COMPLETE |
Orchestrator (from exit code) | All tasks finished & test suite 100% PASS. |
FAILED |
(legacy) | Nothing writes it. A dispatch that dies returns its document to the gate it started from. Kept so documents already there keep their way out. |
VERIFIED_CLOSED |
Opus 5 Gate | Opus 5 audits git diff and marks slice closed. |
A milestone brief is a second document kind, declared by kind: milestone. A
document that declares none is a slice, so nothing existing changes.
| State | Responsible | Action / Gate |
|---|---|---|
MILESTONE_DRAFT |
Agent 1 | Writing the brief. |
MILESTONE_ACTIVE |
Human Gate | Approved β refused while any required section is empty. |
MILESTONE_CLOSED |
Human Gate | The objective was met β refused while any listed slice is open. |
No agent is ever dispatched against a brief, so there is no FAILED here and no
branch to merge. Track checkboxes are derived from the real statuses of the
slices a track lists; closing a slice refreshes them in the same command. See
docs/configuration.md.
Projects can optionally define .superpowers/hooks.yaml in their repository root to trigger environment isolation and cleanup automatically.
These names are the complete set the orchestrator emits. A key that is not
one of them never fires β so the orchestrator reports it as an unknown event at
load time rather than leaving you to wonder why nothing happened. {role} is
each role defined in agents.yaml; with the default roles that is planner and
executor.
| Event | Fired by | When |
|---|---|---|
on_slice_{role}_start |
dispatch-agent |
before the supervisor is spawned β fails the dispatch without touching the slice |
on_{role}_complete |
supervisor | the agent exited 0 |
on_{role}_failed |
supervisor | the agent exited non-zero |
on_slice_verified_closed |
set-status |
after a successful merge |
capture_env: true parses the hookβs stdout for KEY=VALUE (and export KEY=VALUE) lines and passes them into the agentβs environment.
# Example: .superpowers/hooks.yaml
hooks:
on_slice_planner_start:
command: "echo Preparing planning environment"
on_slice_executor_start:
command: "python .claude/skills/sandbox-loopback/scripts/sandbox_loopback.py up"
capture_env: true
on_planner_complete:
command: "echo Plan generated"
on_planner_failed:
command: "echo Planning failed β see .superpowers/logs/"
on_executor_complete:
command: "python .claude/skills/sandbox-loopback/scripts/sandbox_loopback.py teardown --yes"
on_executor_failed:
command: "python .claude/skills/sandbox-loopback/scripts/sandbox_loopback.py teardown --yes"
on_slice_verified_closed:
command: "echo Slice verification complete"
Per-slice infrastructure isolation via this hook is superseded.
Prior to 2.1.0, on_slice_executor_start fired before the dispatched sliceβs
branch/worktree existed, so a branch-derived address resolved the same for
every slice in flight and parallel slices silently shared one stack. Use the
sandbox feature below instead β see
docs/configuration.md.
Optional and opt-in: with no sandbox block in .superpowers/agents.yaml
the orchestrator never makes a docker call. Declare one and each isolated
slice gets its own docker compose stack, published on its own
127.0.0.x loopback address, so two agents dispatched in parallel from
different worktrees never fight over the same host port. See
docs/configuration.md
for the full schema, the template tokens, and the three teardown modes.
python -m scripts.orchestrator sandbox --project-root . status
feat/slice-02-native-sandbox 127.0.0.78 running
feat/slice-03-other-feature 127.0.0.140 stopped
Branch creation here is mechanical, not a habit you bring with you. Three
rules follow from one command, git worktree add -b feat/<slice_id> .worktrees/<slice_id> HEAD:
Do not create a slice branch by hand. The dispatcher derives
feat/<slice_id> from the documentβs frontmatter. A hand-made
feature/<slice_id> is a different branch three characters away, and
close-slice merges only the derived one β the other lingers looking like
unfinished work. dispatch-agent prints a hint when it sees both.
Commit specs and plans on the branch checked out in the main working tree
before dispatching. That branch is what the planner reads (it has
isolated_worktree: false and runs in the project root) and what the executorβs
worktree forks from. An uncommitted document is not in HEAD, so it is not in the
worktree: dispatching an isolated role at one is refused, by name, rather than
handed to an agent that will fail later for a reason it cannot explain. In the
normal case the branch you commit on is your integration branch.
.worktrees/<slice_id> belongs to the plugin. Do not create, move or delete
it yourself; close-slice removes it after the merge, and a failed dispatch
leaves it in place on purpose, so the transcript and the work are still there to
read.
A worktree contains HEAD and nothing else. Your .env is gitignored by
construction, so it does not arrive β and an agent running the projectβs own
tests without it reports a failure whose message is about something else. Name
the files that have to cross in worktree.copy, and the dispatcher copies them
in after refusing the four ways that could go wrong (absent, outside the
project, already tracked, or not ignored where it lands β the last being one
git add -A from a secret in your branch history). See
docs/configuration.md.
The orchestrator writes into the project it operates on. Everything it creates
lives under two directories, so one ignore rule covers it:
| Path | Contents |
|---|---|
.superpowers/logs/ |
One file per role and document: <role>_<file stem>.log. Every run of that pair appends, under a === run started <timestamp> === banner β a retry must not erase the failed run it is retrying, which is the only one worth reading. The newest run is always the tail, which is what summary prints. Nothing rotates them; delete the directory when it gets old |
.superpowers/locks/ |
One lock per in-flight slice, naming the live supervisor PID |
.superpowers/sandbox/ |
One JSON record per docker-compose project, keyed by project name; contains the branch it belongs to, its loopback address, and when it was started; removed only when the stackβs volumes are destroyed |
.worktrees/ |
Isolated worktrees for agents with isolated_worktree: true |
Add them to your .gitignore β dispatch-agent prints a reminder when they are
neither ignored nor tracked:
.superpowers/logs/
.superpowers/locks/
.superpowers/sandbox/
.worktrees/
Your .gitignore is never modified for you. The merge gate ignores these four
paths when deciding whether the tree is clean, so the orchestratorβs own output
cannot block its own VERIFIED_CLOSED merge β but leaving them untracked will
otherwise clutter every diff you take.
A run that dies puts its document back at the gate the dispatch was accepted
from β PLANNING β SPEC_APPROVED, EXECUTING β PLAN_APPROVED β and releases
the lock. Nothing is stranded and nothing needs hand-editing. The status says
where the work stands; what happened to the run is in the log, in more
detail than a status could hold.
... summary --slice <slice-id> --project-root .# taking it over by hand: say so, then move it on when the work is done
python -m scripts.orchestrator set-status --file docs/superpowers/plans/<plan>.md --status EXECUTING
An in-progress status with no supervisor behind it is legal and reported as
Β· owned by hand. Only an in-progress status behind a stale lock is
abandonment, and reconcile is the answer to that one.
claude plugin marketplace add ramil-zakirov-dev/superpowers-multiagents
claude plugin install superpowers-multiagents@ramil-zakirov-dev
The repository is its own marketplace, so the two commands name the same
project: the first registers it, the second installs the plugin.
To work on the plugin rather than with it, clone it and install the Python
dependencies β this makes the orchestrator runnable as a program, and does not
install anything into Claude Code:
git clone https://github.com/ramil-zakirov-dev/superpowers-multiagents.git
cd superpowers-multiagents
pip install -r requirements.txt
Prerequisite β the dispatched harness needs the Superpowers skills. The
default prompts send the planner to writing-plans and the executor to
subagent-driven-development; this plugin ships neither and cannot see whether
the harness has them, so a missing skill degrades silently rather than failing.
For OpenCode, declare the plugin in opencode.json:
{ "plugin": ["superpowers@git+https://github.com/obra/superpowers.git"] }
Using a harness without those skills is fine β override each roleβs
prompt_template instead. See
docs/configuration.md.
Separately β for a harness that already has the skills you want β a role can
name them via the skills list under agents.<role> in
.superpowers/agents.yaml. The names are appended to the rendered prompt as
reinforcement, not a replacement for prompt_template. See
docs/configuration.md for
the schema, and Skills Worth Giving Your Agents
below for which skills to install and where to find them.
A role can also carry instructions β your projectβs rules for how that role
must work, appended last and above whatever standing instructions the harness
loaded on its own (OpenCode reads a global AGENTS.md in every session, and it
can contradict the project it was dispatched into). See
docs/configuration.md.
From a clone:
python -m scripts.orchestrator status --dir docs/superpowers
When installed as a plugin:
python "/abs/path/to/plugin/scripts/orchestrator.py" status --dir docs/superpowers
The same absolute-path form works for every command below β dispatch-agent,
set-status, trigger-hook, summary β not just status; itβs shown once
here for brevity.
The report lists the documents the state machine can act on, and answers three
different questions in three different ways:
| The document | The report |
|---|---|
| carries a real status | one row, as always |
carries a status or kind the machine does not have |
one row marked INVALID, saying which β never hidden, because nothing will ever move it |
carries no status: at all |
counted, not listed: it predates the pipeline or was never meant to enter it |
That last line is what keeps the report readable in a repository with history.
Adopting the plugin into one does not mean backfilling frontmatter into every
document you have ever written β writing a lifecycle state onto a closed
historical design doc would be a claim about it that is not true. Pass --all
when you do want to see them.
python "/abs/path/to/plugin/scripts/orchestrator.py" milestone new --id milestone-1 --title "Intake automation"
Fill every section of the generated brief, then approve it:
python "/abs/path/to/plugin/scripts/orchestrator.py" set-status --file docs/superpowers/milestones/<file>.md --status MILESTONE_ACTIVE
# Dispatch any configured agent by role:
python -m scripts.orchestrator dispatch-agent --role planner --file docs/superpowers/specs/2026-07-25-slice-01-auth-design.md
# Override model at runtime:
python -m scripts.orchestrator dispatch-agent --role executor --file docs/superpowers/plans/2026-07-25-slice-01-auth-plan.md --model claude-sonnet-4
python -m scripts.orchestrator dispatch-planner --spec docs/superpowers/specs/2026-07-25-slice-01-auth-design.md
python -m scripts.orchestrator dispatch-executor --plan docs/superpowers/plans/2026-07-25-slice-01-auth-plan.md
python -m scripts.orchestrator set-status --file docs/superpowers/plans/2026-07-25-slice-01-auth-plan.md --status PLAN_APPROVED
python -m scripts.orchestrator trigger-hook --event on_slice_executor_start --dir .

This plugin routes work between agents. It does not make any of them think
better. That comes from skills β Markdown instruction files the harness
discovers by directory and the model loads on demand. Once a role names them
under skills:, every dispatch of that role carries them.
The single mistake worth avoiding. A skill that offers a way to think β
Dependency Rule, bounded contexts, stability patterns β composes with this
plugin. A skill that offers its own route from work to release (to-spec,
to-tickets, implement, tdd, wayfinder) competes with the state machine
you already run, and when both are active the model picks one silently and never
tells you.
Rule of thumb. If a skillβs description contains a workflow, you already
have one. If it contains a vocabulary, you probably want it.
| Source | What it is | Best for |
|---|---|---|
| wondelai/skills | 62 skills distilled from well-known books β Clean Architecture, DDD, Refactoring, Release It!, Design of Everyday Things. Pure Markdown, MIT, zero executable files. Each is a ~200-line SKILL.md plus references/ loaded only on demand. |
Exactly the lens shape described above. Start here. |
| skills.sh | The hub and the npx skills CLI: search across published repositories, install per skill, target any of 70+ agents (claude-code, opencode, codex, cursor, β¦). |
Discovery, and the one install path that works for both harnesses at once. |
Globally, for both harnesses, in one command β repeat -s per skill, because
the CLI does not parse a comma list and silently matches nothing if you use one:
npx skills add wondelai/skills -s clean-architecture -s domain-driven-design -s clean-code -s refactoring-patterns -a claude-code -a opencode -g -y --copy
Browse before committing to anything:
npx skills find --owner wondelai
| Flag | Why it matters |
|---|---|
--copy |
Required in practice. The default symlinks break on Windows and inside git worktrees. |
-g / -p |
-g installs per user (~/.claude/skills/, ~/.agents/skills/) and is visible from any working directory β including an executorβs isolated worktree. -p installs into the repository and writes a skills-lock.json pinning every skill by SHA-256, but then the files must be committed: git worktree add populates a worktree with tracked files only. |
-a |
Name each harness you dispatch to. At project scope one directory serves both; globally they use different ones. |
--all |
Donβt. A skill is an instruction that overrides model behaviour β installing a catalogue unread is running unread code, and every description sits in context for the rest of the session. |
wondelai also publishes a Claude Code marketplace (/plugin marketplace add wondelai/skills), but its collections are coarse: ux-design brings eleven
skills, systems-architecture six. Per-skill installation is what lets you take
two and leave the rest.
# .superpowers/agents.yaml β requires plugin >= 2.4.0
agents:
planner:
skills: [clean-architecture, domain-driven-design]
executor:
skills: [clean-code, refactoring-patterns]
skills is the only key set here, so model, harness and β importantly β
prompt_template keep coming from the pluginβs defaults and keep improving with
it. Name the lenses a role applies to its own decisions; there is no magic
number. A lens that changed nothing in the output was the wrong lens, and that
β not a count β is what limits the list.
Which lens suits which role:
| Role | Lenses | Why |
|---|---|---|
planner |
clean-architecture, domain-driven-design |
It decides which layer code belongs to and what the domain calls it β the decisions most expensive to undo later. |
executor |
clean-code, refactoring-patterns |
Craft at the code level. Architecture opinions here would compete with the plan it was handed. |
| (neither) | release-it, good-strategy-bad-strategy, ux-heuristics |
These serve whoever writes the spec or designs the screens β a human-facing session, not a dispatched role. Both harnesses discover them from disk anyway. |
Ask the harness what it actually resolved. No model call, no cost:
opencode debug skill
At dispatch the orchestrator asks the same question through the adapter and
prints a hint for any name it cannot find. That hint is advisory β skills are
reinforcement, not a dependency, so a missing one never blocks a dispatch. The
failure mode to watch for is therefore quiet: output that is weaker than it
should be, with a Hint: these skills are not visible to the harness line
scrolled somewhere above.
Two things the install output will tell you and this README will not: the CLI
reports Socket and Snyk risk rows per skill, and it emits install telemetry.
python -m pytest tests/ -v -p no:cacheprovider
No test invokes a real harness β dispatch tests wire in a stub adapter instead.
Available once the plugin is installed. Each wraps the CLI shown above; the
orchestrator path inside them is expanded by the harness, so nothing derives
it.
| Command | Effect |
|---|---|
/superpowers-multiagents:status |
Read the state of every milestone, spec and plan |
/superpowers-multiagents:new-milestone <id> <title> |
Create a milestone brief |
/superpowers-multiagents:activate-milestone <brief> |
MILESTONE_DRAFT β MILESTONE_ACTIVE |
/superpowers-multiagents:approve-spec <spec> |
DRAFT_SPEC β SPEC_APPROVED |
/superpowers-multiagents:approve-plan <plan> |
PLAN_GENERATED β PLAN_APPROVED |
/superpowers-multiagents:close-slice <plan> [--skip-merge] |
EXECUTION_COMPLETE β VERIFIED_CLOSED, merge, re-sync briefs |
/superpowers-multiagents:close-milestone <brief> |
MILESTONE_ACTIVE β MILESTONE_CLOSED |
/superpowers-multiagents:dispatch <role> <file> |
Dispatch a configured agent role |
milestone sync, milestone check, summary, trigger-hook and sandbox
have no commands β they are not steps of the operating procedure. Use the CLI.
close-slice merges feat/<slice_id> before it records the status, so it
refuses when that branch does not exist. --skip-merge closes the slice
without merging, for work that landed fast-forward or whose branch was deleted
once merged. It is an assertion the orchestrator cannot check: pass it only
when you know the work is already on the current branch.
superpowers-multiagents/
βββ .claude-plugin/
β βββ plugin.json # Claude Code / Desktop plugin manifest
β βββ marketplace.json # Marketplace descriptor: this repo publishes itself
βββ assets/
β βββ banner.png # Project banner graphic
β βββ icon.png # 24x24 project icon (PNG)
β βββ icon.svg # 24x24 project icon (SVG)
βββ commands/ # Slash commands over the orchestrator CLI
β βββ status.md # Read the whole lifecycle state
β βββ new-milestone.md # Create a milestone brief
β βββ activate-milestone.md # MILESTONE_DRAFT -> MILESTONE_ACTIVE
β βββ approve-spec.md # DRAFT_SPEC -> SPEC_APPROVED
β βββ approve-plan.md # PLAN_GENERATED -> PLAN_APPROVED
β βββ close-slice.md # EXECUTION_COMPLETE -> VERIFIED_CLOSED
β βββ close-milestone.md # MILESTONE_ACTIVE -> MILESTONE_CLOSED
β βββ dispatch.md # Dispatch a configured agent role
βββ docs/
β βββ architecture.md # Module structure & design principles
β βββ configuration.md # Full agents.yaml schema reference
βββ hooks/
β βββ hooks.json # Hook registration
β βββ session-start # SessionStart prompt injector
βββ skills/
β βββ multiagent-orchestrator/
β βββ SKILL.md # Multi-Agent orchestrator instructions
βββ scripts/
β βββ orchestrator.py # CLI entry point & command handlers
β βββ config.py # DEFAULT_CONFIG & agents.yaml loader
β βββ errors.py # Exception hierarchy
β βββ paths.py # Runtime artifact layout
β βββ runner.py # Supervisor for background agent execution
β βββ frontmatter.py # YAML frontmatter parsing & atomic updates
β βββ git_ops.py # Git worktree & merge operations
β βββ hooks.py # Infrastructure hook execution
β βββ locks.py # File-based slice locking
β βββ dependencies.py # Slice dependency checking
β βββ utils.py # ID validation, YAML conversion, project root
β βββ adapters/
β βββ __init__.py # Public adapter API
β βββ base.py # HarnessAdapter abstract base class
β βββ opencode.py # OpenCode CLI adapter (default)
β βββ loader.py # Dynamic adapter resolution & custom loading
βββ tests/
β βββ test_orchestrator.py # Pytest test suite
β βββ test_docs_consistency.py # Documentation and metadata verification
β βββ test_set_status.py # Status transition tests
β βββ test_hook_events.py # Hook event firing tests
β βββ ...
βββ .superpowers/
β βββ logs/ # Runtime execution logs (created on dispatch)
β βββ locks/ # Slice lock files (created on dispatch)
βββ package.json
βββ requirements.txt # Python dependencies (ruamel.yaml, pytest)
βββ README.md
Distributed under the MIT License.