← Back to writing

Codifying the Workflow: flow-toolkit for Spec-Driven Development

aiclaude-codedeveloper-productivitysoftware-architecture

The methodology works. The problem is running it every day without shortcuts.

The first post in this series described a development loop built on three plain markdown files: a specifications backlog, a rules file, and a roadmap. The second post showed how the same structure scales to a team: the spec becomes the design surface, and the rules file becomes a shared constitution that keeps AI output consistent across contributors.

Both posts describe the methodology. This one is about the tooling that enforces it.

After running this workflow across two production apps and a few team projects, I noticed the same failures repeating. Completed specs staying in the active backlog. The rules file growing without bound. New sessions starting without reading the context files I had carefully maintained. Pre-ship steps skipped because there was no gate. AI dropping work quietly when scope got inconvenient.

None of these are methodology failures. They are tooling failures. The discipline was personal, which meant it degraded under pressure.

So I built flow-toolkit. It started as five Claude Code slash commands. It has since become a Claude Code plugin: a set of /flow:* commands, sub-agents that isolated work fans out to, and always-on hooks that check the rules a human forgets. This post covers what it does now and why each piece exists.

From scripts to a plugin

The first version was a git clone and an install script that copied command files into your Claude config. That worked, but it made updates manual and the commands lived as loose files with no version.

flow-toolkit is now a plugin. You install it from a marketplace:

/plugin marketplace add liminalarc/flow-toolkit
/plugin install flow@flow-toolkit

Restart Claude Code and every entry point appears under the flow: namespace. Updates are versioned through /plugin update. The plugin bundles everything: commands, skills, sub-agents, and hooks. A fallback installer still exists for environments where the plugin is not an option, but the plugin is the path.

The entry points

There are eight, all namespaced /flow:*. They map to the phases of the work.

/flow:init bootstraps a project. Run it once with a one-sentence description of what you are building. It generates the spec model, a CLAUDE.md hierarchy (a root file plus one lean file per major layer), and a README with local setup documented. On an existing codebase it reads what is there, skips the walking skeleton, and seeds a real backlog. Add --backend ado to track the backlog on an Azure DevOps board instead of a local file.

/flow:run is the primary command. With no arguments it shows the backlog ordered by priority. With a spec id it reads the spec, proposes a plan, waits for your approval, then builds test-first in small commits. With --add it co-authors a new spec through a short dialogue. With --ideas it brainstorms through three lenses: what is sellable, what is profitable, what is a quick win.

/flow:ship cuts a release. It reads CLAUDE.md to learn how the project deploys, checks that nothing is uncommitted and tests pass, proposes a version bump from the commit history, and waits for confirmation before tagging.

/flow:lint is the health check. It audits the CLAUDE.md hierarchy for bloat and duplication and checks the spec model for invalid statuses, duplicate ids, and specs that are DONE but not archived. Findings come back by severity.

/flow:review runs a multi-lens audit: docs, UX, marketing copy, or product decisions. Each lens has a defined scope and returns a prioritized list.

/flow:pr reviews a pull request or branch diff against the spec that motivated it, across three dimensions: spec fidelity, quality, and tests.

/flow:hunt looks for new work. It researches opportunities through a panel of domain personas and returns scored candidates.

/flow:validate drives the running app and scores it against a rubric: one lens for design-system conformance, one for whether a user can complete the task. The project layer of that rubric lives in the repo, at .flow/validate/ui.md and .flow/validate/ux.md. It is self-maintaining: the validator proposes a draft from your source on the first run and offers a refresh when the design system drifts, writing nothing without your approval. It is the only part of the toolkit that runs the app instead of reading the code.

Three of these (init, lint, ship) are thin: they run inline, do one deliberate thing, and dispatch nothing. The other five are skills. They load their detail only when invoked, and they fan work out to sub-agents.

Sub-agents

A skill does not do all the work in one context. It spawns sub-agents, each with its own clean context and a narrow job.

/flow:run dispatches an implementer per task, then a verifier that checks the implementer’s diff against the task’s acceptance criteria. /flow:review, /flow:pr, and /flow:hunt dispatch one agent per lens, dimension, or research angle and run them in parallel, then synthesize the findings. /flow:validate drives the app one lens at a time.

The split that matters: only the implementer writes code. Every other agent is read-only. The verifier judges a diff and never fixes it. The reviewers and researchers report, and the main thread decides what to apply. This keeps the agent that changes your files separate from the agents that assess the change, so a review cannot quietly rewrite what it was supposed to critique. When implementers run in parallel across layers, each works in an isolated git worktree so they cannot collide.

The hooks: a seatbelt that costs nothing

The commands enforce discipline when you run them. The hooks enforce it always.

Four hooks fire on Claude Code events. A spec guard validates spec files as they are written. A CLAUDE.md guard enforces the line caps. A commit guard checks that a commit message is conventional, that the spec it touches is valid, and that a spec is not being marked DONE with open work. A session brief prints a short backlog orientation when a session starts.

The rules they check live in one place, a single preflight script that both the hooks and the on-demand commands call. A rule cannot drift between the seatbelt and the audit because there is one copy of it. Every hook’s first act is to ask whether it applies. A non-spec file, a non-commit command, or a repo with no spec model exits immediately, so a project that does not use flow-toolkit pays nothing.

The hooks are the answer to the discipline being personal. They run whether or not you remember to.

The spec model

A spec started as one entry in a single backlog file. That worked until specs grew large enough to need their own structure.

The model now has two parts. An index holds the status of every spec: id, title, status, and a link. The index is the single source of truth for where a spec stands, and it is the file the board replaces when you track work in Azure DevOps. Each spec also has a detail file that holds the problem, the value, the scope, the acceptance criteria, and the plan. The detail file carries no status; status lives only in the index.

A detail file stays flat while it is small. When it grows past a few tasks, or a task earns its own acceptance criteria, it becomes a directory: an orchestrator file plus one file per task. The orchestrator owns the status and the deferral tracking. Each task file carries a local “done when” contract, which is the seam an implementer builds to and a verifier checks against.

The lifecycle vocabulary is NOT STARTED, IN PROGRESS, PARTIAL, DONE, and SUPERSEDED. Spec ids are never reused. This is the rule that matters most over a long project. Commits and pull requests that reference a spec id are permanent. Delete a spec and create a new one with the same id and you break every reference to the original. When a spec is DONE it moves to an archive that preserves its id. /flow:lint reports any id that appears twice and flags DONE specs that have not been archived.

Autonomy, and no silent deferrals

By default /flow:run is in checkpoint mode. It proposes a plan and stops. You approve or redirect. Only then does it write code. The gate is in the tool, not in your memory.

A spec can opt into auto-build to skip the plan pause. The safety net is the verifier: under auto-build it blocks, and a failing verdict gets one bounded retry before the task falls back to a human checkpoint. Under checkpoint mode the verifier is advisory. The precedence is explicit: a project can force a mode, a repo can set a default, and a spec can request one.

The other guarantee is about scope. Scope narrows only by your decision. The moment Claude would drop something that was in scope, it stops, explains why, and asks you to build it now or move it to another spec. That choice is recorded as a machine-checked deferral entry, and an open deferral blocks the spec from reaching DONE. Work does not disappear because it got inconvenient. It gets a decision.

Context is a resource

This is the part that does not come up in most methodology discussions, and it is still the reason the whole thing is shaped the way it is.

Every token in the context window is signal or noise. When the methodology is working, signal is high: the rules file describes your conventions accurately, the backlog reflects what is actually in progress, and the AI produces consistent code because it is reading current context.

When the methodology drifts, signal degrades. The rules file hits 400 lines. Completed specs stay in the active backlog. The README describes the setup from six months ago. Claude reads all of it anyway, and stale context hurts output.

The toolkit is built around this. The CLAUDE.md hierarchy enforces size limits and loads layer-specific rules only when you are in that layer. The index keeps status out of the detail files so a session reading one spec does not load the state of every other. The sub-agents give each unit of work a clean context instead of one session that accumulates the residue of everything before it. /flow:lint and the hooks catch the drift before it compounds.

The CLAUDE.md hierarchy deserves its own note. A single rules file works for a small project and breaks down as it grows, because every session loads all of it even when you are touching one layer. The fix is a hierarchy. The root file covers what is universal: architecture, development rules, commit format, testing philosophy. Each layer gets its own file. When Claude works in the server, it loads the root plus the server file. The hierarchy is additive and you never repeat root content in a subdirectory file. The common failure is copying a root section into a subdirectory file for reference and watching the two copies drift apart. /flow:init generates the structure and /flow:lint enforces it.

Getting started

Install the plugin:

/plugin marketplace add liminalarc/flow-toolkit
/plugin install flow@flow-toolkit

Restart Claude Code, navigate to your project, and run /flow:init. Then:

/flow:run          # see the backlog
/flow:run 0.1      # plan and build the first spec (pauses for sign-off)
/flow:ship         # cut the release

That is the loop. The methodology is the hard part. The tooling is the easy part. Once the spec model exists and the plugin is installed, the workflow is a series of prompts and a set of guards that run on their own, rather than a set of habits you have to remember.

The next post in this series covers the business case: why this workflow produces better outcomes at the organizational level, not just the developer level.

Found this useful?

If this post helped you, consider buying me a coffee.

Buy me a coffee

Comments