claude-project-flow

releasev3.0.2

A Claude Code plugin that carries a project from a rough idea to shipped code through six approval-gated phases

0stars
0forks
0watchers
0open issues
owner: voyvodkastatus: CORElanguage: Unknownbranch: mainlicense: MIT Licenseupdated: last push:
agent-skillsai-toolsclaude-codeclaude-code-plugindeveloper-toolsdocumentationproject-managementproject-planningscaffolding

README Snapshot

claude-project-flow

A Claude Code plugin that carries a project from "I have a rough idea" to working code through six approval-gated phases — and refuses to write a line of application code until the first five are done.

The problem it solves is the pair of failure modes an AI assistant falls into on a new project: it starts building on a guess, or it asks questions forever. This fixes both with a bounded checklist, evidence from real research instead of recall, and a set of documents that hold the memory so the conversation does not have to.

Install

/plugin marketplace add voyvodka/claude-plugins
/plugin install project-flow@voyvodka

The plugin is listed in a small catalog marketplace rather than being one itself, so a single registration covers every plugin from the same author and /plugin marketplace update voyvodka refreshes all of them at once.

The owner/repo shorthand clones over SSH. Without an SSH key on the machine, use the HTTPS URL instead — it needs no credentials for a public repository:

/plugin marketplace add https://github.com/voyvodka/claude-plugins.git

Then, in any project folder:

/project                       # start, or resume wherever the folder left off
/project a tool that does X    # start with a rough idea

Always the same command. It reads docs/product/00-state.md to work out whether this is a new project, a resumption, or a request to advance — an empty folder, a half-finished plan, and an existing codebase all route correctly.

The six phases

Phase Does Writes code
0 · Detect Classifies the folder, reports where things stand No
1 · Discover Bounded question rounds against a fixed checklist No
2 · Research Subagent fan-out: market, tech, dev environment No
3 · Decide Findings become owned decisions and an MVP scope No
4 · Scaffold CLAUDE.md, AGENTS.md, right-sized AI tooling No
5 · Build Implements the roadmap in approved increments Yes

Every boundary is a gate the user opens. A phase can be skipped when it does not apply — but never silently: it says what it is skipping, why, and writes that into the state file.

What it leaves behind

<project>/
├── CLAUDE.md                 main context source
├── AGENTS.md                 pointer for non-Claude tools
├── docs/
│   ├── product/              00-state · 01-brief · 02-decisions · 03-mvp · 04-roadmap
│   └── research/             market · tech · devenv
└── .claude/
    ├── agents/               project-specific subagents — few, or none
    └── skills/               only for genuinely repeated work

All of it is meant to be committed. Someone who clones the repo — using Claude Code, opencode, or anything else — reads CLAUDE.md and docs/product/00-state.md and continues from the same line of thought. That handover is the point of the whole thing.

The ideas it is built on

  • No application code before Phase 5 is approved. If you ask for code earlier, it names what is still unknown and offers to fast-track the remaining phases rather than silently starting.
  • Documents are the memory, the conversation is not. Anything confirmed is written down before moving on, as if the chat will be lost mid-sentence.
  • Ask, but bounded. A fixed checklist with a round limit. Remaining unknowns become marked assumptions, raised again at the moment code depends on one — never more rounds of questions.
  • Research runs in subagents. Each branch digs deep in its own context, writes straight to its own file, and returns ten lines. That is what keeps one long chat viable.
  • Right-size everything. A weekend script gets a weekend-sized plan, two doc files and zero custom subagents. Preventing over-engineering is the reason this exists.
  • Never invent a fact. Market numbers, competitor names, library versions and pricing come from research with a source, or they are written down as assumptions. Never from memory presented as fact.
  • Decisions are updated in place. Git holds the history; the file always reads as current truth. A reversal is a sweep through everything that encoded the old choice, not a paragraph added below it.

The developer profile

plugins/project-flow/skills/project-flow/profile/ is the part you are meant to edit. It records what you already know and reach for by default, one file per stack, so a project reads only what it touches.

With it filled in, Phase 2 stops asking "which stack?" and starts asking "is there a reason to deviate from the default here?" — faster, and a better question, because it forces a candidate to beat the default on something the project actually needs.

The files in this repository are one developer's answers, kept as a worked example rather than as advice. Replace them. A profile describing someone else is worse than an empty one, because it will be trusted.

Keeping your real profile out of git

profile/local/ is gitignored, and any file placed there is read instead of the file with the same name one directory up:

profile/infrastructure.md          committed — the template
profile/local/infrastructure.md    ignored     — the real one, read in preference

That is where hostnames, machine limits, git identity and repository paths belong. Two files ship as templates for exactly this reason — infrastructure.md and local-environment.md — and until one is filled in or overridden, the plugin treats its subject as genuinely open and asks rather than assuming.

This requires running the plugin from a copy you own. A marketplace install is copied into a versioned plugin cache, and that breaks the override in both directions: the clone it was built from never contained local/, and a local/ you create inside the cache is deleted by the next update. Nothing errors when it fails — the templates are read instead, and the tool proceeds trusting answers that describe a different developer, which is exactly the outcome the profile warns about.

Two ways to have a real profile:

# clone it, and point a skills directory at the plugin — discovered in place, no cache copy
git clone https://github.com/voyvodka/claude-project-flow.git
ln -s "$PWD/claude-project-flow/plugins/project-flow" ~/.claude/skills/project-flow

or install from the marketplace and edit the committed profile/ files directly, accepting that an update overwrites them. If you do neither, treat every default in profile/ as someone else's and expect Phase 1 to confirm each one with you.

It reviews itself

At every phase gate the tool asks whether anything went wrong because of how it is written, separates structural failures from circumstantial ones, and logs them. The bar for acting is evidence from a real project, not taste, and the preferred fix is to remove the cause rather than add a reminder. It proposes changes; it never applies them to itself without approval.

plugins/project-flow/skills/project-flow/feedback/observations.md is that ledger, and plugins/project-flow/README.md records why each version changed — reasoning, not a changelog. Both include the findings that were rejected, and one that shipped and had to be reverted, because the reason a plausible rule was wrong is the only thing that stops it coming back.

Language

Conversation and everything under docs/ follow the user's language. CLAUDE.md, AGENTS.md, .claude/**, all code and all commit messages are always English.

Repository layout

plugins/project-flow/              the plugin — see its own README for detail

Licence

MIT — see LICENSE.

Changelog

Changelog

All notable changes to the project plugin are documented here. The format follows Keep a Changelog, and this project adheres to Semantic Versioning.

The Status section of the plugin README carries the reasoning behind each change — why the tool needed it. This file carries what changed. Releases before 2.7.0 are summarised from that section and from git history.

[Unreleased]

[3.0.2] - 2026-09-08

Fixed

  • The research phase told the subagent to use Context7 and gave it no way to proceed without it. phase-2-research.md said "use Context7 (resolve-library-id, then query-docs) … Do not answer from memory", but this plugin declares no dependency on Context7 and nothing installs it. On a machine without it the branch had an instruction it could not follow and no stated alternative, against a rule that forbids answering from memory — so the only exit was the one the rule forbids. profile/code-style.md already said "Context7 or the registry", so the two files disagreed about whether the tool was required. The rule now leads with what is actually non-negotiable (never answer from memory), prefers a docs tool where the session has one, and names the registry commands to fall back to. The sibling web-launcher skill reached the same shape from the same problem.
  • self-improvement.md sent the observation log into a directory the next update deletes. "Where the edit has to land" tells the reader to stop when ${CLAUDE_PLUGIN_ROOT} is inside a plugins/cache/ path, but the "Logging" section below it said, without qualification, to append to feedback/observations.md — a file in that same cache. A reader arriving straight at Logging appended an observation that a marketplace update then wiped, silently, having counted it as recorded. The constraint is now restated where the writing actually happens.
  • Two release blocks in this changelog held the same fixes twice. 3.0.1 and 2.8.0 each carried two ### Fixed headings, because separate pull requests each appended to [Unreleased] and the release stamped both without merging them. 3.0.1's second block restated the first in different words; 2.8.0's split thirteen genuine entries across two lists with a ### Changed between them. Merged, with every unique entry kept.

Added

  • CI checks the changelog's structure: no section heading twice inside one version block, only Keep a Changelog section names, an [Unreleased] section that the next change can land in, and one dated heading per version. The duplication above was found by reading the file weeks later, and it is mechanically detectable — so it is checked rather than trusted, which is the standard this plugin applies to every project it touches.

[3.0.1] - 2026-08-28

Fixed

  • phase-3-decide.md told the reader the decision record has four fields, while a paragraph further down — untouched by that edit — describes Kabul edilen bedel / accepted cost as mandatory, down to what to write when there is none. An agent following the explicit "four fields are what is fixed" instruction would drop it. The reference now describes all five, in both the Turkish block and the English label mapping, and says to write "—" when a decision genuinely costs nothing rather than dropping the line.
  • The plugin README's Status section went stale twice in one day: backfilled at 2.7.0, then three more releases shipped past it. The cause was keeping the same history in two files, so the cause is gone — CHANGELOG.md is the record from 2.7.0 onward and Status is explicitly frozen pre-2.7.0 history. This plugin tells every project it touches to write once and link; it now does.
  • The CI routing check aborted opaquely on the condition it exists to report: grep exits 1 when it matches nothing, and under set -eo pipefail that killed the step before the ::error:: annotation was printed. It now annotates and fails deliberately.

Changed

  • The README's Status section is frozen as pre-2.7.0 history. It duplicated the changelog and went stale twice in one day, which is the failure this plugin warns about everywhere else. The authoritative record from 2.7.0 onward is CHANGELOG.md; the older entries stay because their reasoning predates the changelog and is still worth reading.

[3.0.0] - 2026-08-28

Changed

  • The plugin is renamed from project to project-flow. BREAKING for the install key: it is now /plugin install project-flow@voyvodka, and enabledPlugins entries move accordingly. The catalog carries a renames entry so Claude Code v2.1.193+ rewrites existing settings automatically and reports the change; because the source is remote, expect one plugin-cache-miss and a single /plugin install to pick it up under the new name.

    project was a bare dictionary word standing in for a plugin about phased project delivery. It collides easily — cyberswat/claude-plugin-projects already occupies the same space on GitHub — and a generic install key is the one identifier a user cannot disambiguate at install time. The skill one directory down has been called project-flow since the first release; the plugin now matches it.

    The repository name (claude-project-flow) is unchanged, and the /project command is unchanged — it still starts, resumes and advances a project exactly as before. What moved is the install key and the skill's namespaced id, which is now project-flow:project-flow.

  • plugins/project/ is now plugins/project-flow/, so the plugin directory matches the plugin name.

Fixed

  • The .gitignore rule protecting profile/local/ was pinned to plugins/project/... and stopped matching the moment that directory was renamed. An ignore rule a rename can silently switch off is not an ignore rule; it is now **/profile/local/. CI also asserts that nothing under profile/local/ is tracked, so the protection is checked rather than assumed.

[2.8.0] - 2026-08-28

Fixed

  • The research phase could carry private infrastructure detail into a committed file. The Tech branch is told to paste profile/infrastructure.md into the subagent prompt. On any real machine that resolves to profile/local/infrastructure.md, which is gitignored precisely because it holds hostnames, provider and account names, port lists, domain portfolios and backup schedules. That branch writes into docs/research/tech.md — a file this tool tells the user to commit, in a different repository from the one the profile describes. Nothing said "conclusions, not transcription", so it depended entirely on the subagent's judgement. It is now an explicit rule, modelled on the wording the committed infrastructure.md already applies to itself.

  • Phase 2 could not tell an interrupted branch from a finished one. Branches write straight to their final file, so a session that dies mid-fan-out leaves a file Phase 0 reads as complete. Launched branches are now recorded in 00-state.md at dispatch and marked done as each returns — the rule Phase 5 already applies to increments.

  • SKILL.md stated an absolute that self-improvement.md contradicts. "This tool never edits itself without the user's approval" sat next to two documented repair exceptions. The exceptions are now named where the promise is made.

  • "No application code before Phase 5" vs the Phase 3 spike. Phase 3 explicitly writes and runs throwaway code. The directive now says "no code that ships" and names the spike as the one bounded exception, so the reader is not choosing which of two rules to break.

  • "Two documents instead of five" was never defined. Phase 1 offers the compact shape; Phases 3-5 then name 02-decisions.md and 04-roadmap.md directly, leaving a model that took the offer with two conflicting instructions. The compact layout is now a table naming exactly which file absorbs which, recorded in 00-state.md.

  • Nothing asked before writing over an existing CLAUDE.md, AGENTS.md or docs/ tree. Phase 4 now stops, says what the existing file covers and where it disagrees, and offers merge / replace / write-alongside.

  • The Aktif faz field enumerated phases 0-5 while Phase 5's closing step writes "MVP complete" into it, and nothing distinguished a phase that is running from one that finished. It now carries a parenthesised status.

  • phase-0-detect.md's "Reconstructing state" section did not say it runs after approval rather than before; the heading now does.

  • Phase 1's "round limit" was not a limit. SKILL.md promises questioning is bounded and that leftover unknowns become marked assumptions, but phase-1-discover.md only said to announce a fourth round — with no ceiling and no conversion rule, so a user whose answers keep opening new ground could be questioned indefinitely, which is the exact failure the directive exists to prevent. Four rounds is now a hard ceiling; what is still open converts to marked assumptions and Phase 2 researches it.

  • The decision-record format hardcoded Turkish field labels. phase-3-decide.md showed Karar / Neden / Elenenler / Bağlı olduğu varsayım as the literal block to fill in, while SKILL.md says product documents follow the user's own language — so an English-language project got Turkish headings inside otherwise English documents. The four fields are what is fixed; the labels follow the document.

  • code-style.md told the agent to append to a gotchas.md that nothing creates. No phase scaffolds it and no template defines it, so the rule fired mid-implementation against a file that did not exist. It now says to create it on first use, with the three-layer structure already described a few lines below — deliberately not scaffolded up front, so a project that never hits a warning does not carry an empty ledger.

  • Two avoid.md exclusions (Sentry, API versioning) carried no argument, while the file's own rule is that a candidate "has to beat the stated reason". With nothing stated there was nothing to beat. Both are now marked as unargued weak priors to be raised in Phase 1 rather than treated as settled.

  • The rejected entry in feedback/observations.md was missing two fields its own logging template requires.

[2.7.0] - 2026-08-28

Fixed

  • The self-improvement loop could write into a directory that gets deleted. references/self-improvement.md walks through proposing a change and then applying it to SKILL.md or a phase reference, and allows two classes of repair without asking — but never said where the edit lands. On a marketplace install that is a versioned plugin cache, wiped on the next update, silently, after the user approved the change and watched it be written. profile/README.md already documented this failure for profile/local/; it now covers the whole skill, with a check against ${CLAUDE_PLUGIN_ROOT} before anything is applied.
  • Phase 5 wrote a file no layout tree listed. A project README.md is written at MVP close from one of the two README templates, but neither SKILL.md's target layout nor the plugin README's "What it produces" named it — while phase-0-detect.md treats a root README.md as a pre-existing signal. Both trees now list it and say when it appears.
  • The Status section had stopped at 2.4.0 while plugin.json was at 2.6.0, so the reasoning for two releases existed only in commit bodies. Backfilled.
  • profile/code-style.md stated "Documentation is Turkish" as an unconditional rule for every project, contradicting profile/README.md (everything under profile/ is a default confirmed in Phase 1) and SKILL.md (docume

Releases

  • v3.0.2

    Fixed

    • The research phase told the subagent to use Context7 and gave it no way to proceed without it. phase-2-research.md said "use Context7 (resolve-library-id, then query-docs) … Do not answer from memory", but this plugin declares no dependency on Context7 and nothing installs it. On a machine without it the branch had an instruction it could not follow and no stated alternative, against a rule that forbids answering from memory — so the only exit was the one the rule forbids. profile/code-style.md already said "Context7 or the registry", so the two files disagreed about whether the tool was required. The rule now leads with what is actually non-negotiable (never answer from memory), prefers a docs tool where the session has one, and names the registry commands to fall back to.
    • self-improvement.md sent the observation log into a directory the next update deletes. "Where the edit has to land" tells the reader to stop when ${CLAUDE_PLUGIN_ROOT} is inside a plugins/cache/ path, but the "Logging" section below it said, without qualification, to append to feedback/observations.md — a file in that same cache. A reader arriving straight at Logging appended an observation that a marketplace update then wiped, silently, having counted it as recorded. The constraint is now restated where the writing happens.
    • Two release blocks in the changelog held the same fixes twice. 3.0.1 and 2.8.0 each carried two ### Fixed headings, because separate pull requests each appended to [Unreleased] and the release stamped both without merging them. Merged, with every unique entry kept.

    Added

    • CI checks the changelog's structure: no section heading twice inside one version block, only Keep a Changelog section names, an [Unreleased] section that the next change can land in, and one dated heading per version.

    Full changelog: https://github.com/voyvodka/claude-project-flow/blob/main/CHANGELOG.md

    Open on GitHub
  • v3.0.1

    Follow-ups from a full re-audit. All three are defects introduced or left standing by 3.0.0's own changes.

    Fixed

    • phase-3-decide.md said the decision record has four fields while a paragraph further down describes Kabul edilen bedel / accepted cost as mandatory, down to what to write when there is none. An agent following the explicit instruction drops the field the same file calls required — and it is the one that stops the next reader reopening a settled decision. The template now carries all five.
    • The plugin README's Status section went stale twice in one day — backfilled at 2.7.0, then three releases shipped past it. Resetting it a third time would be the weakest possible fix, so the cause is gone: CHANGELOG.md is the record from 2.7.0 onward, and Status is explicitly frozen as pre-2.7.0 reasoning.
    • The CI routing check aborted opaquely on the condition it exists to report. grep exits 1 when it matches nothing, and under set -eo pipefail that killed the step before the annotation printed. It always failed safe, but a gate that cannot say what it caught costs the next person the time it was meant to save.
    Open on GitHub
  • v3.0.0

    ⚠️ Breaking: the install key changed

    The plugin is renamed from project to project-flow:

    /plugin install project-flow@voyvodka
    

    The catalog carries a renames entry, so Claude Code v2.1.193+ rewrites enabledPlugins and pluginConfigs in your user, project and local settings automatically and tells you it did. Because the source is remote, expect one plugin-cache-miss and a single /plugin install to pick it up under the new name. On older Claude Code the old name reports plugin-not-found — install the new one.

    Unchanged: the repository name, and the /project command. It still starts, resumes and advances a project exactly as before. What moved is the install key and the skill's namespaced id (project-flow:project-flow).

    Why

    project is a bare dictionary word standing in for a plugin about phased project delivery, and the plugin name is the install key — the one identifier you cannot disambiguate at install time. cyberswat/claude-plugin-projects already occupies the same space. The skill one directory down has been called project-flow since the first release; the plugin now matches it, and plugins/project/ became plugins/project-flow/ so the directory does too.

    Fixed

    • The .gitignore rule protecting profile/local/ was pinned to a literal path and stopped matching the moment the plugin directory was renamed — no error, no warning. It is now **/profile/local/, and CI asserts that nothing under profile/local/ is tracked, so the protection is checked rather than assumed. If you run this plugin from a clone with your own profile/local/, this is the release that makes that safe against future moves.
    Open on GitHub
  • v2.8.0

    A privacy fix worth upgrading for, plus four contract mismatches.

    Fixed — a gitignored file was feeding something that gets committed

    phase-2-research.md tells the Tech branch to paste profile/infrastructure.md into the subagent prompt. On any real machine that resolves to profile/local/infrastructure.md — gitignored precisely because it holds hostnames, provider and account names, port lists, domain portfolios and backup schedules. That branch writes into docs/research/tech.md, a file this tool tells you to commit, in a different repository from the one the profile describes. Nothing distinguished using that content for judgement from transcribing it. Now an explicit rule, worded after the constraint the committed infrastructure.md already places on itself.

    Fixed — an interrupted research branch looked finished

    Branches write straight to their final file, so a session that died mid-fan-out left a file Phase 0 read as complete. Launched branches are now recorded in 00-state.md at dispatch and marked done as each returns.

    Fixed — the tool contradicting its own promises

    • SKILL.md said "never edits itself without the user's approval" while self-improvement.md documents two repair exceptions. The exceptions are now named where the promise is made.
    • "No application code before Phase 5" vs Phase 3's timeboxed throwaway spike. Now "no code that ships", with the spike named as the one exception.
    • "Two documents instead of five" was offered without saying which two, while Phases 3-5 name files the compact shape does not have. There is now a table.

    Fixed — Phase 4 overwrote existing context files silently

    No merge, diff or approval step existed for a pre-existing CLAUDE.md, AGENTS.md or docs/ tree. It now stops, says what is there and where it disagrees, and offers merge / replace / write-alongside.

    Also

    The Aktif faz field enumerated phases 0-5 while Phase 5 writes "MVP complete" into it, and nothing marked a phase as running or interrupted. It now carries a parenthesised status.

    Open on GitHub
  • v2.7.0

    Content fixes found by a full re-audit on 2026-08-28, plus the repository's first CI gate. First tagged release — earlier versions are summarised in CHANGELOG.md.

    Fixed

    • The self-improvement loop could write into a directory that gets deleted. references/self-improvement.md walks through proposing a change and then applying it to SKILL.md or a phase reference, and allows two classes of repair without asking — but never said where the edit lands. On a marketplace install that is a versioned plugin cache, wiped on the next update, silently, after you approved the change and watched it be written. There is now a check against ${CLAUDE_PLUGIN_ROOT} before anything is applied.
    • Phase 5 wrote a file no layout tree listed. A project README.md is written at MVP close, but neither SKILL.md's target layout nor the plugin README's "What it produces" named it — while Phase 0 treats a root README.md as a pre-existing signal.
    • The README's Status section had stopped at 2.4.0 while the manifest was at 2.6.0. Backfilled.
    • profile/code-style.md stated "Documentation is Turkish" as an unconditional rule for every project, against the profile's own default-not-a-rule framing and against SKILL.md. Reworded. The English-for-code half is unchanged and still absolute.

    Removed

    • A stray version: 0.1.0 from the SKILL.md front matter, which Claude Code does not read and which contradicted the manifest.

    Added

    • CI that validates the manifest and asserts the phase routing, references and templates all resolve in both directions. This skill's failure mode is routing: a renamed reference breaks a phase at the moment that phase is needed, halfway through someone's project.
    • Dependabot, CHANGELOG.md, and $schema in the manifest.
    Open on GitHub