flow-workflows
v0.79.0
Published
Guided feat/bug workflows (start→ship), post-deploy monitoring and multi-agent code review, stack-agnostic. Each repo uses a shared FLOW.md plus optional harness overlay.
Maintainers
Readme
flow-workflows
Guided feat / bug workflows for terminal coding agents: a ticket reaches an open MR/PR through explicit, reviewable phases, not one big prompt.
For developers running Claude Code (or zcode, opencode, Gemini CLI, Codex CLI, Hermes Agent) on real repos with tickets, reviewers and a deploy.
You get named phases, an artifact on disk after each one, hard gates the agent never crosses alone, and an autonomy dial from "ask me everything" to "run it and record what you decided".
Quickstart
Claude Code
/plugin marketplace add mashware/flow-workflows
/plugin install flow@flow-plugins
/flow:init # writes FLOW.md for this repo — auto-detects, asks the minimum
/flow:next # routes you to init, resume or status, depending on where you areCodex CLI — same plugin, and its skills are invoked with $flow:
codex plugin marketplace add https://github.com/mashware/flow-workflows.git
codex plugin add flow@flow-plugins
# then, in a new session: $flow:init · $flow:nextzcode — same plugin, from its own marketplace
zcode plugins marketplace add mashware/flow-workflows
zcode plugins install flow@flow-plugins
# then, in a new session: /flow:init · /flow:nextopencode, Gemini CLI, Hermes Agent — one command, nothing to clone
npx flow-workflows install opencode # or: gemini | hermes | codex
npx flow-workflows check # is a newer version out?Re-run the same line to update: it sweeps the previous version before copying. → Other harnesses
No ticket? /flow:feat:start with no arguments drafts the work from the conversation you just had.
The first minute
One XS work, start to ship. Four commands; each one stops with the same header and waits for you.
$ /flow:feat:start PROJ-412
PROJ-412 · XS · phase start
Now: ticket read, sized XS, branch PROJ-412-digest-unsubscribe created
I need: confirm the brief — an unsubscribe link in the digest footer, no template rework
$ /flow:feat:build
PROJ-412 · XS · phase build
Now: footer partial and the opt-out check, 2 files, suite green
I need: nothing, review is next
$ /flow:feat:review
PROJ-412 · XS · phase review
Now: 3 reviewers, one finding — the link skipped the locale fallback — fixed · spent 3/12
I need: nothing, XS skips validate; ship is next
$ /flow:feat:ship
PROJ-412 · XS · phase ship
Now: MR preview ready — 2 files, +34 −4, description and test notes below
I need: confirm the preview and I pushdesign, plan and validate never ran: XS prunes them. What is on disk afterwards is the work
itself, readable and editable without the agent:
.claude/work/PROJ-412-digest-unsubscribe/
├── 00-summary.md # the ≤15-line handoff every phase reads first
├── meta.json # phase, size, branch, the MR it opened
├── panel.json # live state, for a pane outside the chat
├── 01-context.md # ticket, size, the questions asked at the brief
├── 05-implementation.md # what was built, and where it left the plan
└── 06-review.md # every finding, and what was done about itNot everything is a work. A typo, a version bump, a log level: edit it and commit — a folder, a
branch and a review panel cost more than that change is worth. /flow:feat:start makes that call
itself and offers you the two-line alternative. → PHILOSOPHY §When not to use it
The two chains
feat start → design → plan → build → review → validate → ship
(§1.5 (M/L) └─── repeats per MR/PR of a train ───┘
approaches
on M/L)
bug start → investigate → fix → validate → review → postmortem → ship
(§1.5 reproduce, (M/L)
then the cause)
after ship, before merge: green ⟲ pipeline red / conflicts / behind base
respond ⟲ reviewer threads: triage, debate, change, reply
size prunes: XS start → build → review → ship S + design (abridged) + validate
M/L full chain; plan splits the work into stacked MR/PRsThree ideas you will not find in the other workflow plugins
- An autonomy dial that does not decay.
autois only worth having if it never drifts back into asking, so the list of whatguided/automust never ask about is written down and enforced, next to the hard gates that stop in every mode. → Autonomy - A cost ceiling per command, and the cost printed in the output. Two ceilings that count agents
rather than findings — one per parallel round, one for everything a command run launches — each
command declaring which phase it gives up first, and
reviewreportingspent/budgetand what the ceiling skipped. → Token budget - Work you decide not to do does not evaporate. Every out-of-scope piece, unmitigated risk and
unchecked edge case becomes a record in
meta.json, triaged once atshipwith one question each, and named in the MR/PR description if it is still open. → How it works
Autonomy
autonomy.mode in FLOW.md, changeable at any time:
| Mode | Decisions | Next phase |
|---|---|---|
| manual (default) | Stops at every one | Proposed as a one-click confirmation, never run unconfirmed |
| guided | Resolves low-risk ones and records them; asks at the real ones | Chains automatically |
| auto | Also resolves the rest, with recorded defaults | Chains without pausing |
Hard gates — the flow stops and asks in every mode:
- Any push or MR/PR creation (all of
ship). - Creating a branch when the base is ambiguous.
- A DB schema change or migration.
- Shipping a review with high-severity findings.
- The business brief before touching code — what you get afterwards, and what is not included.
Symmetrically, guided/auto never ask about the flow's own machinery (panels, reviewer counts, WIP commits, the next MR/PR of a train). → CONFIGURATION §autonomy
Commands you will use every day
| Command | What it does |
|---|---|
| /flow:next | Entry point — routes to init, resume or status depending on where you are |
| /flow:feat:start | Read the tracker, classify size, create the branch and initial artifact |
| /flow:feat:build | Implement following the approved design, keeping a log |
| /flow:feat:review | Mandatory multi-agent code review before shipping |
| /flow:feat:ship | Commit, push, open the MR/PR, offer to save domain knowledge |
| /flow:bug:start | Start the incident flow (tracker, size, branch, initial artifact) |
| /flow:bug:fix | Implement the minimal fix and keep a log |
| /flow:work:status | All open work items and their next step |
| /flow:work:resume | Resume the work tied to the current branch |
| /flow:work:green | Mergeable loop — the MR/PR cannot merge: triage, fix at the root, push. Never green-washes |
| /flow:work:respond | Review loop — triage the threads, debate, implement what you agreed, reply. Never resolves threads |
Everything else
| Command | What it does |
|---|---|
| /flow:feat:design | Options and angles first (M/L), then architecture, DB, APIs and risks — before touching code |
| /flow:feat:plan | Split the work into small, independently mergeable MR/PRs |
| /flow:feat:validate | Tests, edge cases and integrity — drives the app itself before asking you to |
| /flow:bug:investigate | Reproduce the failure, then find the root cause and not the symptom |
| /flow:bug:validate | Regression test that fails before, passes after |
| /flow:bug:review | Multi-agent code review of the fix |
| /flow:bug:postmortem | Lessons learned, areas to monitor (M/L incidents) |
| /flow:bug:ship | Commit, push, MR/PR for the fix (carries the postmortem summary) |
| /flow:init | Wizard that generates this repo's FLOW.md |
| /flow:doctor | What FLOW.md resolves to — set vs empty and its fallback — then whether the environment honours it: CLIs installed and authenticated, agents, hooks, MCP |
| /flow:work:query | Query duel — fact sheet, blinded challenger, verdict by execution plan against the base version |
| /flow:work:watch | Post-deploy watcher — monitors observability, flags regressions |
| /flow:work:daily | Standup across local + forge + tracker; ask a question or get the briefing |
| /flow:work:try | Point the main checkout at a branch to test it, and print the manual test plan once it is up (then --back) |
| /flow:work:clean | Sweep merged worktrees, dead branches, unarchived folders. Never deletes on a guess |
| /flow:work:abandon | Close a work item without shipping |
| /flow:news | What changed in the plugin since the version you last saw |
What a work looks like on disk
One folder per work under .claude/work/, named <TICKET>-<slug> (or <slug> when ticket-less):
.claude/work/PROJ-123-billing-retry-window/
├── 00-summary.md # ≤15-line handoff, read first by every phase
├── meta.json # source of truth: phase, size, branch, MR/PRs, related repos
├── panel.json # live state for an external reader (below)
├── 01-context.md # ticket, size, branch, first questions
├── 03-design.md # approaches considered + architecture + ADR-light + external contracts
├── 04-mr-plan.md # the MR/PR split, order and dependencies
├── 05-implementation.md # running log, deviations from the design
├── 06-review.md # findings and what was done about them
├── 07-validation.md # tests, edge cases, integrity
├── 08-feedback.md # respond: one entry per review round
├── 09-ci.md # green: one entry per round of merge blockers
└── evidence/ # what validate observed in the running app; ship attaches it to the MR/PRA bug writes 03-investigation.md (reproduction, then root cause), 04-fix.md, 05-validation.md, 06-review.md and, on M/L, 99-postmortem.md. abandon writes 99-abandoned.md and moves the folder to _archive/.
Artifacts are hand-editable: rewrite 03-design.md and the next phase respects it. meta.json is the state; without it, commands refuse to continue rather than guess.
Configuration: base plus harness overlay
FLOW.md at the repo root is the shared base. FLOW.claude.md, FLOW.codex.md,
FLOW.opencode.md, FLOW.gemini.md, FLOW.hermes.md, or FLOW.zcode.md can sparsely override values for the product executing the
command. Existing repos with only FLOW.md behave exactly as before; anything effectively empty
is auto-detected or asked for.
| Section | What it configures |
|---|---|
| tracker | Ticket prefix, CLI, view and comment-thread commands, state transitions |
| git | Host (which decides the term and the CLI), base branch, branch pattern, MR/PR sections, squash, worktrees, pre-deploy gate |
| autonomy | manual · guided · auto (hard gates always ask) |
| quality | Test / lint / analysis / DB commands, review_depth, review panel, respond_max_rounds, functional_check, evidence |
| agents | Role → specialist agent map, cost ceilings (fanout_max per round, budget_max per command), fan-out orchestrator (fanout_tool) |
| models | Model for the subagents — agents (improvised ones) · workers (fan-out rounds) |
| data | How to read a query's execution plan and the real size of the hot tables |
| conventions | Rules the code must respect |
| notes | Extra mandatory instructions per command |
| knowledge | Knowledge sources by role — search, stage, read_staging, save — any MCP (domain-memory, codegraph…), CLI or skill |
| observability | The profile /flow:work:watch monitors after a deploy |
/flow:init writes a compact base and creates the active overlay only when it has a
harness-specific value. It offers to git-ignore /FLOW.md, /FLOW.*.md, and .claude/work/.
Both files are personal config, not team config
(why). Resolution and examples:
CONFIGURATION.
How it works
Two mechanisms that are easy to miss in the command list and are most of what makes the flow usable on real work.
Work you decide not to do does not evaporate. Every "idea for a separate ticket", out-of-scope piece, unmitigated risk, unchecked edge case and postmortem prevention action becomes a record in meta.json, not just a line in an artifact that gets archived unread. The phases that park them ask nothing. ship triages the whole set once, at the end, with one question per item: do it (which opens the tracker issue and offers to start it), not worth it, or later. Whatever is still open when the MR/PR is created is named in its description, so a reviewer can see what was consciously left out. status, daily and next keep surfacing the undecided ones — including from _archive/, because a finished work is exactly when its deferrals become invisible. Two things are deliberately not deferred work: a product decision the current diff depends on is asked the moment it surfaces, in every mode, because parking it makes the diff guess; and a gap in the repo's own tooling is recorded in the work and never asked about, because a tracker where those outnumber the product's defects makes the number lie.
The live panel makes the work readable from outside the chat: every stop is published there too, so a pane or dashboard can show the MR/PR train with links, what runs now, what comes next, whether it waits on you, and any blocker. Each line says what it is (mark: done current pending wait block info); the reader owns symbols and colours. Published before a long stretch, so a step that died halfway never shows as finished, and carrying the phase running, not the one meta.json records. A terminal that offers the panel_set / panel_patch tools takes the panel through them — the first publication claims the pane, every change after it is a patch; anywhere else the same document is .claude/work/<work>/panel.json, overwritten whole with an honest updated_at. Document and transports: work/README.
Token budget
A phase costs turns × context, plus what it writes. The API keeps no state, so every tool call
resends the whole conversation: a 40-turn build carrying 70k of context pays for those 70k forty
times, even though the window never grows past 70k. Prompt caching makes the resent part roughly ten
times cheaper, which is why the number that matters is turns, not the size of a command file. Every
design decision below follows from that one line.
- Fewer turns per phase. The shared rules live in the
flow-coreskill, loaded once per session; a command file carries only its phase. Every phase readsmeta.jsonand00-summary.mdfirst and opens a full artifact only on demand — a handoff read in one turn instead of rediscovered in ten. - Fewer agents, declared in advance. Two ceilings, both counting agents rather than findings:
agents.fanout_maxper parallel round (default 4) andagents.budget_maxfor everything one command run launches (default 12). Each command declares which phase it gives up first, and what a ceiling drops is reported. - A tier that matches the diff, not the ticket. The review scales to the diff under review: a 40-line MR/PR inside an L-sized work is reviewed as the 40 lines it is.
- Bounded output. Output tokens are the most expensive kind and are never cached.
agents.report_max_words(default 250) is a cost ceiling as much as a format rule. - The cost is printed.
reviewreportsspent/budget— subagents launched, tier, effort, and every phase the ceiling skipped.
When it costs too much
Ordered by effect. Each is one line in FLOW.md:
| Change | What it drops | What you lose |
|---|---|---|
| models.supervisors to a cheaper tier | The waits — a running pipeline, a deploy that has not landed, a long suite — stop being watched on the thread's model | Nothing: a supervisor reports status and evidence, and the verdict on them was never its to give |
| models.agents / models.workers to a cheaper tier | Subagents stop running on the thread's model | Little: a subagent reads a diff and reports ≤250 words |
| quality.review_depth: light | The panel, the reinforcements, the skeptic fan-out | Depth on everything but the built-in reviewer; a sensitive surface still bumps back up |
| agents.budget_max, agents.fanout_max | Rounds past the ceiling, in the order each command declares | Coverage — but named coverage: what a ceiling skipped is reported, never silently dropped |
| agents.report_max_words | Output length per subagent | Detail in reports, not findings |
Two things that cost real money and look free. The first: a cache entry expires, so a phase run
in one sitting is cheaper than the same phase spread across an afternoon — coming back after a long
pause, the next turn repays the whole prefix at write price. The second: /compact is not a saving.
It rewrites the history the provider has already priced and stored, so the turn after it pays for
everything again. Nothing here ever asks you to compact, because the phase boundary already is the
compaction point — selective, on disk and reversible.
→ PHILOSOPHY
Cost figures in these docs are estimates, not measurements: the flow reports how many agents a
command launched, not how many tokens they spent. Quality used to be in the same position and no
longer is, for one command. /flow:feat:review has a bench —
plugins/flow/evals/ — that runs it over fixtures whose outcome is
known: a defect seeded at a known file:line the review has to raise, and a clean diff where any
blocker it reports is a false positive. Every other phase is still argued from judgement, and the
design decisions inside review itself were too, until there was something to check them against.
Other harnesses
The same commands, in each harness's own shape. Only the invocation syntax differs:
| Harness | Install | Invoked as |
|---|---|---|
| Codex CLI | codex plugin add flow@flow-plugins (see Quickstart) | $flow:feat-start |
| Codex CLI, one repo only | npx flow-workflows install codex project → .agents/skills/ | $flow-feat-start |
| zcode | zcode plugins install flow@flow-plugins (see Quickstart) | /flow:feat:start |
| opencode | npx flow-workflows install opencode | /flow-feat-start |
| Gemini CLI | npx flow-workflows install gemini | /flow:feat:start |
| Hermes Agent | npx flow-workflows install hermes | /flow-feat-start |
Updating is the same command again — it removes the previous version's files first, so a command
dropped upstream does not linger. npx flow-workflows check compares what your harnesses run
against the newest release. From a clone, adapters/install.sh <harness> [project] does the same
thing without Node; the preflight installs both ways and fails if the results differ by one byte.
zcode reads this plugin package directly and names a command after its path, with no plugin
prefix — so the /flow:-prefixed set it installs is a generated mirror living beside the Claude
one, and the plugin's own pages also show up there unprefixed (/feat:start, /init, …). Those
name Claude's overlay, so type the /flow: names.
The mirrors are generated from the plugin commands by script/adapter-build.py and checked mechanically on every preflight (format, prefix, cited paths, install location).
They have not been executed end to end in those harnesses — validate as you use them. → adapters/README
Documentation
| | |
|---|---|
| CONCEPTS | Glossary — every term, with where it is specified |
| PHILOSOPHY | Why it is built this way (short) |
| DESIGN | The rationale behind every rule |
| CONFIGURATION | Complete FLOW.md reference |
| WORKFLOWS | green, respond, query, watch, daily, clean, cross-repo tasks |
| work/README | Internal guide: principles, schemas, size shortcuts, golden rules |
| CHANGELOG | What changed, version by version |
| adapters/README | Installing on opencode / Gemini CLI / Codex CLI / Hermes Agent |
| RELEASING | Release procedure and what the preflight enforces |
| CONTRIBUTING | What a good contribution looks like, and what we will not take |
Structure
flow-workflows/
├── .claude-plugin/marketplace.json # catalog (Claude Code)
├── .github/ preflight CI · issue forms · PR template
├── plugins/flow/
│ ├── commands/ feat/ bug/ work/ + next, init, doctor, news
│ ├── codex-skills/ · zcode-commands/ # generated mirrors for the two other plugin hosts
│ ├── skills/flow-core/ # shared rules, loaded once per session
│ ├── hooks/ push guard · update notice · where-you-left-off notice
│ └── examples/ FLOW.template.md · symfony/ (a worked example, never loaded)
├── docs/ CONCEPTS · PHILOSOPHY · DESIGN · CONFIGURATION · WORKFLOWS
├── script/check.py # release preflight
├── script/adapter-build.py # generates the adapter mirrors
├── script/adapter-smoke.py # are the mirrors usable?
├── script/tests/ # hook tests
├── RELEASING.md · CONTRIBUTING.md
└── adapters/ install.sh · opencode/ · gemini/ · codex/ · hermes/Before tagging a release
python3 script/check.py # preflight: manifest, JSON/TOML, hooks, frontmatter, mirrors (static)
python3 script/adapter-smoke.py # also runs install.sh against a throwaway HOME
bash script/tests/push-guard.sh # the push guard's cases
bash script/tests/notify-update.sh # the update-notice hook's cases
bash script/tests/session-start.sh # the where-you-left-off hook's cases
bash script/tests/review-unwrap.sh # the answer shapes `flow review` has to unwrap
bash script/tests/bench-compare.sh # the reader that compares two runs of the review benchCI runs the same seven on every PR. The preflight refuses what has shipped broken before: an empty tracked file, unparsable JSON or TOML, a manifest version out of step with CHANGELOG.md, a hook without its executable bit, a stale or unusable mirror. → RELEASING
What it does not ship (on purpose)
No agents and no review skill — those are stack-specific; you name yours in the effective FLOW
configuration, normally the active harness overlay. One worked set ships as an example and is
never loaded: examples/symfony/ is a filled-in FLOW.md plus
four reviewers for a Symfony + Doctrine repo, to copy and edit. Three generic hooks ship: a guard
against pushing to master/main, an update notice at session start, and a session-start line
saying which work this branch belongs to and where it stands — after a compaction, that last one
prints the brief and plan the build is held to instead, since there the context is what was lost,
not the thread. Optional dependencies (a knowledge
source such as domain-memory or codegraph, your git host CLI, a tracker CLI) improve specific
steps; without them those steps degrade and the rest works.
License
MIT.
