It is a zero-dependency CLI that bootstraps an agentic AI control plane into any repo. It works with Vue, React, Python, and any other codebase. It is compatible with Claude Code, OpenCode, Gemini CLI, Cursor, and other coding agents.
Our workflow follows this core engineering ladder: Plan → Decompose → Parallelize → Execute → Validate → Trace.
- Composable planning: Structured definition and decomposition of tasks.
--ascognition: Pre-flight explanations and step-by-step blueprints.- Waves: Orchestrated, parallel execution scheduling.
- Artifact graph: A concrete trail of evidence connecting requirement to validation.
- Model routing: Dispatching the right model for the right job.
We orchestrate what needs to happen (plan, execute, validate), not who does it. The command is the contract. For a detailed look at how this solves a different problem than tools like BMAD, GSD, or Spec Kit, see our Agentic Coding Comparisons page.
cd my-project/
npx wb-flow
npm install -g wb-flow
cd my-project/
wb-flow
git clone https://github.com/wissemb11/wb-flow.git ~/.wb-flow
cd my-project/
node ~/.wb-flow/bin/install.js
git clone https://github.com/wissemb11/wb-flow.git
cd wb-flow && npm link
cd ~/my-project/
wb-flow # uses your local clone
--force/-f— overwrite existing files (default: skip existing)--dry-run/-n— preview without writing--list/-l— print the bundled command roster and exit--version/-v— print the installed version--help/-h— show usage
By default, wb-flow is non-destructive — it skips files that already exist. Pass --force to overwrite, or --dry-run first to preview.
Copying the templates puts the procedures on disk. To type /wbPlan src/api instead of "read this template and run it", your assistant also needs a small command file — one per assistant, in its own format and location. wb-flow init writes them for you:
wb-flow init
🚀 wb-flow init — wiring the /wb* commands into your assistants
Where should the /wb* commands be available?
1) Globally — every project on this machine
2) This project only — /home/me/my-project
> [1]
Which assistants should get the commands? (detected ones default to Yes)
Claude Code → ~/.claude/commands [Y/n]
OpenCode → ~/.config/opencode/command [Y/n]
Gemini CLI → ~/.gemini/commands [y/N]
Antigravity (agy) → ~/.gemini/config/skills (skill — agy has no slash-commands) [Y/n]
It does both layers in one pass: copies the templates to a stable home, then writes the wrappers.
| Assistant | Location (global / project) | Format |
|---|---|---|
| Claude Code | ~/.claude/commands/ —.claude/commands/ |
<cmd>.md +$ARGUMENTS |
| OpenCode | ~/.config/opencode/command/ —.opencode/command/ |
<cmd>.md +$ARGUMENTS |
| Gemini CLI | ~/.gemini/commands/ —.gemini/commands/ |
<cmd>.toml +{{args}} |
Antigravity ( agy ) |
~/.gemini/config/skills/ —.agents/skills/ |
one wb-flow/SKILL.md dispatcher |
| Cursor | project only — .cursor/commands/ |
<cmd>.md |
| Codex | ~/.codex/commands/ —.codex/commands/ |
<cmd>.md +$ARGUMENTS |
Scope decides where the templates live and how wrappers reference them: global copies to ~/.wb-flow/ and embeds absolute paths (works from any project); project copies to ./.wb/ and embeds relative paths (commit them, and your team gets the commands too).
Antigravity is the one exception — it has no user-definable slash-commands (only Rules, Skills, Plugins, Hooks and MCP), so all commands collapse into a single skill activated by natural language: run wbPlan on src/api, not /wbPlan.
wb-flow init --scope=global --agents=claude,opencode -y # unattended
wb-flow init --scope=project --agents=all --dry-run # preview
wb-flow init --agents=detected # only installed assistants
wb-flow init --templates=/path/to/templates # reuse an existing root
--force overwrites existing wrappers; without it they're skipped. In a non-TTY (CI) --yes is required, otherwise init refuses rather than hangs.
Nothing is magic — a wrapper is three lines. If you'd rather not run init:
mkdir -p ~/.claude/commands
TPL="$HOME/.wb-flow/commands" # or .wb/commands for a project install
printf -- '---\ndescription: Creates a task plan\n---\n\nRead `%s/wbPlan/wbPlan_template.md` and execute it.\n\nArguments / target: $ARGUMENTS\n' "$TPL" \
> ~/.claude/commands/wbPlan.md
And with no wrapper at all, in any assistant:
read .wb/commands/wbPlan/wbPlan_template.md and execute it on src/api
/wbSetup . # Read the codebase — generates context.md + dev.md
/wbPlan "add dark mode" # Break the goal into a ranked task table
/wbWork --id=1 # Execute the first task, fully traced
/wbValid # Verify: does the work match the plan?
That's a full cycle: plan → execute → validate, guided by your AI assistant.
You are reading v1.0.5. The deep-dive below covers v1.0.2, the last release with a full
write-up. 1.0.5 is itself a feature release — a self-maintaining model catalog
(wb-flow model --sync-catalog / --add), fallback chains on every dispatch flag, and
role-variable wave matrices. It also ships the plan trust model,
wb-flow wave --sandbox dispatches whose refusals are scored REFUSED rather than PASS, a
content-hash no-op gate over the whole workspace, and a prepublishOnly backup-artifact assert
that keeps files such as bin/model.js.bak out of the npm tarball. See CHANGELOG.
The two releases since it are maintenance-only and are documented in
CHANGELOG.md:
1.0.3 — --command emission gated to opencode (it broke every /wbValid wave cell on
claude and grok), the --no-merge wave flag, and a publish-runbook dotfile-copy fix ·
1.0.4 — README hero media and a corrected comparisons link; no change to bin/ or
templates/.
Local error guarding in action: when a provider returns an error with exit code 0, the chain now detects it and fails over instead of silently reporting success.
wb-flow now ships a set of subcommands alongside the /wb* slash-command templates —
init, lint, model, next, snap, wave, watch and archive. The three that changed most in this
release, plus watch and archive which are new:
wb-flow init — one command to install everything: copies templates to a stable home, wires/wb* slash-commands into Claude Code, OpenCode, Gemini CLI, Antigravity, and Cursor, and seeds the model roster. Detects installed assistants, offers interactive role-ranking, and writes wrapper files in each assistant's native format. Fully flag-driven for CI (--scope ,--agents ,--yes ). #
wb-flow lint — check plan files against the output conventions and sync rules to catch structural errors before closing a plan. #
wb-flow model — the single writer of the model roster.Detects credentialed models from every installed CLI (opencode providers list ,agy models ,claude ), ranks them by role with pattern-based preference (newest-version-first, family-collapsed), and writes the result tocommands/model_recommendations.md .--pick (-i ) opens an interactive tree-picker annotated withbilling pool ,Model Role Qualification Badges (🧠, 💻, ⚡, 🔨), and probe results — making visible that three names can be one point of failure.--probe --all pre-verifies reachability across the catalog, now supporting multiple modes:--all (default) orders reachable models by Role,--all=raw streams all results including failures,--all=<provider> filters to a specific provider, and--all=<role> filters to a specific role — all of which work identically with or without--pick .--set <role>=<slug> ,--json ,--dry-run ,--file= . #
wb-flow next — regenerates the▶️ How to run this plan block at the bottom of the plan file. It parses the🌊 Next Executable Sequence matrix and derives four explicit, non-overlapping execution scenarios. Shell out to it (wb-flow next <plan.md> --embed ) from any/wb* command that alters a plan's state so the run-book stays in sync with the matrix. #
wb-flow snap — pins the current output into.wb/snaps/<YYYYMMDD>_<label>/ as a symlink (or a copy with--snap-copy ) so you can easily find it later. Universal across all/wb* commands via the--snap=<label> flag. #
wb-flow wave — the wave orchestration engine. Takes a plan file's## 🌊 Next Executable Sequence DAG matrix and converts it into collision-free parallel background dispatches. Routes cells by role: Planner stays in-session with the orchestrator; Worker and Mechanical dispatch toopencode run (oragy , or the native CLI of whatever model you picked); Validators run in-session unless they pair a row the orchestrator executed. Spawned agents get--no-plan-update — they write only their task report; the orchestrator checks the boxes and recomputes the matrix once, after the wave settles. #
wb-flow watch — live status of the cells a wave left running in the background. Renders per-cell progress as a share of the plan's ownEst. Time (mins) column, and marks a cellOVER est Nm by Mm once it passes that budget —that , not raw elapsed time, is what separatesslow fromhung . Liveness is read from the process table (pgrep ), never from log mtime: agents buffer while composing, so an idle log does not mean a dead cell. Three states, never two —✅/❌ finished,🔄 running,⚠️ ENDED for a cell with no verdictand no process (killed or crashed).-1 for a one-shot snapshot,--list for past runs,--run= to pick one. It reports whatwave.js recorded, so treat it as a progress view and confirm outcomes with the row's ownVerify oracle. #
wb-flow archive — retires superseded daily reports so a scope's reports/ tree holds only thecurrent file per category. Moves each<YYYY>/<MM>/<DD>/<category>/ folder —whole , because a plan'stasks/ andwaves/ are its siblings — into.wb/workflows/archives/ at thesame depth , so relative links inside the moved files keep resolving unchanged. The newest folder per category is never a candidate, and keepers are resolvedper category .standups/ andtracks/ are exempt: they ARE the log. Every move is banner-stamped, logged, and reversible with--restore= .-n to preview,--recursive for a whole monorepo.
wb-flow model and wb-flow init read a .env file from the current working directory — your project's, not wb-flow's — falling back to ~/.wb-flow/.env when the working directory has none. They load only keys matching a known provider prefix (GROQ_, OPENROUTER_, ANTHROPIC_, OPENAI_, GEMINI_, …) into the environment. Those values are inherited by the agent CLIs wb-flow spawns (claude, agy, opencode, codex), which is the point: wb-flow itself never reads an API key. Keys outside the prefix list are skipped and counted on stderr. Extend with WB_FLOW_ENV_ALLOW="MYVENDOR_"; restore the old load-everything behaviour with WB_FLOW_ENV_ALL=1. wb-flow does not add .env to your .gitignore — check that yourself.
A template ships at templates/.env.example with every provider key name and blank values — copy it to ~/.wb-flow/.env (global) or ./.env (per-project, takes precedence) and fill in the providers you actually use. Leave a key blank to skip that provider.
models.json is the catalog (which models exist, and the provider that decides their CLI). Its default ships in the package and wb-flow init copies it to ~/.wb/models.json — only if absent, so your edits survive upgrades. selected.json is your picked roster in priority order, written by wb-flow model --pick; it is generated, not shipped. Both are plain JSON and meant to be hand-edited — add a provider, reorder a chain, swap a model. --wave dispatches each role's chain left to right (model1 || model2 || model3), reading the most recently written commands/model_recommendations.md. See docs/commands/wbModel/README.md.
wb-flow model --show and wb-flow wave can report different rosters.--show reads the first roster file in the current directory; wave reads the most recently written one across the package root, repo root and ~/.wb-flow/. For what a wave will actually dispatch, use wb-flow wave <plan.md> --wave=<L> --list — it prints 📋 Roster in effect: with the resolved file and the full chain per role. Details: wbModel/README.md.
⚠️
Passing an existing output file with no other flags now means "make this the one file I have to read":
/wbPlan <plan_file.md> # absorb every older open task, then repair in place
/wbPlan <plan_file.md> --archive # …then retire the plan folders it just emptied
/wbStandup <monorepo-root>/ --archive # fleet-wide: one live file per category, per scope
A month of work leaves thirty plan files, of which one is live. The rest are decoys — and a stale plan is more dangerous than a missing one, because it answers confidently and wrongly.
🔴 Consolidate always runs before archive. Archiving first does not delete an open task, it
makes it invisible: nothing live references it, and the next /wbStandup no longer scans the tree
it sits in. Archiving is therefore opt-in and never implied by another flag.
/wbStandup and /wbTrack are exempt — their value is the series, so keeping only the newest
destroys the thing worth reading. /wbStandup --archive instead sweeps everything else.
See Report Lifecycle.
--summary (on by default in wave mode) — streams only the decision lines (▶ dispatch marker,G1/G2/G3 gate results,VERDICT ) to the terminal. Each cell's full output still goes to its log file viatee . Measured on a real 10-cell validation wave:63,002 tokens streamed without it, of which one cell alone was 16,824 —ls -la dumps, ANSI escapes and template reads that no Done box depends on. Pass--no-summary to get the full stream while debugging a single cell. #
--sessions — reuses one warm opencode session per (scope, model). A cold dispatch re-reads its command template and context files every cell; with--sessions the session isresumed and forked so parallel cells each get their own branch off the same warm base. Opt-in because a resumed session replays its conversation history — measureopencode stats --days 1 --models both ways before making it habit.
Every background cell spawned by wb-flow wave runs through .wb/bin/wbRun, a local subshell guard that intercepts stdout and stderr, not just exit codes. A model that returns exit 0 with the text Error: Insufficient credits is indistinguishable from success by || chaining alone. wbRun catches fatal API-level strings, displays visual banners (▶ Executing: / ❌ Failed:), and automatically fails over to the next model in the || fallback chain. The chain advances on Gate 1 (Infra) only — a Gate 2 or Gate 3 retry meets the same wall at double cost, so re-dispatch after those is a human decision.
Every cell dispatched by wb-flow wave is classified by three gates — never by its output text:
| Gate | Question | Signal |
|---|---|---|
| 1 · Infra | did the agent run at all? | CLI exit code, plus anchored fatal patterns ( ^Error: Model not found , rate limit, quota) |
| 2 · Artifact | did it write what it was required to write? | tasks/task_<ID>/task_<ID>_report_*.md exists |
| 3 · Oracle | does the task's own Verify command pass? |
exit 0 |
| G1 | G2 | G3 | Verdict | Done box |
|---|---|---|---|---|
| ✗ | — | — | INFRA — never ran | ⬜ |
| ✓ | ✗ | — | NO-OP — ran, produced nothing | ⬜ |
| ✓ | ✓ | ✗ | ATTEMPTED — needs a validator | ⬜ |
| ✓ | ✓ | ✓ | DONE | ✅ |
Output string-matching is forbidden as a success signal. A /wbWork log legitimately contains Error: and failed whenever the task is about error handling — and those are the rows where a false verdict costs most.
A plan file is one authored table plus four derived projections of it — status callout, 🌊 matrix, how-to-run block, What's Next — regenerated in that order, because each derives from the one before.
-
📝 Wave notes externalized to
tasks/waves.md; the plan keeps a one-line pointer. Notes grow every wave — inline, they push the task table below a screen of prose about waves that already ran. -
▶️ How-to-run block relocated to sit directly beneath the 🌊 matrix table it is computed from.
-
🔗 Multi-ID merged dispatches — cells sharing a wave, scope, role and model merge into
--id=5,6: one context read instead of N, with per-ID gating preserved.Batching yields to executor≠validator, never the reverse — two validate cells sharing a model must not merge if their ids had different executors, or the merged verdict silently self-validates. -
🌊
--wave=Ameans work then validate (A.work→A.valid), so a wave is a complete unit rather than a promise redeemed a wave later. One label per invocation —--wave=C,Ddoes not exist. -
📋 Four copy/paste scenarios below every matrix, individual dispatches always carrying an explicit
-M="…". -
✅ The sync oracle (
sync_check.sh) exits non-zero and names the derived block that drifted. A plan that fails it is not slightly out of date — it is actively misleading, and every downstream dispatch inherits the error. -
👀
wb-flow watchshows the task#idand description , not just the model — a glance answers "which of the four is the slow one"./wbWorkcloses with a continuation signoff so the screen shows work is live rather than looking idle. -
🎛️ Universal model flags (
--planner,--worker,--validator,--mechanical,--model) accepted by every/wb*command. Role flags persist (equivalent to running/wbModelfirst).-M="<model>"delegates a single invocation and outranks everything. -
⚡ Autonomous Wave Auto-Pilot (
-y/--yes) : Zero-touch background execution and wave script spawning. -
📌 Persistent Model Rosters & Matrix Auto-Correction : Embeds model rosters in plan matrix headers and repairs missing matrices on
/wbPlanor/wbWork. -
📚 Uniform 9-File Docs Suite : Complete 9-file suite across all 33 commands (306 files).
See the full What's New Guide and Detailed Technical Release Notes.
The complete reference — all 33 commands, workflow concepts, daily use patterns, and session lifecycle — is available in two places:
- → What's New in v1.0.2 — concise summary of the last feature release
- → CHANGELOG — every release, including1.0.5 (feature) and the two maintenance releases before it
- → Detailed Technical Guide — comprehensive code & terminal examples
- → GitHub Docs — browse the full documentation hub
- → flow.wbc-ui.com — the dedicated documentation website
This documentation — all 250+ files, 33 command references, and concept pages — was itself planned, audited, and validated using wb-flow. Every task was tracked via /wbPlan, every page was scored via /wbAudit, and every commit was generated via /wbGit. The tool eats its own cooking.
wb-flow is created and maintained by Wissem Boughamoura.
-
🐙 GitHub:@wissemb11/wb-flow
-
📦 npm:wb-flow
-
📚 Documentation:flow.wbc-ui.com ·GitHub Docs
-
👤 Author:Wissem Boughamoura —
wissemb11@gmail.com -
Bugs / feature requests → GitHub Issues
-
General questions → email
wissemb11@gmail.com
License: MIT © 2026 Wissem Boughamoura. See LICENSE. Changelog: see CHANGELOG.md.
wb-flow ships a skeleton catalog — provider names only, no models — because a catalog copied
from someone else's machine fails late and confusingly. Fill it from your own CLIs:
wb-flow model --sync-catalog # everything this machine can reach
wb-flow model --add=zen,codex # or one provider at a time
wb-flow init does this for you on a fresh install.