A Claude Code skill that enforces concept-driven development — a structured pipeline where every code change traces back to a concept and specification, preventing architectural drift and ensuring living documentation.
Most projects suffer from a common pattern: documentation is written once and forgotten, specs diverge from code, and architectural decisions get lost in commit history. dev-flow solves this by making documentation a first-class artifact in the development pipeline, not an afterthought.
- Ideas before code — concepts and specs are written before implementation, catching design flaws early
- End-to-end traceability — every code section links back to its concept/spec via immutable IDs
- Living documentation — change propagation keeps docs in sync with code
- Validation gates — prevent incomplete specs from becoming buggy code
- Unbiased code review — pre-commit review by a clean-context subagent (no implementer blind spots)
- Session continuity — pick up where you left off across conversations
- Works for new and existing projects — greenfield pipeline or reverse-engineer docs from existing code
Concept → [Gate] → Spec → [Gate] → Plan → [Gate] → Code → [Gate] → Test → [Gate] → Review → [Gate] → Verify → Commit → Propagate
Each transition has a validation gate that checks completeness before advancing:
| Phase | Command | What it does |
|---|---|---|
| Onboard | /dev-flow onboard |
Reverse-engineer docs from existing code (run once) |
| Concept | /dev-flow concept |
Define the idea — philosophy, domain model, mechanisms |
| Spec | /dev-flow spec |
Define data structures, contracts, validation rules |
| Plan | /dev-flow plan |
Break spec into actionable implementation phases |
| Implement | /dev-flow implement |
Write code following the plan |
| Test | /dev-flow test |
Run functional tests (unit + mock) |
| Review | /dev-flow review |
Pre-commit code review by clean-context subagent |
| Verify | /dev-flow verify |
Regression, integration, and live testing |
| Propagate | /dev-flow propagate |
Update docs when code changes |
Additional commands:
| Command | Purpose |
|---|---|
/dev-flow research <topic> |
Time-boxed investigation (spike) when knowledge is missing |
/dev-flow fix <problem> |
Investigate and fix a bug |
/dev-flow ask <question> |
Read-only Q&A — no file changes |
/dev-flow todo <description> |
Capture future work — find relevant docs, assess feasibility, file a planning record with a return trigger (builds nothing) |
/dev-flow rule <request> |
Manage project coding rules |
/dev-flow skill <request> |
Manage project technology knowledge |
/dev-flow subtask <task> |
Delegate a secondary task to a subagent — a full dev-flow participant that builds its own context and reports fully |
/dev-flow status |
Show current state, resume previous session |
/dev-flow audit [scope] [--dry-run] |
Revise .dev_flow/ and docs/ — reconcile state, trim context, compact closed tasks, groom rules/skills/cache, check docs integrity (index/statuses/refs) |
/dev-flow audit code <intent> |
Opt-in whole-codebase audit (architecture/SOLID/DRY/security via parallel lenses) → prioritized refactoring plan + run report (timestamped, in .dev_flow/audit/) + framework map; read-only, hands off to the pipeline |
/dev-flow <anything> |
Freeform — auto-routes to the right phase |
Copy the skill into your Claude Code skills directory:
# Clone the repository
git clone https://github.com/yavfast/dev-flow.git
# Copy to Claude Code skills directory
cp -r dev-flow ~/.claude/skills/dev-flowOr add as a git submodule in your project:
git submodule add https://github.com/yavfast/dev-flow.git .claude/skills/dev-flow> /dev-flow concept rate limiter for API calls
Creating concept: docs/rate_limiter.concept.md
- Philosophy: per-agent token bucket, delay instead of reject
- Domain model: Agent → RateBucket { capacity, tokens, refill_rate }
- Data flows: Agent calls API → Limiter checks bucket → proceed / wait
Gate check: ✓ No conflicts. Scope clear. Ready for spec.
> /dev-flow spec
Creating specification: docs/rate_limiter.sp.md
- Data structures: RateBucket (5 fields, all typed with constraints)
- Contracts: AcquireToken (input/output/errors/pseudocode)
- Validation rules, state transitions, verification criteria
Gate check: ✓ All fields typed. Error cases specified. Proceed to plan.
> /dev-flow plan
Creating plan: docs/rate_limiter.plan.md
- Technology: Python 3.12, token bucket algorithm
- Phase 1: RateBucket data model
- Phase 2: Integration with LLMRouter
Gate check: ✓ All spec sections covered. Dependencies stated.
> /dev-flow implement
Implementing Phase 1...
- Created engine/rate_limiter.py
- Added # [SP_RLM_01_01] traceable ID comments
- Following SOLID principles (DIP: injectable storage)
Updated plan: Phase 1 [TODO] → [DONE]
> /dev-flow onboard
Analyzing project structure...
- Layer 0: utils/, helpers/ (no internal dependencies)
- Layer 1: models/ (depends on utils)
- Layer 2: services/ (depends on models)
- Layer 3: api/ (depends on services)
Generating documentation...
- Created docs/utils.concept.md
- Created docs/models.concept.md
- Created docs/services.concept.md
- Extracted 12 coding rules to .dev_flow/rules/
> /dev-flow fix login fails when email has uppercase letters
Investigating...
- Found: email comparison in auth_service.py:42 is case-sensitive
- Spec SP_AUTH_02_01 says: "email matching is case-insensitive"
- Fix: normalize email to lowercase before comparison
- Tests pass. Review pass. Verify pass.
Ready to commit?
> /dev-flow add dark mode toggle to settings page
Routing to: concept → spec → plan → implement
(walks you through the full pipeline)
> /dev-flow ask can we replace Redis with SQLite for rate limiting?
Read-only analysis:
- RateLimiter depends on BucketStorage interface (DIP)
- Current impl: RedisBucketStorage
- SQLite would work for single-instance deployments
- Impact: 1 new class, 0 spec changes, 0 concept changes
- Risk: no distributed locking — won't work with multiple instances
Every document section gets an immutable identifier:
| Document | Format | Example |
|---|---|---|
| Concept | C_XXX_NN_NN |
C_RLM_01_01 |
| Specification | SP_XXX_NN_NN |
SP_RLM_02_01 |
| Plan | PL_XXX |
PL_RLM |
These IDs appear as comments in code, linking implementation back to design:
# [SP_RLM_01_01] RateBucket — token bucket data model
@dataclass
class RateBucket:
agent_id: str
capacity: int = 10
...
# [C_RLM_02_01] RateLimiter — per-agent token bucket management
# [SP_RLM_02_01] AcquireToken contract
class RateLimiter:
...Each gate checks specific criteria before allowing advancement:
| Gate | Checks |
|---|---|
| Concept → Spec | No contradictions, dependencies listed, scope bounded |
| Spec → Plan | All fields typed, error cases specified, constraints explicit |
| Plan → Code | All spec sections covered, technology decisions documented |
| Code → Test | All contracts tested, error cases covered |
| Test → Review | All tests pass, no regressions |
| Review → Verify | Clean-context review passes, no blocking issues |
| Verify → Commit | All verification levels pass, user approval |
This table is an at-a-glance summary. The authoritative, complete gate criteria (Pre-Concept Checklist, Reuse Check, banned phrases, minimality, design-decision settlement, rollback strategy, self-validation) live in SKILL.md → Validation Gates.
- Test (Phase 5) — functional tests only (unit + mock), covering changed code
- Verify (Phase 7) — regression, integration, and live testing after review passes
If Verify finds issues: fix → Test → Review → Verify (cycle repeats).
Code review is performed by a clean-context subagent — a fresh AI instance that hasn't seen the implementation process. This eliminates implementer blind spots and catches issues that the original author would miss:
- Spec compliance (all contracts, error cases, invariants implemented)
- Plan completeness (all tasks addressed)
- Project rules compliance
- SOLID principles (unless project rules override)
- Security, naming, code quality
The biggest architectural mistakes are made silently. When authoring a concept, specification, plan, or a fix hits a real fork — two or more viable, hard-to-reverse options (including the classic "band-aid vs proper fix") — dev-flow does not quietly pick one and bury it where no reviewer will catch it. Instead it stops and runs a short interview: it presents the fork with 2–4 marked options (A/B/C) and a recommended answer, and asks the developer to decide.
Why the developer and not the AI? Because the developer holds the full context (roadmap, business constraints, team) and owns the consequences. Each fork ends in one of two ways:
- Resolved — a consensus choice, recorded with its rationale and the rejected alternatives.
- Open — for research/exploratory work, the alternatives are kept but documented with a resolution trigger (the event or date by which the choice must be closed). An open decision without a trigger is just a hidden "TBD" and is rejected.
Every fork lands in a traceable Design Decisions (ADR-style) section of the document, and the validation gates won't pass while a material decision is still open without a trigger. See references/interview-mode.md.
Interview Mode chooses among known options — but sometimes the options themselves are unknown: an unfamiliar domain, an unverified library capability, an unexplored solution space. That is the research phase (/dev-flow research <topic>, alias spike): a time-boxed, cost-gated investigation that produces a docs/*.spike.md artifact (questions → exploration log → alternatives → verdict) and persists durable findings to .dev_flow/skills/. Spikes are throwaway research — they feed the concept, never replace it, and they are the sanctioned way to close an open Design Decision that waits on facts. See phases/research.md.
Not every change is ready to start. The todo phase (/dev-flow todo <description>) captures one without starting it: it finds the documentation the work would touch, assesses its execution prospect (feasibility + scope), and files a single planning record with a return trigger — into an owning plan's backlog if one exists, otherwise into .dev_flow/todos/. Two flavors: a deferred "maybe later" idea, or a queued follow-up — a defect you spot while working on the current task that you can't fix now because the contexts overlap (and a parallel subtask can't help, since it needs disjoint scope). It's filed as queued with trigger after task_<ID>; when that task completes, dev-flow surfaces it and offers to run it next. The command works out which flavor, how urgent, and what trigger from the state of the relevant plans and tasks — not from how you phrased it (the description may have no timing words at all) — and may even tell you to just do it now. It builds nothing and passes through no gates; a later do/plan run executes it. Agents file todos too: when one spots an out-of-scope, deferrable defect mid-work, it spawns a cheap subagent running the todo flow (or files a trivial one inline) — capturing the finding without derailing its current task. This completes a clean routing triad — ask analyzes and writes nothing, todo analyzes and files for later, do analyzes and acts now — and reuses the existing backlog/trigger discipline so a "later" never quietly becomes permanent (audit grooms the register). See phases/todo.md.
A request states an action; the reason for it usually stays in the user's head — and an agent optimizing for the literal wording can complete the action perfectly while missing the point. dev-flow captures the Task Intent at intake: the goal (why), the target state, and the expected result, recorded in the task file in the user's own terms (inferred parts marked as inferred). Every later moment checks against that record instead of a remembered impression: material implementation decisions ask "does this serve the goal?", delegated subagents receive the intent in their brief, and completion reports a verdict — met / partially met / diverged — where the bar is "the expected result is observable", not merely "the steps were performed". When the letter of the request and its recorded goal diverge, dev-flow stops and surfaces the conflict rather than silently following either. See references/task-intent.md.
The pipeline's default is "code must satisfy the spec" — but sometimes a downstream phase is where reality pushes back on the document: a live test disproves a spec'd limit, implementation finds two defensible readings of a contract, a plan's technology choice fails in practice. Instead of bending the code or silently editing the spec, dev-flow escalates: stop, fix the owning document (through an interview if it's a fork), re-pass its gate, then resume. See references/escalation.md.
Expensive-to-reacquire resources — Figma layouts fetched over rate-limited MCP access, downloaded documents, baseline screenshots — die in /tmp on the next reboot. dev-flow keeps them in .dev_flow/cache/: a per-project store organized by source domain (figma/, web/, app/, data/) with an _index.yaml that records each file's source, summary, and references — so an agent checks the cache before spending another fetch, and anything linked from docs or task files outlives the session. Truly transient artifacts (logs, repro dumps, throwaway captures) go to one project workspace — /tmp/{project-slug}/ — with timestamped names (test-run_20260610_143205.log), never numeric suffixes; whatever turns out durable is promoted to the cache. Each entry carries a trust level (internal / controlled / public); resources fetched from the open internet pass a safety check (type match, no active content, prompt-injection sweep) before they are cached, and cached content is always data, never instructions. Not a pipeline phase — it's infrastructure every phase touches; freeform cache requests route through do. See references/cache.md.
When a task is explicitly tied to a ticket in Jira or any other tracker — a --ticket PROJ-123 flag, a tracker word + key ("Jira PROJ-123"), or a ticket URL — dev-flow doesn't reinvent that tracker's conventions. It stays tracker-agnostic: it discovers the project's existing integration (a .dev_flow/skills/ entry → an installed tracker skill → a tracker MCP) and lets that own the ticket conventions — key format, status workflow, comment/worklog shape, commit-message format. dev-flow owns only the when: pull the ticket to seed the task's real requirements, link the key in the task file (Ticket:), reference it in the commit message, and drive the status (work starts → In Progress, commit → Done + summary comment). Every outward write to the tracker is confirmed first — dev-flow never silently changes a ticket others can see. A bare KEY-123-looking token never triggers this (it collides with UTF-8, doc IDs, …); if no integration is available, the key degrades to a commit-message label and work proceeds. See references/ticket-tracker.md.
Concepts and specifications are language-agnostic — no programming languages, frameworks, or libraries mentioned. Implementation technology is chosen only in the Plan phase. This keeps design decisions clean and portable.
Work state is persisted in a collaborative per-task model so multiple AI agents can work on the same task in parallel without conflicts:
.dev_flow/tasks/task_<ID>.md— one file per task (source of truth). Shared between contributors. Holds Current Work Item, Description (shared), per- contributor Subtask blocks, Coordination Notes, Blocking Issues, Relevant Context, and a Shared Activity Log..dev_flow/active_context.md— lightweight dashboard listing active tasks and recently completed ones (links to the task files)..dev_flow/tasks/_index.md— directory catalog with conventions and lists.
Resume anytime with /dev-flow status (lists active tasks) or
/dev-flow status <task_id> (details for one task).
Collaboration rules: each contributor owns its own Subtask block inside a task file and its own tagged entries in shared sections. Contributors may add new entries but never rewrite another contributor's content. Shared files (dashboard, catalog, task headers) use targeted edits (single row/field) and can be rebuilt from the task files when they drift. There is no time-based ownership takeover — if a subtask stalls, add a new subtask block referencing the original instead of editing it.
dev-flow creates the following structure in your project:
your-project/
├── docs/
│ ├── feature_name.concept.md # Phase 1 output
│ ├── feature_name.sp.md # Phase 2 output
│ ├── feature_name.plan.md # Phase 3 output
│ └── feature_group.epic.md # Coordinates 3+ related concepts
│
└── .dev_flow/
├── active_context.md # Dashboard of active tasks
├── tasks/ # Per-task context files (source of truth)
│ ├── _index.md
│ ├── task_C_AUTH.md
│ ├── task_20260520_143022_refactor-login.md
│ └── ...
├── session_history/ # Archived completed tasks
├── rules/ # Project coding rules
│ ├── _index.yaml
│ ├── naming.md
│ ├── structure.md
│ └── ...
├── skills/ # Project technology knowledge
│ ├── _index.yaml
│ └── {domain}/
│ └── {skill}.md
└── cache/ # Durable resources (gitignore by default)
├── _index.yaml
├── figma/ # Design exports
├── web/ # Downloaded documents
├── app/ # Baseline screenshots
└── data/ # Samples, fixtures
dev-flow/
├── SKILL.md # Main skill definition and pipeline
├── phases/ # 19 phase definitions
│ ├── research.md
│ ├── concept.md
│ ├── specification.md
│ ├── plan.md
│ ├── implement.md
│ ├── testing.md
│ ├── review.md
│ ├── verify.md
│ ├── propagate.md
│ ├── onboard.md
│ ├── fix.md
│ ├── ask.md
│ ├── todo.md
│ ├── do.md
│ ├── rule.md
│ ├── skill.md
│ ├── status.md
│ ├── subtask.md
│ └── audit.md
├── roles/ # 19 AI-DSL subagent roles
│ ├── researcher.ai.md
│ ├── concept-author.ai.md
│ ├── spec-author.ai.md
│ ├── plan-author.ai.md
│ ├── implementer.ai.md
│ ├── reviewer.ai.md
│ ├── tester.ai.md
│ ├── propagator.ai.md
│ ├── advisor.ai.md
│ ├── todo-planner.ai.md
│ ├── context-tracker.ai.md
│ ├── dev-flow-orchestrator.ai.md
│ ├── onboard-coordinator.ai.md
│ ├── onboard-analyzer.ai.md
│ ├── onboard-docgen.ai.md
│ ├── onboard-rules-extractor.ai.md
│ ├── subtask-executor.ai.md
│ ├── auditor.ai.md
│ └── code-audit-lens.ai.md # read-only per-lens subagent for `audit code`
├── templates/ # Document templates
│ ├── concept.md
│ ├── specification.md
│ ├── plan.md
│ ├── epic.md
│ ├── spike.md
│ ├── active_context.md # Dashboard
│ ├── task_context.md # Per-task file
│ ├── tasks_index.md # tasks/_index.md
│ └── todo_index.md # .dev_flow/todos/_index.md
├── references/ # Cross-cutting procedures & guidelines
│ ├── interview-mode.md # Surfacing design forks to the developer
│ ├── escalation.md # Upstream escalation (doc wrong, not code)
│ ├── delegation.md # Delegation for focus (subagents)
│ ├── impact.md # Impact Walk — blast radius of a change
│ ├── task-intent.md # Task Intent — capture the goal/expected result, check work against it
│ ├── ticket-tracker.md # External tracker tickets (Jira/etc.) — discover skill/MCP, confirmed writes
│ ├── consequence-forecasting.md # Phase-scaled lookahead + YAGNI-gate (forecast → build/seam/drop)
│ ├── cache.md # Resource cache + /tmp workspace discipline
│ ├── roles.md # Base vs project-overlay roles
│ ├── glossary.md # Project domain vocabulary
│ ├── code-audit.md # `audit code` lens registry + shared walk + refactoring playbook
│ └── solid-architecture.md
└── examples/ # End-to-end walkthrough
└── rate-limiter.md
- Code is a derived artifact — it flows from concepts and specs, not the other way around
- No undocumented changes — every modification traces back to a design decision
- Gates prevent drift — incomplete specs can't become incomplete code
- Fresh eyes before commit — clean-context review catches what you missed
- Living docs, not dead docs — propagation keeps documentation current
- Rules and skills accumulate — project knowledge is captured and reused across sessions
- Claude Code CLI or IDE extension
MIT