Vibecode CodeSpring
track this build4 phases, 12 steps, beginner friendly0%The core loop, a mind map that turns feature notes into PRDs and kanban tasks fed to a coding agent, is just structured prompting and file generation, well within reach of a one-shot build. What's missing is the polish: the visual mind-map canvas, MCP/CLI integrations with Claude Code, Cursor and Codex, and the docs search. A DIY version gets you most of the value but with a rougher UI and manual glue between the planning docs and your agent of choice.
You are building a lean indie version of CodeSpring. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # CodeSpring · indie build A local planning tool whose hard problems are keeping the plan in the repository rather than in a database the agent cannot see, stopping a generated draft from being mistaken for an approved specification, and noticing when a plan has gone stale against the code it describes. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Runtime | A local Node and TypeScript application with a small web interface, no accounts | one person planning one repository does not need a server or a login | | Source of truth | Markdown files with frontmatter inside the target git repository | the coding agent reads files, so the plan has to be files, and git already versions them | | Index | SQLite, rebuilt from the files on demand | a cache you can delete is a cache that cannot silently rot | | Generation | One model call per feature, structured output, written to a draft path | a draft that lands on top of an approved spec destroys the only edits that were correct | | Status | Read from git branches and commit messages, not from dragging cards | a board moved by hand starts lying about what is finished within a week | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the planning tool and the export. - Get it: nodejs.org, or your version manager. - Verify: node --version prints v22 or higher - [ ] **Git, with a repository you actually intend to build in** · free - Why: The plan lives in the repository and task status is read from branches and commits, so a scratch folder will not exercise any of it. - Get it: Use an existing project, or create one and make at least one commit. - Verify: git log prints at least one commit in the target directory - [ ] **An API key for a text model that returns structured output** · pay per call; a planning session is small change, and the monthly ceiling in this build is what keeps it that way - Why: Generation is one call per feature and is the only part that leaves your machine or costs money. - Get it: Create a key with the provider you prefer and set a spend limit in their console. - Verify: One feature produces a draft that parses against your schema - [ ] **The coding agent you actually use** · free or whatever you already pay - Why: The whole last phase is about writing files that agent reads, and the only way to know it read them is to ask it to quote one back. - Get it: Whichever agent or editor you already work in. - Verify: After an export, the agent can quote a line from your approved specification - [ ] **Where the plan files live in the repository** · free - Why: This path is the contract between the tool, git and the agent, and changing it later means rewriting every link. - Get it: Write down the directory, the file naming rule and the frontmatter keys before any code. - Verify: docs/file-format.md exists and the indexer reads it as specification ## Quick start ```sh npm run reindex ``` Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Running the coding agent for you. - A hosted board with collaborators. - Semantic search over documentation. - A protocol server exposing the plan. - polished drag-and-drop mind-map canvas - MCP server integration with Cursor/Claude Code/Codex - semantic docs search - hosted kanban sync across devices - prebuilt skills library If one of those is essential to you, that is the reason to keep paying for CodeSpring, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · CodeSpring The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a planning workspace that turns a map of features into specification files your coding agent reads out of the repository to replace CodeSpring. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Runtime: A local Node and TypeScript application with a small web interface, no accounts · one person planning one repository does not need a server or a login - Source of truth: Markdown files with frontmatter inside the target git repository · the coding agent reads files, so the plan has to be files, and git already versions them - Index: SQLite, rebuilt from the files on demand · a cache you can delete is a cache that cannot silently rot - Generation: One model call per feature, structured output, written to a draft path · a draft that lands on top of an approved spec destroys the only edits that were correct - Status: Read from git branches and commit messages, not from dragging cards · a board moved by hand starts lying about what is finished within a week ### Data model (create this before Phase 1) - features(id, slug, title, status, parent_id, map_x, map_y, file_path, created_at, updated_at) · the row is an index entry, the file is the record - edges(from_feature, to_feature, kind) · depends_on or splits_into, drawn on the map and used to order tasks - specs(feature_id, draft_path, approved_path, model_id, prompt_version, generated_at, approved_at, approved_by) - tasks(id, feature_id, title, acceptance, expected_files_json, status, branch, commit_sha, closed_at) - runs(id, feature_id, model_id, input_tokens, output_tokens, cost_minor, at) · every model call, so the month has a number attached to it - staleness(feature_id, checked_at, referenced_paths_json, repo_changed_at) · which approved plans describe code that has since moved - Nothing here is authoritative. Every row points at a file git already tracks, so deleting the database and reindexing loses precisely nothing. ### Phase 1 · The repository is the record Build: Point the tool at a git working tree. Each feature is a markdown file with frontmatter holding a stable id, title, status and map position, under a directory you choose. Index those files into SQLite on start and on change, and provide a reindex command that rebuilds from scratch. Trap: Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. Done when: Deleting the database and reindexing reproduces the same feature list and edges exactly, tested. A feature id survives a title change and a file rename, tested by renaming both. A feature edited in an external editor shows up without restarting the tool. The tool refuses to run against a directory that is not a git working tree and says why. Do not build yet: No map, no generation, no tasks, no agent export yet. ### Phase 2 · A map you can read without the tool Build: A canvas listing features as nodes with drag positioning, keyboard creation and arrow keys for movement, and edges typed as depends_on or splits_into. Write positions and edges back into the frontmatter of the feature files. Support a plain list view that does everything the canvas does. Trap: Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. Done when: Positions and edges survive a round trip through the files with no canvas-specific document anywhere, checked by reading a feature file by hand. A dependency cycle is detected and reported rather than stored silently. Every canvas action has a keyboard equivalent and the list view can create, connect and reorder without the canvas. A merge conflict in one feature file leaves the rest of the map loadable. Do not build yet: No specification generation and no tasks yet. ### Phase 3 · A draft is not a specification Build: One model call per feature turning the notes and the incoming edges into a structured draft: problem, scope, explicitly out of scope, acceptance criteria, open questions. Write it to a draft path. Show a diff against the approved version. Approval copies the draft over and records the model identifier, the prompt version and the time. Trap: Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. Done when: A generation never writes to an approved path, asserted in the suite. A failed or malformed model response leaves both the draft and the approved file untouched, tested with a stub returning prose. Every approved spec records the model identifier, prompt version and approval time. The draft view shows a line diff against the approved version before approval is possible. Do not build yet: No tasks, no agent export, no cost tracking yet. ### Phase 4 · Tasks that point at code Build: Derive tasks from approved specs, one per acceptance criterion, each with the files it expects to touch. Order them by the dependency edges. Read status from git: a branch named after the task id means in progress, a commit on the default branch mentioning the id means done. Manual status is allowed but is marked as manual wherever it appears. Trap: A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. Done when: Task status derived from a branch or a commit is recomputed on demand and matches a repository fixture, tested. A manually set status is visibly labelled as manual everywhere it is displayed. Regenerating tasks for a spec preserves the status and history of tasks whose text has not changed, tested. Deleting a feature never orphans a task silently; it reports what would be lost first. Do not build yet: No agent export, cost ceiling or staleness report yet. ### Phase 5 · Handing it over, and knowing what it cost Build: Write an AGENTS.md at the repository root, and for a monorepo one per package directory, since the published convention is that the closest file to the edited file wins. Emit approved specs and open tasks as plain markdown beside the code and commit them. Track token spend per run against a monthly ceiling. Report which approved plans reference paths that have changed since approval. Trap: Exporting a zip of planning documents into a folder the agent has never been told to read means the agent never reads it, and you conclude the model ignores your plan. Write to the conventional path at the repository root, check it into git, and confirm by asking the agent to quote a line back to you. Done when: Running the export produces an AGENTS.md at the repository root and nested files for each package directory in a monorepo fixture, tested. The exported markdown contains no tool-specific syntax and is readable on its own, checked by review. Reaching the monthly token ceiling stops generation with a clear message and leaves everything else working, tested. The staleness report lists every approved spec whose referenced paths changed after its approval time, tested against a fixture. Do not build yet: Nothing after this. ### Out of scope (and why) - Running the coding agent for you, which turns a planning tool into an orchestrator and a different, much larger project. - A hosted board with collaborators, which needs accounts, permissions and conflict handling for a tool one person uses on one repository. - Semantic search over documentation, which is an index to build and maintain for a payoff a grep over the repository mostly already gives you. - A protocol server exposing the plan to agents, which is worth adding only after the plain files have proved the agent reads them. ### README must contain - That the markdown files in the repository are the record and the database is a disposable index, with the reindex command written out - That the export writes an agent instruction file at the repository root, and nested files in subdirectories where the convention is that the closest one wins - That a generated specification is a draft until a person approves it, and that approvals are recorded with the model and prompt version - That task status is read from branches and commits, and that any manually set status is labelled as such - Where the token spend is recorded, what the monthly ceiling is, and what stops when it is reached ===== AGENTS.md ===== # Agent instructions · CodeSpring indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A local Node and TypeScript application with a small web interface, no accounts, Markdown files with frontmatter inside the target git repository, SQLite, rebuilt from the files on demand, One model call per feature, structured output, written to a draft path, Read from git branches and commit messages, not from dragging cards. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. - Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. - Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. - A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. ===== BUILD_PLAN.md ===== # Build plan · CodeSpring A local planning tool whose hard problems are keeping the plan in the repository rather than in a database the agent cannot see, stopping a generated draft from being mistaken for an approved specification, and noticing when a plan has gone stale against the code it describes. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · The repository is the record Every feature is a markdown file inside the target repository and the database is only an index of them. ### Steps 1. Fix the on-disk layout before writing any interface The directory, the file name and the frontmatter keys are the contract everything else depends on. Files: `docs/file-format.md`, `src/store/files.ts` 2. Index into SQLite and rebuild on command Prove the index is disposable by disposing of it in a test. Files: `src/store/index.ts`, `tests/reindex.test.ts` ```sh npm run reindex ``` 3. Give every feature an id that survives a rename Titles change constantly and every link into the plan must survive it. Files: `src/store/ids.ts` ### Done when - [ ] Reindexing from empty reproduces the same state - [ ] Ids survive a title change and a file rename - [ ] External edits appear without a restart - [ ] A non-git directory is refused with an explanation ### Watch out - Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. ## Phase 2 · A map you can read without the tool Features and their dependencies can be arranged quickly, and the arrangement lives in the feature files. ### Steps 1. Store coordinates and edges in frontmatter Two numbers a human can read beat a proprietary diagram document. Files: `src/map/persist.ts` 2. Detect dependency cycles on write A cycle is a planning mistake, and it should be caught where it was made. Files: `src/map/graph.ts`, `tests/graph.test.ts` 3. Keep a list view that is not a fallback Most of this work is faster with a keyboard than with a mouse. Files: `src/app/list/page.tsx` ### Done when - [ ] The map round-trips through readable frontmatter - [ ] Cycles are reported rather than stored - [ ] Every canvas action has a keyboard equivalent - [ ] One broken file does not break the whole map ### Watch out - Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. ## Phase 3 · A draft is not a specification Generation produces a draft at a separate path that a person has to approve before anything downstream reads it. ### Steps 1. Generate to a draft path, never over an approval The approved file is the one containing corrections somebody made by hand. Files: `src/generate/spec.ts` 2. Diff before approving, and record the approval Approval is the only moment a human is definitely in the loop. Files: `src/app/spec/[id]/page.tsx`, `src/store/specs.ts` 3. Store the model identifier and prompt version Six weeks later you will want to know which prompt produced a strange section. Files: `src/store/specs.ts`, `tests/spec-approval.test.ts` ### Done when - [ ] Generation never overwrites an approved file - [ ] A malformed response changes nothing on disk - [ ] Approvals record model, prompt version and time - [ ] A diff is shown before approval is possible ### Watch out - Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. ## Phase 4 · Tasks that point at code Each task carries acceptance criteria and expected files, and its status is read from the repository rather than asserted. ### Steps 1. Derive one task per acceptance criterion A task without a falsifiable criterion is a note, not a task. Files: `src/tasks/derive.ts` 2. Read status from branches and commits Git already holds the answer and does not forget. Files: `src/tasks/status.ts`, `tests/status.test.ts` ```sh git log --oneline --grep=TASK- ``` 3. Preserve task identity across regeneration Otherwise every regeneration resets the board. Files: `src/tasks/derive.ts` ### Done when - [ ] Derived status matches a repository fixture - [ ] Manual status is labelled as manual - [ ] Regeneration preserves unchanged tasks - [ ] Deleting a feature reports what it would orphan ### Watch out - A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. ## Not in this build - Running the coding agent for you. - A hosted board with collaborators. - Semantic search over documentation. - A protocol server exposing the plan. ## After v1, if you want it - A per-task context bundle that lists only the files that task expects to touch - A weekly diff of the plan against the repository, mailed to yourself, so staleness is noticed rather than discovered - Estimates recorded at approval time and compared with what the work actually took ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. The git working tree holding the plan. The tool refuses anything that is not one. REPO_PATH=/home/you/code/your-project # Required. Directory inside the repository for feature files, drafts and approved specs. PLAN_DIR=docs/plan # Required. The SQLite index. Deletable at any time; reindex rebuilds it. INDEX_PATH=./.cache/plan-index.db # Required · secret. The generation model. Set a provider-side spend limit as well. MODEL_API_KEY=sk-...redacted # Required. Recorded with every draft, because a different model writes a different specification. MODEL_ID=a text model identifier # Required. Generation stops here for the month. Everything else keeps working. MONTHLY_TOKEN_CEILING=2000000 # Required. Used to match branches and commit messages back to tasks. TASK_ID_PREFIX=TASK-
You are building a lean indie version of CodeSpring. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== README.md ===== # CodeSpring · indie build A local planning tool whose hard problems are keeping the plan in the repository rather than in a database the agent cannot see, stopping a generated draft from being mistaken for an approved specification, and noticing when a plan has gone stale against the code it describes. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Runtime | A local Node and TypeScript application with a small web interface, no accounts | one person planning one repository does not need a server or a login | | Source of truth | Markdown files with frontmatter inside the target git repository | the coding agent reads files, so the plan has to be files, and git already versions them | | Index | SQLite, rebuilt from the files on demand | a cache you can delete is a cache that cannot silently rot | | Generation | One model call per feature, structured output, written to a draft path | a draft that lands on top of an approved spec destroys the only edits that were correct | | Status | Read from git branches and commit messages, not from dragging cards | a board moved by hand starts lying about what is finished within a week | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the planning tool and the export. - Get it: nodejs.org, or your version manager. - Verify: node --version prints v22 or higher - [ ] **Git, with a repository you actually intend to build in** · free - Why: The plan lives in the repository and task status is read from branches and commits, so a scratch folder will not exercise any of it. - Get it: Use an existing project, or create one and make at least one commit. - Verify: git log prints at least one commit in the target directory - [ ] **An API key for a text model that returns structured output** · pay per call; a planning session is small change, and the monthly ceiling in this build is what keeps it that way - Why: Generation is one call per feature and is the only part that leaves your machine or costs money. - Get it: Create a key with the provider you prefer and set a spend limit in their console. - Verify: One feature produces a draft that parses against your schema - [ ] **The coding agent you actually use** · free or whatever you already pay - Why: The whole last phase is about writing files that agent reads, and the only way to know it read them is to ask it to quote one back. - Get it: Whichever agent or editor you already work in. - Verify: After an export, the agent can quote a line from your approved specification - [ ] **Where the plan files live in the repository** · free - Why: This path is the contract between the tool, git and the agent, and changing it later means rewriting every link. - Get it: Write down the directory, the file naming rule and the frontmatter keys before any code. - Verify: docs/file-format.md exists and the indexer reads it as specification ## Quick start ```sh npm run reindex ``` Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Running the coding agent for you. - A hosted board with collaborators. - Semantic search over documentation. - A protocol server exposing the plan. - polished drag-and-drop mind-map canvas - MCP server integration with Cursor/Claude Code/Codex - semantic docs search - hosted kanban sync across devices - prebuilt skills library If one of those is essential to you, that is the reason to keep paying for CodeSpring, and the README should say so rather than pretend. ===== BRIEF.md ===== # Build brief · CodeSpring The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a planning workspace that turns a map of features into specification files your coding agent reads out of the repository to replace CodeSpring. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Runtime: A local Node and TypeScript application with a small web interface, no accounts · one person planning one repository does not need a server or a login - Source of truth: Markdown files with frontmatter inside the target git repository · the coding agent reads files, so the plan has to be files, and git already versions them - Index: SQLite, rebuilt from the files on demand · a cache you can delete is a cache that cannot silently rot - Generation: One model call per feature, structured output, written to a draft path · a draft that lands on top of an approved spec destroys the only edits that were correct - Status: Read from git branches and commit messages, not from dragging cards · a board moved by hand starts lying about what is finished within a week ### Data model (create this before Phase 1) - features(id, slug, title, status, parent_id, map_x, map_y, file_path, created_at, updated_at) · the row is an index entry, the file is the record - edges(from_feature, to_feature, kind) · depends_on or splits_into, drawn on the map and used to order tasks - specs(feature_id, draft_path, approved_path, model_id, prompt_version, generated_at, approved_at, approved_by) - tasks(id, feature_id, title, acceptance, expected_files_json, status, branch, commit_sha, closed_at) - runs(id, feature_id, model_id, input_tokens, output_tokens, cost_minor, at) · every model call, so the month has a number attached to it - staleness(feature_id, checked_at, referenced_paths_json, repo_changed_at) · which approved plans describe code that has since moved - Nothing here is authoritative. Every row points at a file git already tracks, so deleting the database and reindexing loses precisely nothing. ### Phase 1 · The repository is the record Build: Point the tool at a git working tree. Each feature is a markdown file with frontmatter holding a stable id, title, status and map position, under a directory you choose. Index those files into SQLite on start and on change, and provide a reindex command that rebuilds from scratch. Trap: Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. Done when: Deleting the database and reindexing reproduces the same feature list and edges exactly, tested. A feature id survives a title change and a file rename, tested by renaming both. A feature edited in an external editor shows up without restarting the tool. The tool refuses to run against a directory that is not a git working tree and says why. Do not build yet: No map, no generation, no tasks, no agent export yet. ### Phase 2 · A map you can read without the tool Build: A canvas listing features as nodes with drag positioning, keyboard creation and arrow keys for movement, and edges typed as depends_on or splits_into. Write positions and edges back into the frontmatter of the feature files. Support a plain list view that does everything the canvas does. Trap: Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. Done when: Positions and edges survive a round trip through the files with no canvas-specific document anywhere, checked by reading a feature file by hand. A dependency cycle is detected and reported rather than stored silently. Every canvas action has a keyboard equivalent and the list view can create, connect and reorder without the canvas. A merge conflict in one feature file leaves the rest of the map loadable. Do not build yet: No specification generation and no tasks yet. ### Phase 3 · A draft is not a specification Build: One model call per feature turning the notes and the incoming edges into a structured draft: problem, scope, explicitly out of scope, acceptance criteria, open questions. Write it to a draft path. Show a diff against the approved version. Approval copies the draft over and records the model identifier, the prompt version and the time. Trap: Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. Done when: A generation never writes to an approved path, asserted in the suite. A failed or malformed model response leaves both the draft and the approved file untouched, tested with a stub returning prose. Every approved spec records the model identifier, prompt version and approval time. The draft view shows a line diff against the approved version before approval is possible. Do not build yet: No tasks, no agent export, no cost tracking yet. ### Phase 4 · Tasks that point at code Build: Derive tasks from approved specs, one per acceptance criterion, each with the files it expects to touch. Order them by the dependency edges. Read status from git: a branch named after the task id means in progress, a commit on the default branch mentioning the id means done. Manual status is allowed but is marked as manual wherever it appears. Trap: A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. Done when: Task status derived from a branch or a commit is recomputed on demand and matches a repository fixture, tested. A manually set status is visibly labelled as manual everywhere it is displayed. Regenerating tasks for a spec preserves the status and history of tasks whose text has not changed, tested. Deleting a feature never orphans a task silently; it reports what would be lost first. Do not build yet: No agent export, cost ceiling or staleness report yet. ### Phase 5 · Handing it over, and knowing what it cost Build: Write an AGENTS.md at the repository root, and for a monorepo one per package directory, since the published convention is that the closest file to the edited file wins. Emit approved specs and open tasks as plain markdown beside the code and commit them. Track token spend per run against a monthly ceiling. Report which approved plans reference paths that have changed since approval. Trap: Exporting a zip of planning documents into a folder the agent has never been told to read means the agent never reads it, and you conclude the model ignores your plan. Write to the conventional path at the repository root, check it into git, and confirm by asking the agent to quote a line back to you. Done when: Running the export produces an AGENTS.md at the repository root and nested files for each package directory in a monorepo fixture, tested. The exported markdown contains no tool-specific syntax and is readable on its own, checked by review. Reaching the monthly token ceiling stops generation with a clear message and leaves everything else working, tested. The staleness report lists every approved spec whose referenced paths changed after its approval time, tested against a fixture. Do not build yet: Nothing after this. ### Out of scope (and why) - Running the coding agent for you, which turns a planning tool into an orchestrator and a different, much larger project. - A hosted board with collaborators, which needs accounts, permissions and conflict handling for a tool one person uses on one repository. - Semantic search over documentation, which is an index to build and maintain for a payoff a grep over the repository mostly already gives you. - A protocol server exposing the plan to agents, which is worth adding only after the plain files have proved the agent reads them. ### README must contain - That the markdown files in the repository are the record and the database is a disposable index, with the reindex command written out - That the export writes an agent instruction file at the repository root, and nested files in subdirectories where the convention is that the closest one wins - That a generated specification is a draft until a person approves it, and that approvals are recorded with the model and prompt version - That task status is read from branches and commits, and that any manually set status is labelled as such - Where the token spend is recorded, what the monthly ceiling is, and what stops when it is reached ===== AGENTS.md ===== # Agent instructions · CodeSpring indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A local Node and TypeScript application with a small web interface, no accounts, Markdown files with frontmatter inside the target git repository, SQLite, rebuilt from the files on demand, One model call per feature, structured output, written to a draft path, Read from git branches and commit messages, not from dragging cards. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. - Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. - Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. - A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. ===== BUILD_PLAN.md ===== # Build plan · CodeSpring A local planning tool whose hard problems are keeping the plan in the repository rather than in a database the agent cannot see, stopping a generated draft from being mistaken for an approved specification, and noticing when a plan has gone stale against the code it describes. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · The repository is the record Every feature is a markdown file inside the target repository and the database is only an index of them. ### Steps 1. Fix the on-disk layout before writing any interface The directory, the file name and the frontmatter keys are the contract everything else depends on. Files: `docs/file-format.md`, `src/store/files.ts` 2. Index into SQLite and rebuild on command Prove the index is disposable by disposing of it in a test. Files: `src/store/index.ts`, `tests/reindex.test.ts` ```sh npm run reindex ``` 3. Give every feature an id that survives a rename Titles change constantly and every link into the plan must survive it. Files: `src/store/ids.ts` ### Done when - [ ] Reindexing from empty reproduces the same state - [ ] Ids survive a title change and a file rename - [ ] External edits appear without a restart - [ ] A non-git directory is refused with an explanation ### Watch out - Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. ## Phase 2 · A map you can read without the tool Features and their dependencies can be arranged quickly, and the arrangement lives in the feature files. ### Steps 1. Store coordinates and edges in frontmatter Two numbers a human can read beat a proprietary diagram document. Files: `src/map/persist.ts` 2. Detect dependency cycles on write A cycle is a planning mistake, and it should be caught where it was made. Files: `src/map/graph.ts`, `tests/graph.test.ts` 3. Keep a list view that is not a fallback Most of this work is faster with a keyboard than with a mouse. Files: `src/app/list/page.tsx` ### Done when - [ ] The map round-trips through readable frontmatter - [ ] Cycles are reported rather than stored - [ ] Every canvas action has a keyboard equivalent - [ ] One broken file does not break the whole map ### Watch out - Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. ## Phase 3 · A draft is not a specification Generation produces a draft at a separate path that a person has to approve before anything downstream reads it. ### Steps 1. Generate to a draft path, never over an approval The approved file is the one containing corrections somebody made by hand. Files: `src/generate/spec.ts` 2. Diff before approving, and record the approval Approval is the only moment a human is definitely in the loop. Files: `src/app/spec/[id]/page.tsx`, `src/store/specs.ts` 3. Store the model identifier and prompt version Six weeks later you will want to know which prompt produced a strange section. Files: `src/store/specs.ts`, `tests/spec-approval.test.ts` ### Done when - [ ] Generation never overwrites an approved file - [ ] A malformed response changes nothing on disk - [ ] Approvals record model, prompt version and time - [ ] A diff is shown before approval is possible ### Watch out - Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. ## Phase 4 · Tasks that point at code Each task carries acceptance criteria and expected files, and its status is read from the repository rather than asserted. ### Steps 1. Derive one task per acceptance criterion A task without a falsifiable criterion is a note, not a task. Files: `src/tasks/derive.ts` 2. Read status from branches and commits Git already holds the answer and does not forget. Files: `src/tasks/status.ts`, `tests/status.test.ts` ```sh git log --oneline --grep=TASK- ``` 3. Preserve task identity across regeneration Otherwise every regeneration resets the board. Files: `src/tasks/derive.ts` ### Done when - [ ] Derived status matches a repository fixture - [ ] Manual status is labelled as manual - [ ] Regeneration preserves unchanged tasks - [ ] Deleting a feature reports what it would orphan ### Watch out - A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. ## Not in this build - Running the coding agent for you. - A hosted board with collaborators. - Semantic search over documentation. - A protocol server exposing the plan. ## After v1, if you want it - A per-task context bundle that lists only the files that task expects to touch - A weekly diff of the plan against the repository, mailed to yourself, so staleness is noticed rather than discovered - Estimates recorded at approval time and compared with what the work actually took ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. The git working tree holding the plan. The tool refuses anything that is not one. REPO_PATH=/home/you/code/your-project # Required. Directory inside the repository for feature files, drafts and approved specs. PLAN_DIR=docs/plan # Required. The SQLite index. Deletable at any time; reindex rebuilds it. INDEX_PATH=./.cache/plan-index.db # Required · secret. The generation model. Set a provider-side spend limit as well. MODEL_API_KEY=sk-...redacted # Required. Recorded with every draft, because a different model writes a different specification. MODEL_ID=a text model identifier # Required. Generation stops here for the month. Everything else keeps working. MONTHLY_TOKEN_CEILING=2000000 # Required. Used to match branches and commit messages back to tasks. TASK_ID_PREFIX=TASK-
You are building a production product version of CodeSpring. Create the following project files first, then implement the application by following them. Keep the files updated as decisions change. Do not collapse this into a single README or prompt. ===== PRODUCT.md ===== # CodeSpring · product brief ## Problem The core loop, a mind map that turns feature notes into PRDs and kanban tasks fed to a coding agent, is just structured prompting and file generation, well within reach of a one-shot build. What's missing is the polish: the visual mind-map canvas, MCP/CLI integrations with Claude Code, Cursor and Codex, and the docs search. A DIY version gets you most of the value but with a rougher UI and manual glue between the planning docs and your agent of choice. ## Product outcome A planning tool whose output is ordinary markdown in your repository: drafts that a person approved, tasks whose status git already knows, agent instruction files at the conventional paths, and a report of which plans no longer match the code. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - OpenAI/Anthropic API key ## Explicit non-goals for v1 - Running the coding agent for you. - A hosted board with collaborators. - Semantic search over documentation. - A protocol server exposing the plan. - polished drag-and-drop mind-map canvas - MCP server integration with Cursor/Claude Code/Codex - semantic docs search - hosted kanban sync across devices - prebuilt skills library ## Success criteria - Deleting the index and reindexing is confirmed to reproduce the same state - Generation is confirmed never to write to an approved path - Export is confirmed to write root and nested agent files in a monorepo fixture - Derived task status is confirmed to match a repository fixture - The monthly token ceiling is confirmed to stop generation and nothing else ===== BRIEF.md ===== # Build brief · CodeSpring The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a planning workspace that turns a map of features into specification files your coding agent reads out of the repository to replace CodeSpring. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Runtime: A local Node and TypeScript application with a small web interface, no accounts · one person planning one repository does not need a server or a login - Source of truth: Markdown files with frontmatter inside the target git repository · the coding agent reads files, so the plan has to be files, and git already versions them - Index: SQLite, rebuilt from the files on demand · a cache you can delete is a cache that cannot silently rot - Generation: One model call per feature, structured output, written to a draft path · a draft that lands on top of an approved spec destroys the only edits that were correct - Status: Read from git branches and commit messages, not from dragging cards · a board moved by hand starts lying about what is finished within a week ### Data model (create this before Phase 1) - features(id, slug, title, status, parent_id, map_x, map_y, file_path, created_at, updated_at) · the row is an index entry, the file is the record - edges(from_feature, to_feature, kind) · depends_on or splits_into, drawn on the map and used to order tasks - specs(feature_id, draft_path, approved_path, model_id, prompt_version, generated_at, approved_at, approved_by) - tasks(id, feature_id, title, acceptance, expected_files_json, status, branch, commit_sha, closed_at) - runs(id, feature_id, model_id, input_tokens, output_tokens, cost_minor, at) · every model call, so the month has a number attached to it - staleness(feature_id, checked_at, referenced_paths_json, repo_changed_at) · which approved plans describe code that has since moved - Nothing here is authoritative. Every row points at a file git already tracks, so deleting the database and reindexing loses precisely nothing. ### Phase 1 · The repository is the record Build: Point the tool at a git working tree. Each feature is a markdown file with frontmatter holding a stable id, title, status and map position, under a directory you choose. Index those files into SQLite on start and on change, and provide a reindex command that rebuilds from scratch. Trap: Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. Done when: Deleting the database and reindexing reproduces the same feature list and edges exactly, tested. A feature id survives a title change and a file rename, tested by renaming both. A feature edited in an external editor shows up without restarting the tool. The tool refuses to run against a directory that is not a git working tree and says why. Do not build yet: No map, no generation, no tasks, no agent export yet. ### Phase 2 · A map you can read without the tool Build: A canvas listing features as nodes with drag positioning, keyboard creation and arrow keys for movement, and edges typed as depends_on or splits_into. Write positions and edges back into the frontmatter of the feature files. Support a plain list view that does everything the canvas does. Trap: Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. Done when: Positions and edges survive a round trip through the files with no canvas-specific document anywhere, checked by reading a feature file by hand. A dependency cycle is detected and reported rather than stored silently. Every canvas action has a keyboard equivalent and the list view can create, connect and reorder without the canvas. A merge conflict in one feature file leaves the rest of the map loadable. Do not build yet: No specification generation and no tasks yet. ### Phase 3 · A draft is not a specification Build: One model call per feature turning the notes and the incoming edges into a structured draft: problem, scope, explicitly out of scope, acceptance criteria, open questions. Write it to a draft path. Show a diff against the approved version. Approval copies the draft over and records the model identifier, the prompt version and the time. Trap: Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. Done when: A generation never writes to an approved path, asserted in the suite. A failed or malformed model response leaves both the draft and the approved file untouched, tested with a stub returning prose. Every approved spec records the model identifier, prompt version and approval time. The draft view shows a line diff against the approved version before approval is possible. Do not build yet: No tasks, no agent export, no cost tracking yet. ### Phase 4 · Tasks that point at code Build: Derive tasks from approved specs, one per acceptance criterion, each with the files it expects to touch. Order them by the dependency edges. Read status from git: a branch named after the task id means in progress, a commit on the default branch mentioning the id means done. Manual status is allowed but is marked as manual wherever it appears. Trap: A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. Done when: Task status derived from a branch or a commit is recomputed on demand and matches a repository fixture, tested. A manually set status is visibly labelled as manual everywhere it is displayed. Regenerating tasks for a spec preserves the status and history of tasks whose text has not changed, tested. Deleting a feature never orphans a task silently; it reports what would be lost first. Do not build yet: No agent export, cost ceiling or staleness report yet. ### Phase 5 · Handing it over, and knowing what it cost Build: Write an AGENTS.md at the repository root, and for a monorepo one per package directory, since the published convention is that the closest file to the edited file wins. Emit approved specs and open tasks as plain markdown beside the code and commit them. Track token spend per run against a monthly ceiling. Report which approved plans reference paths that have changed since approval. Trap: Exporting a zip of planning documents into a folder the agent has never been told to read means the agent never reads it, and you conclude the model ignores your plan. Write to the conventional path at the repository root, check it into git, and confirm by asking the agent to quote a line back to you. Done when: Running the export produces an AGENTS.md at the repository root and nested files for each package directory in a monorepo fixture, tested. The exported markdown contains no tool-specific syntax and is readable on its own, checked by review. Reaching the monthly token ceiling stops generation with a clear message and leaves everything else working, tested. The staleness report lists every approved spec whose referenced paths changed after its approval time, tested against a fixture. Do not build yet: Nothing after this. ### Out of scope (and why) - Running the coding agent for you, which turns a planning tool into an orchestrator and a different, much larger project. - A hosted board with collaborators, which needs accounts, permissions and conflict handling for a tool one person uses on one repository. - Semantic search over documentation, which is an index to build and maintain for a payoff a grep over the repository mostly already gives you. - A protocol server exposing the plan to agents, which is worth adding only after the plain files have proved the agent reads them. ### README must contain - That the markdown files in the repository are the record and the database is a disposable index, with the reindex command written out - That the export writes an agent instruction file at the repository root, and nested files in subdirectories where the convention is that the closest one wins - That a generated specification is a draft until a person approves it, and that approvals are recorded with the model and prompt version - That task status is read from branches and commits, and that any manually set status is labelled as such - Where the token spend is recorded, what the monthly ceiling is, and what stops when it is reached ===== ARCHITECTURE.md ===== # Architecture · CodeSpring ## Stack | Part | Choice | Why | | --- | --- | --- | | Runtime | A local Node and TypeScript application with a small web interface, no accounts | one person planning one repository does not need a server or a login | | Source of truth | Markdown files with frontmatter inside the target git repository | the coding agent reads files, so the plan has to be files, and git already versions them | | Index | SQLite, rebuilt from the files on demand | a cache you can delete is a cache that cannot silently rot | | Generation | One model call per feature, structured output, written to a draft path | a draft that lands on top of an approved spec destroys the only edits that were correct | | Status | Read from git branches and commit messages, not from dragging cards | a board moved by hand starts lying about what is finished within a week | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Files | Feature, draft and approved files plus frontmatter. | Any on-disk layout, provided it is documented and readable without the tool. | | Index | SQLite index rebuilt from files. | Any store, provided deleting it and reindexing loses nothing. | | Generation | One model call, structured draft output. | Any provider, provided a failure never touches an approved file. | | Tasks | Derivation, ordering and git-derived status. | Any tracker, provided derived status stays distinguishable from a typed one. | | Export | Agent instruction files and the staleness report. | Any format, provided it lands where the agent already looks. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `REPO_PATH` · required · The git working tree holding the plan. The tool refuses anything that is not one. - `PLAN_DIR` · required · Directory inside the repository for feature files, drafts and approved specs. - `INDEX_PATH` · required · The SQLite index. Deletable at any time; reindex rebuilds it. - `MODEL_API_KEY` · required, secret · The generation model. Set a provider-side spend limit as well. - `MODEL_ID` · required · Recorded with every draft, because a different model writes a different specification. - `MONTHLY_TOKEN_CEILING` · required · Generation stops here for the month. Everything else keeps working. - `TASK_ID_PREFIX` · required · Used to match branches and commit messages back to tasks. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it. ===== AGENTS.md ===== # Agent instructions · CodeSpring product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A local Node and TypeScript application with a small web interface, no accounts, Markdown files with frontmatter inside the target git repository, SQLite, rebuilt from the files on demand, One model call per feature, structured output, written to a draft path, Read from git branches and commit messages, not from dragging cards. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. - Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. - Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. - A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. - Exporting a zip of planning documents into a folder the agent has never been told to read means the agent never reads it, and you conclude the model ignores your plan. Write to the conventional path at the repository root, check it into git, and confirm by asking the agent to quote a line back to you. ===== MILESTONES.md ===== # Delivery milestones · CodeSpring Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · The repository is the record Every feature is a markdown file inside the target repository and the database is only an index of them. ### Steps 1. Fix the on-disk layout before writing any interface The directory, the file name and the frontmatter keys are the contract everything else depends on. Files: `docs/file-format.md`, `src/store/files.ts` 2. Index into SQLite and rebuild on command Prove the index is disposable by disposing of it in a test. Files: `src/store/index.ts`, `tests/reindex.test.ts` ```sh npm run reindex ``` 3. Give every feature an id that survives a rename Titles change constantly and every link into the plan must survive it. Files: `src/store/ids.ts` ### Done when - [ ] Reindexing from empty reproduces the same state - [ ] Ids survive a title change and a file rename - [ ] External edits appear without a restart - [ ] A non-git directory is refused with an explanation ### Watch out - Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. ## M2 · A map you can read without the tool Features and their dependencies can be arranged quickly, and the arrangement lives in the feature files. ### Steps 1. Store coordinates and edges in frontmatter Two numbers a human can read beat a proprietary diagram document. Files: `src/map/persist.ts` 2. Detect dependency cycles on write A cycle is a planning mistake, and it should be caught where it was made. Files: `src/map/graph.ts`, `tests/graph.test.ts` 3. Keep a list view that is not a fallback Most of this work is faster with a keyboard than with a mouse. Files: `src/app/list/page.tsx` ### Done when - [ ] The map round-trips through readable frontmatter - [ ] Cycles are reported rather than stored - [ ] Every canvas action has a keyboard equivalent - [ ] One broken file does not break the whole map ### Watch out - Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. ## M3 · A draft is not a specification Generation produces a draft at a separate path that a person has to approve before anything downstream reads it. ### Steps 1. Generate to a draft path, never over an approval The approved file is the one containing corrections somebody made by hand. Files: `src/generate/spec.ts` 2. Diff before approving, and record the approval Approval is the only moment a human is definitely in the loop. Files: `src/app/spec/[id]/page.tsx`, `src/store/specs.ts` 3. Store the model identifier and prompt version Six weeks later you will want to know which prompt produced a strange section. Files: `src/store/specs.ts`, `tests/spec-approval.test.ts` ### Done when - [ ] Generation never overwrites an approved file - [ ] A malformed response changes nothing on disk - [ ] Approvals record model, prompt version and time - [ ] A diff is shown before approval is possible ### Watch out - Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. ## M4 · Tasks that point at code Each task carries acceptance criteria and expected files, and its status is read from the repository rather than asserted. ### Steps 1. Derive one task per acceptance criterion A task without a falsifiable criterion is a note, not a task. Files: `src/tasks/derive.ts` 2. Read status from branches and commits Git already holds the answer and does not forget. Files: `src/tasks/status.ts`, `tests/status.test.ts` ```sh git log --oneline --grep=TASK- ``` 3. Preserve task identity across regeneration Otherwise every regeneration resets the board. Files: `src/tasks/derive.ts` ### Done when - [ ] Derived status matches a repository fixture - [ ] Manual status is labelled as manual - [ ] Regeneration preserves unchanged tasks - [ ] Deleting a feature reports what it would orphan ### Watch out - A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. ## M5 · Handing it over, and knowing what it cost (production only) The plan leaves as the conventional files an agent already looks for, with a spend ceiling and a staleness report. ### Steps 1. Write to the conventional agent file, nested where needed The closest file to the edited file is the one that wins. Files: `src/export/agents.ts`, `tests/export.test.ts` ```sh npm run export ``` 2. Cap the monthly spend and degrade to writing by hand A rented model with no ceiling is a surprise bill. Files: `src/generate/cost.ts` 3. Report plans whose code has moved under them A stale plan is more dangerous than no plan, because it is confident. Files: `src/staleness.ts` ### Done when - [ ] Export writes root and nested agent files - [ ] Exported markdown reads on its own - [ ] The token ceiling stops generation, not the tool - [ ] Stale plans are listed with what changed ### Watch out - Exporting a zip of planning documents into a folder the agent has never been told to read means the agent never reads it, and you conclude the model ignores your plan. Write to the conventional path at the repository root, check it into git, and confirm by asking the agent to quote a line back to you. ===== OPERATIONS.md ===== # Operations · CodeSpring ## Backup Git is the backup, which is the point of putting the plan there. Confirm the plan directory is committed and not in .gitignore, and back up nothing else. The index is disposable. ## Restore Clone the repository, run reindex, and confirm the feature count and edges match. If they do not, the file format documentation is wrong, not the index. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Monthly token spend against the ceiling, the proportion of drafts approved without edits, and the size of the staleness list. Drafts approved untouched usually mean the approval step has become a habit rather than a review. ## Incident checklist The failure mode here is quiet: the agent builds from a plan that no longer matches the code. The staleness report and the recorded approval times are what let you find when the plan and the repository parted company. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Deleting the index and reindexing is confirmed to reproduce the same state - [ ] Generation is confirmed never to write to an approved path - [ ] Export is confirmed to write root and nested agent files in a monorepo fixture - [ ] Derived task status is confirmed to match a repository fixture - [ ] The monthly token ceiling is confirmed to stop generation and nothing else ## Launch constraint Do not market omitted CodeSpring capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered. ===== .env.example ===== # Copy to .env and fill in. Never commit .env; this file documents it. # Required. The git working tree holding the plan. The tool refuses anything that is not one. REPO_PATH=/home/you/code/your-project # Required. Directory inside the repository for feature files, drafts and approved specs. PLAN_DIR=docs/plan # Required. The SQLite index. Deletable at any time; reindex rebuilds it. INDEX_PATH=./.cache/plan-index.db # Required · secret. The generation model. Set a provider-side spend limit as well. MODEL_API_KEY=sk-...redacted # Required. Recorded with every draft, because a different model writes a different specification. MODEL_ID=a text model identifier # Required. Generation stops here for the month. Everything else keeps working. MONTHLY_TOKEN_CEILING=2000000 # Required. Used to match branches and commit messages back to tasks. TASK_ID_PREFIX=TASK-
# CodeSpring · indie build A local planning tool whose hard problems are keeping the plan in the repository rather than in a database the agent cannot see, stopping a generated draft from being mistaken for an approved specification, and noticing when a plan has gone stale against the code it describes. Estimated effort: **multi-day**. Work `BUILD_PLAN.md` top to bottom · every phase ends in a check that has to pass before the next one starts. ## Stack | Part | Choice | Why | | --- | --- | --- | | Runtime | A local Node and TypeScript application with a small web interface, no accounts | one person planning one repository does not need a server or a login | | Source of truth | Markdown files with frontmatter inside the target git repository | the coding agent reads files, so the plan has to be files, and git already versions them | | Index | SQLite, rebuilt from the files on demand | a cache you can delete is a cache that cannot silently rot | | Generation | One model call per feature, structured output, written to a draft path | a draft that lands on top of an approved spec destroys the only edits that were correct | | Status | Read from git branches and commit messages, not from dragging cards | a board moved by hand starts lying about what is finished within a week | ## Before you start Have every one of these ready. The plan assumes them from step one. - [ ] **Node.js 22 or newer** · free - Why: Runs the planning tool and the export. - Get it: nodejs.org, or your version manager. - Verify: node --version prints v22 or higher - [ ] **Git, with a repository you actually intend to build in** · free - Why: The plan lives in the repository and task status is read from branches and commits, so a scratch folder will not exercise any of it. - Get it: Use an existing project, or create one and make at least one commit. - Verify: git log prints at least one commit in the target directory - [ ] **An API key for a text model that returns structured output** · pay per call; a planning session is small change, and the monthly ceiling in this build is what keeps it that way - Why: Generation is one call per feature and is the only part that leaves your machine or costs money. - Get it: Create a key with the provider you prefer and set a spend limit in their console. - Verify: One feature produces a draft that parses against your schema - [ ] **The coding agent you actually use** · free or whatever you already pay - Why: The whole last phase is about writing files that agent reads, and the only way to know it read them is to ask it to quote one back. - Get it: Whichever agent or editor you already work in. - Verify: After an export, the agent can quote a line from your approved specification - [ ] **Where the plan files live in the repository** · free - Why: This path is the contract between the tool, git and the agent, and changing it later means rewriting every link. - Get it: Write down the directory, the file naming rule and the frontmatter keys before any code. - Verify: docs/file-format.md exists and the indexer reads it as specification ## Quick start ```sh npm run reindex ``` Then copy `.env.example` to `.env` and fill in the values it documents. ## Honest limits This build deliberately does not replace: - Running the coding agent for you. - A hosted board with collaborators. - Semantic search over documentation. - A protocol server exposing the plan. - polished drag-and-drop mind-map canvas - MCP server integration with Cursor/Claude Code/Codex - semantic docs search - hosted kanban sync across devices - prebuilt skills library If one of those is essential to you, that is the reason to keep paying for CodeSpring, and the README should say so rather than pretend.
# Build brief · CodeSpring The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a planning workspace that turns a map of features into specification files your coding agent reads out of the repository to replace CodeSpring. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Runtime: A local Node and TypeScript application with a small web interface, no accounts · one person planning one repository does not need a server or a login - Source of truth: Markdown files with frontmatter inside the target git repository · the coding agent reads files, so the plan has to be files, and git already versions them - Index: SQLite, rebuilt from the files on demand · a cache you can delete is a cache that cannot silently rot - Generation: One model call per feature, structured output, written to a draft path · a draft that lands on top of an approved spec destroys the only edits that were correct - Status: Read from git branches and commit messages, not from dragging cards · a board moved by hand starts lying about what is finished within a week ### Data model (create this before Phase 1) - features(id, slug, title, status, parent_id, map_x, map_y, file_path, created_at, updated_at) · the row is an index entry, the file is the record - edges(from_feature, to_feature, kind) · depends_on or splits_into, drawn on the map and used to order tasks - specs(feature_id, draft_path, approved_path, model_id, prompt_version, generated_at, approved_at, approved_by) - tasks(id, feature_id, title, acceptance, expected_files_json, status, branch, commit_sha, closed_at) - runs(id, feature_id, model_id, input_tokens, output_tokens, cost_minor, at) · every model call, so the month has a number attached to it - staleness(feature_id, checked_at, referenced_paths_json, repo_changed_at) · which approved plans describe code that has since moved - Nothing here is authoritative. Every row points at a file git already tracks, so deleting the database and reindexing loses precisely nothing. ### Phase 1 · The repository is the record Build: Point the tool at a git working tree. Each feature is a markdown file with frontmatter holding a stable id, title, status and map position, under a directory you choose. Index those files into SQLite on start and on change, and provide a reindex command that rebuilds from scratch. Trap: Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. Done when: Deleting the database and reindexing reproduces the same feature list and edges exactly, tested. A feature id survives a title change and a file rename, tested by renaming both. A feature edited in an external editor shows up without restarting the tool. The tool refuses to run against a directory that is not a git working tree and says why. Do not build yet: No map, no generation, no tasks, no agent export yet. ### Phase 2 · A map you can read without the tool Build: A canvas listing features as nodes with drag positioning, keyboard creation and arrow keys for movement, and edges typed as depends_on or splits_into. Write positions and edges back into the frontmatter of the feature files. Support a plain list view that does everything the canvas does. Trap: Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. Done when: Positions and edges survive a round trip through the files with no canvas-specific document anywhere, checked by reading a feature file by hand. A dependency cycle is detected and reported rather than stored silently. Every canvas action has a keyboard equivalent and the list view can create, connect and reorder without the canvas. A merge conflict in one feature file leaves the rest of the map loadable. Do not build yet: No specification generation and no tasks yet. ### Phase 3 · A draft is not a specification Build: One model call per feature turning the notes and the incoming edges into a structured draft: problem, scope, explicitly out of scope, acceptance criteria, open questions. Write it to a draft path. Show a diff against the approved version. Approval copies the draft over and records the model identifier, the prompt version and the time. Trap: Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. Done when: A generation never writes to an approved path, asserted in the suite. A failed or malformed model response leaves both the draft and the approved file untouched, tested with a stub returning prose. Every approved spec records the model identifier, prompt version and approval time. The draft view shows a line diff against the approved version before approval is possible. Do not build yet: No tasks, no agent export, no cost tracking yet. ### Phase 4 · Tasks that point at code Build: Derive tasks from approved specs, one per acceptance criterion, each with the files it expects to touch. Order them by the dependency edges. Read status from git: a branch named after the task id means in progress, a commit on the default branch mentioning the id means done. Manual status is allowed but is marked as manual wherever it appears. Trap: A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. Done when: Task status derived from a branch or a commit is recomputed on demand and matches a repository fixture, tested. A manually set status is visibly labelled as manual everywhere it is displayed. Regenerating tasks for a spec preserves the status and history of tasks whose text has not changed, tested. Deleting a feature never orphans a task silently; it reports what would be lost first. Do not build yet: No agent export, cost ceiling or staleness report yet. ### Phase 5 · Handing it over, and knowing what it cost Build: Write an AGENTS.md at the repository root, and for a monorepo one per package directory, since the published convention is that the closest file to the edited file wins. Emit approved specs and open tasks as plain markdown beside the code and commit them. Track token spend per run against a monthly ceiling. Report which approved plans reference paths that have changed since approval. Trap: Exporting a zip of planning documents into a folder the agent has never been told to read means the agent never reads it, and you conclude the model ignores your plan. Write to the conventional path at the repository root, check it into git, and confirm by asking the agent to quote a line back to you. Done when: Running the export produces an AGENTS.md at the repository root and nested files for each package directory in a monorepo fixture, tested. The exported markdown contains no tool-specific syntax and is readable on its own, checked by review. Reaching the monthly token ceiling stops generation with a clear message and leaves everything else working, tested. The staleness report lists every approved spec whose referenced paths changed after its approval time, tested against a fixture. Do not build yet: Nothing after this. ### Out of scope (and why) - Running the coding agent for you, which turns a planning tool into an orchestrator and a different, much larger project. - A hosted board with collaborators, which needs accounts, permissions and conflict handling for a tool one person uses on one repository. - Semantic search over documentation, which is an index to build and maintain for a payoff a grep over the repository mostly already gives you. - A protocol server exposing the plan to agents, which is worth adding only after the plain files have proved the agent reads them. ### README must contain - That the markdown files in the repository are the record and the database is a disposable index, with the reindex command written out - That the export writes an agent instruction file at the repository root, and nested files in subdirectories where the convention is that the closest one wins - That a generated specification is a draft until a person approves it, and that approvals are recorded with the model and prompt version - That task status is read from branches and commits, and that any manually set status is labelled as such - Where the token spend is recorded, what the monthly ceiling is, and what stops when it is reached
# Agent instructions · CodeSpring indie build - Read `README.md` and `BUILD_PLAN.md` before writing code. The stack is fixed: A local Node and TypeScript application with a small web interface, no accounts, Markdown files with frontmatter inside the target git repository, SQLite, rebuilt from the files on demand, One model call per feature, structured output, written to a draft path, Read from git branches and commit messages, not from dragging cards. Do not substitute. - Work one phase at a time, in order. Do not start a phase until every "Done when" item of the previous one passes. - Prefer the fewest moving parts that satisfy the step. No frameworks, services or dependencies the plan does not name. - Secrets live in `.env`, never in source or logs. Keep `.env.example` current when a variable is introduced. - Do not invent cryptography, security guarantees, APIs or compliance claims. - Add a focused test for every destructive, security-sensitive or data-loss path the plan names. - Run the project checks before declaring a phase complete, and record any deliberate shortcut in the README under "Tradeoffs". ## Known traps - Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. - Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. - Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. - A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact.
# Build plan · CodeSpring A local planning tool whose hard problems are keeping the plan in the repository rather than in a database the agent cannot see, stopping a generated draft from being mistaken for an approved specification, and noticing when a plan has gone stale against the code it describes. Phases are in dependency order. Each ends in a "Done when" list; treat an unticked item as a blocker, not a note. ## Phase 1 · The repository is the record Every feature is a markdown file inside the target repository and the database is only an index of them. ### Steps 1. Fix the on-disk layout before writing any interface The directory, the file name and the frontmatter keys are the contract everything else depends on. Files: `docs/file-format.md`, `src/store/files.ts` 2. Index into SQLite and rebuild on command Prove the index is disposable by disposing of it in a test. Files: `src/store/index.ts`, `tests/reindex.test.ts` ```sh npm run reindex ``` 3. Give every feature an id that survives a rename Titles change constantly and every link into the plan must survive it. Files: `src/store/ids.ts` ### Done when - [ ] Reindexing from empty reproduces the same state - [ ] Ids survive a title change and a file rename - [ ] External edits appear without a restart - [ ] A non-git directory is refused with an explanation ### Watch out - Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. ## Phase 2 · A map you can read without the tool Features and their dependencies can be arranged quickly, and the arrangement lives in the feature files. ### Steps 1. Store coordinates and edges in frontmatter Two numbers a human can read beat a proprietary diagram document. Files: `src/map/persist.ts` 2. Detect dependency cycles on write A cycle is a planning mistake, and it should be caught where it was made. Files: `src/map/graph.ts`, `tests/graph.test.ts` 3. Keep a list view that is not a fallback Most of this work is faster with a keyboard than with a mouse. Files: `src/app/list/page.tsx` ### Done when - [ ] The map round-trips through readable frontmatter - [ ] Cycles are reported rather than stored - [ ] Every canvas action has a keyboard equivalent - [ ] One broken file does not break the whole map ### Watch out - Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. ## Phase 3 · A draft is not a specification Generation produces a draft at a separate path that a person has to approve before anything downstream reads it. ### Steps 1. Generate to a draft path, never over an approval The approved file is the one containing corrections somebody made by hand. Files: `src/generate/spec.ts` 2. Diff before approving, and record the approval Approval is the only moment a human is definitely in the loop. Files: `src/app/spec/[id]/page.tsx`, `src/store/specs.ts` 3. Store the model identifier and prompt version Six weeks later you will want to know which prompt produced a strange section. Files: `src/store/specs.ts`, `tests/spec-approval.test.ts` ### Done when - [ ] Generation never overwrites an approved file - [ ] A malformed response changes nothing on disk - [ ] Approvals record model, prompt version and time - [ ] A diff is shown before approval is possible ### Watch out - Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. ## Phase 4 · Tasks that point at code Each task carries acceptance criteria and expected files, and its status is read from the repository rather than asserted. ### Steps 1. Derive one task per acceptance criterion A task without a falsifiable criterion is a note, not a task. Files: `src/tasks/derive.ts` 2. Read status from branches and commits Git already holds the answer and does not forget. Files: `src/tasks/status.ts`, `tests/status.test.ts` ```sh git log --oneline --grep=TASK- ``` 3. Preserve task identity across regeneration Otherwise every regeneration resets the board. Files: `src/tasks/derive.ts` ### Done when - [ ] Derived status matches a repository fixture - [ ] Manual status is labelled as manual - [ ] Regeneration preserves unchanged tasks - [ ] Deleting a feature reports what it would orphan ### Watch out - A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. ## Not in this build - Running the coding agent for you. - A hosted board with collaborators. - Semantic search over documentation. - A protocol server exposing the plan. ## After v1, if you want it - A per-task context bundle that lists only the files that task expects to touch - A weekly diff of the plan against the repository, mailed to yourself, so staleness is noticed rather than discovered - Estimates recorded at approval time and compared with what the work actually took
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. The git working tree holding the plan. The tool refuses anything that is not one. REPO_PATH=/home/you/code/your-project # Required. Directory inside the repository for feature files, drafts and approved specs. PLAN_DIR=docs/plan # Required. The SQLite index. Deletable at any time; reindex rebuilds it. INDEX_PATH=./.cache/plan-index.db # Required · secret. The generation model. Set a provider-side spend limit as well. MODEL_API_KEY=sk-...redacted # Required. Recorded with every draft, because a different model writes a different specification. MODEL_ID=a text model identifier # Required. Generation stops here for the month. Everything else keeps working. MONTHLY_TOKEN_CEILING=2000000 # Required. Used to match branches and commit messages back to tasks. TASK_ID_PREFIX=TASK-
# CodeSpring · product brief ## Problem The core loop, a mind map that turns feature notes into PRDs and kanban tasks fed to a coding agent, is just structured prompting and file generation, well within reach of a one-shot build. What's missing is the polish: the visual mind-map canvas, MCP/CLI integrations with Claude Code, Cursor and Codex, and the docs search. A DIY version gets you most of the value but with a rougher UI and manual glue between the planning docs and your agent of choice. ## Product outcome A planning tool whose output is ordinary markdown in your repository: drafts that a person approved, tasks whose status git already knows, agent instruction files at the conventional paths, and a report of which plans no longer match the code. ## Target user A builder who needs a maintainable product foundation, not a one-off demo. ## Required capabilities - OpenAI/Anthropic API key ## Explicit non-goals for v1 - Running the coding agent for you. - A hosted board with collaborators. - Semantic search over documentation. - A protocol server exposing the plan. - polished drag-and-drop mind-map canvas - MCP server integration with Cursor/Claude Code/Codex - semantic docs search - hosted kanban sync across devices - prebuilt skills library ## Success criteria - Deleting the index and reindexing is confirmed to reproduce the same state - Generation is confirmed never to write to an approved path - Export is confirmed to write root and nested agent files in a monorepo fixture - Derived task status is confirmed to match a repository fixture - The monthly token ceiling is confirmed to stop generation and nothing else
# Build brief · CodeSpring The one-shot brief this plan expands. `BUILD_PLAN.md` (or `MILESTONES.md`) is the same sequence broken into steps and checks; where the two disagree, the plan wins. Build me a planning workspace that turns a map of features into specification files your coding agent reads out of the repository to replace CodeSpring. Build it in phases, in the order below. Do not write the whole thing in one pass. Finish a phase, run its "Done when" check, fix what fails, and only then start the next phase. ### Stack (fixed, do not substitute) - Runtime: A local Node and TypeScript application with a small web interface, no accounts · one person planning one repository does not need a server or a login - Source of truth: Markdown files with frontmatter inside the target git repository · the coding agent reads files, so the plan has to be files, and git already versions them - Index: SQLite, rebuilt from the files on demand · a cache you can delete is a cache that cannot silently rot - Generation: One model call per feature, structured output, written to a draft path · a draft that lands on top of an approved spec destroys the only edits that were correct - Status: Read from git branches and commit messages, not from dragging cards · a board moved by hand starts lying about what is finished within a week ### Data model (create this before Phase 1) - features(id, slug, title, status, parent_id, map_x, map_y, file_path, created_at, updated_at) · the row is an index entry, the file is the record - edges(from_feature, to_feature, kind) · depends_on or splits_into, drawn on the map and used to order tasks - specs(feature_id, draft_path, approved_path, model_id, prompt_version, generated_at, approved_at, approved_by) - tasks(id, feature_id, title, acceptance, expected_files_json, status, branch, commit_sha, closed_at) - runs(id, feature_id, model_id, input_tokens, output_tokens, cost_minor, at) · every model call, so the month has a number attached to it - staleness(feature_id, checked_at, referenced_paths_json, repo_changed_at) · which approved plans describe code that has since moved - Nothing here is authoritative. Every row points at a file git already tracks, so deleting the database and reindexing loses precisely nothing. ### Phase 1 · The repository is the record Build: Point the tool at a git working tree. Each feature is a markdown file with frontmatter holding a stable id, title, status and map position, under a directory you choose. Index those files into SQLite on start and on change, and provide a reindex command that rebuilds from scratch. Trap: Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. Done when: Deleting the database and reindexing reproduces the same feature list and edges exactly, tested. A feature id survives a title change and a file rename, tested by renaming both. A feature edited in an external editor shows up without restarting the tool. The tool refuses to run against a directory that is not a git working tree and says why. Do not build yet: No map, no generation, no tasks, no agent export yet. ### Phase 2 · A map you can read without the tool Build: A canvas listing features as nodes with drag positioning, keyboard creation and arrow keys for movement, and edges typed as depends_on or splits_into. Write positions and edges back into the frontmatter of the feature files. Support a plain list view that does everything the canvas does. Trap: Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. Done when: Positions and edges survive a round trip through the files with no canvas-specific document anywhere, checked by reading a feature file by hand. A dependency cycle is detected and reported rather than stored silently. Every canvas action has a keyboard equivalent and the list view can create, connect and reorder without the canvas. A merge conflict in one feature file leaves the rest of the map loadable. Do not build yet: No specification generation and no tasks yet. ### Phase 3 · A draft is not a specification Build: One model call per feature turning the notes and the incoming edges into a structured draft: problem, scope, explicitly out of scope, acceptance criteria, open questions. Write it to a draft path. Show a diff against the approved version. Approval copies the draft over and records the model identifier, the prompt version and the time. Trap: Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. Done when: A generation never writes to an approved path, asserted in the suite. A failed or malformed model response leaves both the draft and the approved file untouched, tested with a stub returning prose. Every approved spec records the model identifier, prompt version and approval time. The draft view shows a line diff against the approved version before approval is possible. Do not build yet: No tasks, no agent export, no cost tracking yet. ### Phase 4 · Tasks that point at code Build: Derive tasks from approved specs, one per acceptance criterion, each with the files it expects to touch. Order them by the dependency edges. Read status from git: a branch named after the task id means in progress, a commit on the default branch mentioning the id means done. Manual status is allowed but is marked as manual wherever it appears. Trap: A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. Done when: Task status derived from a branch or a commit is recomputed on demand and matches a repository fixture, tested. A manually set status is visibly labelled as manual everywhere it is displayed. Regenerating tasks for a spec preserves the status and history of tasks whose text has not changed, tested. Deleting a feature never orphans a task silently; it reports what would be lost first. Do not build yet: No agent export, cost ceiling or staleness report yet. ### Phase 5 · Handing it over, and knowing what it cost Build: Write an AGENTS.md at the repository root, and for a monorepo one per package directory, since the published convention is that the closest file to the edited file wins. Emit approved specs and open tasks as plain markdown beside the code and commit them. Track token spend per run against a monthly ceiling. Report which approved plans reference paths that have changed since approval. Trap: Exporting a zip of planning documents into a folder the agent has never been told to read means the agent never reads it, and you conclude the model ignores your plan. Write to the conventional path at the repository root, check it into git, and confirm by asking the agent to quote a line back to you. Done when: Running the export produces an AGENTS.md at the repository root and nested files for each package directory in a monorepo fixture, tested. The exported markdown contains no tool-specific syntax and is readable on its own, checked by review. Reaching the monthly token ceiling stops generation with a clear message and leaves everything else working, tested. The staleness report lists every approved spec whose referenced paths changed after its approval time, tested against a fixture. Do not build yet: Nothing after this. ### Out of scope (and why) - Running the coding agent for you, which turns a planning tool into an orchestrator and a different, much larger project. - A hosted board with collaborators, which needs accounts, permissions and conflict handling for a tool one person uses on one repository. - Semantic search over documentation, which is an index to build and maintain for a payoff a grep over the repository mostly already gives you. - A protocol server exposing the plan to agents, which is worth adding only after the plain files have proved the agent reads them. ### README must contain - That the markdown files in the repository are the record and the database is a disposable index, with the reindex command written out - That the export writes an agent instruction file at the repository root, and nested files in subdirectories where the convention is that the closest one wins - That a generated specification is a draft until a person approves it, and that approvals are recorded with the model and prompt version - That task status is read from branches and commits, and that any manually set status is labelled as such - Where the token spend is recorded, what the monthly ceiling is, and what stops when it is reached
# Architecture · CodeSpring ## Stack | Part | Choice | Why | | --- | --- | --- | | Runtime | A local Node and TypeScript application with a small web interface, no accounts | one person planning one repository does not need a server or a login | | Source of truth | Markdown files with frontmatter inside the target git repository | the coding agent reads files, so the plan has to be files, and git already versions them | | Index | SQLite, rebuilt from the files on demand | a cache you can delete is a cache that cannot silently rot | | Generation | One model call per feature, structured output, written to a draft path | a draft that lands on top of an approved spec destroys the only edits that were correct | | Status | Read from git branches and commit messages, not from dragging cards | a board moved by hand starts lying about what is finished within a week | ## Modules Each module has one owner concern and a documented way to replace it. | Module | Owns | How to replace it | | --- | --- | --- | | Files | Feature, draft and approved files plus frontmatter. | Any on-disk layout, provided it is documented and readable without the tool. | | Index | SQLite index rebuilt from files. | Any store, provided deleting it and reindexing loses nothing. | | Generation | One model call, structured draft output. | Any provider, provided a failure never touches an approved file. | | Tasks | Derivation, ordering and git-derived status. | Any tracker, provided derived status stays distinguishable from a typed one. | | Export | Agent instruction files and the staleness report. | Any format, provided it lands where the agent already looks. | ## Configuration Every runtime setting is an environment variable documented in `.env.example`, validated at startup, with a safe local default wherever one exists. - `REPO_PATH` · required · The git working tree holding the plan. The tool refuses anything that is not one. - `PLAN_DIR` · required · Directory inside the repository for feature files, drafts and approved specs. - `INDEX_PATH` · required · The SQLite index. Deletable at any time; reindex rebuilds it. - `MODEL_API_KEY` · required, secret · The generation model. Set a provider-side spend limit as well. - `MODEL_ID` · required · Recorded with every draft, because a different model writes a different specification. - `MONTHLY_TOKEN_CEILING` · required · Generation stops here for the month. Everything else keeps working. - `TASK_ID_PREFIX` · required · Used to match branches and commit messages back to tasks. ## Production baseline - Security: least privilege, input validation at every boundary, secret redaction in logs, rate limits on abuse-prone paths, no invented security primitives. - Data: explicit schema and migrations, transactional writes where integrity matters, backup and restore procedures that have been exercised. - Integrations: adapters around third-party providers, idempotent webhook or job processing, bounded retries, timeouts. - Observability: structured logs with request or operation ids, an error-tracking hook, and health and readiness checks where a server exists. - Quality: unit tests for domain rules, integration tests at module boundaries, one end-to-end test of the critical path. ## Decision records For each dependency in the stack table, keep a short note: why it was chosen, its failure mode, and how it is replaced. Do not add infrastructure until a requirement in `PRODUCT.md` justifies it.
# Agent instructions · CodeSpring product build - Read `PRODUCT.md` and `ARCHITECTURE.md` before changing code. The stack is fixed: A local Node and TypeScript application with a small web interface, no accounts, Markdown files with frontmatter inside the target git repository, SQLite, rebuilt from the files on demand, One model call per feature, structured output, written to a draft path, Read from git branches and commit messages, not from dragging cards. - Implement milestone by milestone from `MILESTONES.md`; keep each change reviewable and leave the application runnable at every commit. - Treat authentication, payments, encryption, imports, webhooks and destructive actions as high-risk boundaries when present. - Never invent cryptography or silently weaken a requirement to make a check pass. - Put every external service behind an interface with a deterministic fake for tests. - Add migrations and rollback or recovery notes for every persistent data change. - Log useful operational context without credentials, tokens, passwords or personal data. - Update documentation and run every check before completing a milestone. ## Known traps - Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. - Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. - Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. - A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. - Exporting a zip of planning documents into a folder the agent has never been told to read means the agent never reads it, and you conclude the model ignores your plan. Write to the conventional path at the repository root, check it into git, and confirm by asking the agent to quote a line back to you.
# Delivery milestones · CodeSpring Estimated effort: **multi-day** for the indie phases; the production-only milestones add the trust and operability layer. ## M1 · The repository is the record Every feature is a markdown file inside the target repository and the database is only an index of them. ### Steps 1. Fix the on-disk layout before writing any interface The directory, the file name and the frontmatter keys are the contract everything else depends on. Files: `docs/file-format.md`, `src/store/files.ts` 2. Index into SQLite and rebuild on command Prove the index is disposable by disposing of it in a test. Files: `src/store/index.ts`, `tests/reindex.test.ts` ```sh npm run reindex ``` 3. Give every feature an id that survives a rename Titles change constantly and every link into the plan must survive it. Files: `src/store/ids.ts` ### Done when - [ ] Reindexing from empty reproduces the same state - [ ] Ids survive a title change and a file rename - [ ] External edits appear without a restart - [ ] A non-git directory is refused with an explanation ### Watch out - Keeping the plan in SQLite and exporting it on demand gives you two copies that disagree inside a day, and the agent always reads the exported one, which is the stale one. Write the file first, index second, and treat the database as something you can delete at any moment without asking anybody. ## M2 · A map you can read without the tool Features and their dependencies can be arranged quickly, and the arrangement lives in the feature files. ### Steps 1. Store coordinates and edges in frontmatter Two numbers a human can read beat a proprietary diagram document. Files: `src/map/persist.ts` 2. Detect dependency cycles on write A cycle is a planning mistake, and it should be caught where it was made. Files: `src/map/graph.ts`, `tests/graph.test.ts` 3. Keep a list view that is not a fallback Most of this work is faster with a keyboard than with a mouse. Files: `src/app/list/page.tsx` ### Done when - [ ] The map round-trips through readable frontmatter - [ ] Cycles are reported rather than stored - [ ] Every canvas action has a keyboard equivalent - [ ] One broken file does not break the whole map ### Watch out - Handing layout to a diagram library that stores its own document format means the map is unreadable and unmergeable outside your tool, and the first git conflict on it is unresolvable by a human. Store coordinates as two numbers in frontmatter and keep the edges as ordinary lines in a file. ## M3 · A draft is not a specification Generation produces a draft at a separate path that a person has to approve before anything downstream reads it. ### Steps 1. Generate to a draft path, never over an approval The approved file is the one containing corrections somebody made by hand. Files: `src/generate/spec.ts` 2. Diff before approving, and record the approval Approval is the only moment a human is definitely in the loop. Files: `src/app/spec/[id]/page.tsx`, `src/store/specs.ts` 3. Store the model identifier and prompt version Six weeks later you will want to know which prompt produced a strange section. Files: `src/store/specs.ts`, `tests/spec-approval.test.ts` ### Done when - [ ] Generation never overwrites an approved file - [ ] A malformed response changes nothing on disk - [ ] Approvals record model, prompt version and time - [ ] A diff is shown before approval is possible ### Watch out - Regenerating straight over the approved file destroys the human edits, which are the only part of the document that was ever reliable, and you will not notice until the agent builds the wrong thing from a sentence you had already corrected. Generate to a draft path, diff, and make approval an explicit act that is recorded. ## M4 · Tasks that point at code Each task carries acceptance criteria and expected files, and its status is read from the repository rather than asserted. ### Steps 1. Derive one task per acceptance criterion A task without a falsifiable criterion is a note, not a task. Files: `src/tasks/derive.ts` 2. Read status from branches and commits Git already holds the answer and does not forget. Files: `src/tasks/status.ts`, `tests/status.test.ts` ```sh git log --oneline --grep=TASK- ``` 3. Preserve task identity across regeneration Otherwise every regeneration resets the board. Files: `src/tasks/derive.ts` ### Done when - [ ] Derived status matches a repository fixture - [ ] Manual status is labelled as manual - [ ] Regeneration preserves unchanged tasks - [ ] Deleting a feature reports what it would orphan ### Watch out - A board whose columns are only moved by hand drifts from reality in about a week, and then every planning session starts with reconciling cards nobody has touched since the work shipped. Read what git already knows, and label any status a human typed as a human's claim rather than a fact. ## M5 · Handing it over, and knowing what it cost (production only) The plan leaves as the conventional files an agent already looks for, with a spend ceiling and a staleness report. ### Steps 1. Write to the conventional agent file, nested where needed The closest file to the edited file is the one that wins. Files: `src/export/agents.ts`, `tests/export.test.ts` ```sh npm run export ``` 2. Cap the monthly spend and degrade to writing by hand A rented model with no ceiling is a surprise bill. Files: `src/generate/cost.ts` 3. Report plans whose code has moved under them A stale plan is more dangerous than no plan, because it is confident. Files: `src/staleness.ts` ### Done when - [ ] Export writes root and nested agent files - [ ] Exported markdown reads on its own - [ ] The token ceiling stops generation, not the tool - [ ] Stale plans are listed with what changed ### Watch out - Exporting a zip of planning documents into a folder the agent has never been told to read means the agent never reads it, and you conclude the model ignores your plan. Write to the conventional path at the repository root, check it into git, and confirm by asking the agent to quote a line back to you.
# Operations · CodeSpring ## Backup Git is the backup, which is the point of putting the plan there. Confirm the plan directory is committed and not in .gitignore, and back up nothing else. The index is disposable. ## Restore Clone the repository, run reindex, and confirm the feature count and edges match. If they do not, the file format documentation is wrong, not the index. Do a restore drill before the first real user, and write the date here when it passes. ## Monitoring Monthly token spend against the ceiling, the proportion of drafts approved without edits, and the size of the staleness list. Drafts approved untouched usually mean the approval step has become a habit rather than a review. ## Incident checklist The failure mode here is quiet: the agent builds from a plan that no longer matches the code. The staleness report and the recorded approval times are what let you find when the plan and the repository parted company. 1. Contain the issue without destroying evidence or user data. 2. Record the timeline and affected scope. 3. Rotate exposed secrets and revoke compromised sessions or credentials. 4. Restore from a verified backup when needed. 5. Document the root cause, the remediation and the regression test. ## Release gate - [ ] Deleting the index and reindexing is confirmed to reproduce the same state - [ ] Generation is confirmed never to write to an approved path - [ ] Export is confirmed to write root and nested agent files in a monorepo fixture - [ ] Derived task status is confirmed to match a repository fixture - [ ] The monthly token ceiling is confirmed to stop generation and nothing else ## Launch constraint Do not market omitted CodeSpring capabilities as implemented. The non-goals in `PRODUCT.md` remain user-visible limitations until they are deliberately delivered.
# Copy to .env and fill in. Never commit .env; this file documents it. # Required. The git working tree holding the plan. The tool refuses anything that is not one. REPO_PATH=/home/you/code/your-project # Required. Directory inside the repository for feature files, drafts and approved specs. PLAN_DIR=docs/plan # Required. The SQLite index. Deletable at any time; reindex rebuilds it. INDEX_PATH=./.cache/plan-index.db # Required · secret. The generation model. Set a provider-side spend limit as well. MODEL_API_KEY=sk-...redacted # Required. Recorded with every draft, because a different model writes a different specification. MODEL_ID=a text model identifier # Required. Generation stops here for the month. Everything else keeps working. MONTHLY_TOKEN_CEILING=2000000 # Required. Used to match branches and commit messages back to tasks. TASK_ID_PREFIX=TASK-
$ choose a build depth, inspect the files, then open the complete pack in your agent
Non-technical builders pay for the guided, visual workflow and the fact it already talks to Cursor, Claude Code and Codex out of the box, rather than assembling their own prompt templates and task tracker.
xpolished drag-and-drop mind-map canvas
xMCP server integration with Cursor/Claude Code/Codex
xsemantic docs search
xhosted kanban sync across devices
xprebuilt skills library
Don't feel like building it? These folks already made it free.
no votes, no pay-to-list · just what's real
Vibecode CodeSpring
Kinda. The core of CodeSpring is buildable in a weekend with the prompt on this page, but there are real gaps: polished drag-and-drop mind-map canvas, MCP server integration with Cursor/Claude Code/Codex. Read the honest list above before committing.
How much does CodeSpring cost?
CodeSpring costs about $53/month (Pro, checked 2026-08-10), which is $636 per year.
What do I lose by replacing CodeSpring?
Honestly: polished drag-and-drop mind-map canvas; MCP server integration with Cursor/Claude Code/Codex; semantic docs search; hosted kanban sync across devices; prebuilt skills library. If any of those are load-bearing for you, keep paying.
Is there an open-source alternative to CodeSpring?
Yes: AFFiNE (Whiteboard-plus-docs workspace you can use to map features and write specs by hand.) The prompt is for when you want it exactly your way.