@davidbalzan/groundwork
v0.4.0
Published
Groundwork — an installable AI development workflow (skills + doc methodology) you bolt onto any repo.
Maintainers
Readme
Groundwork
An installable AI development workflow you bolt onto any repo. It gives your AI assistant persistent project context, a phase-based process, and deterministic helper scripts — working identically across Claude Code, Cursor, and VS Code Copilot from a single source.
It's a small CLI that installs the workflow into any repo — new or existing — and re-syncs in place as it improves. (A bolt-on, not a template you fork.)
npm i -g @davidbalzan/groundwork
groundwork init # full workflow into the current repo
groundwork init . --minimal # just the core 6 skillsSource lives in the groundwork-kit monorepo (
packages/groundwork); the olddavidbalzan/groundworkremote is frozen.
One-time per machine (only if you use
/remember): point Groundwork at your central knowledge repo —groundwork knowledge link <path>(orexport GROUNDWORK_KNOWLEDGE=<path>in your shell profile). This is separate frominitand machine-local — it doesn't travel. See Cross-project knowledge.
Mental model
Groundwork is two separable pieces:
| | What it is | Where it lives |
| --- | --- | --- |
| The workflow | Skills + doc methodology + scripts | This repo — installed by groundwork init |
| The starter (optional) | A generic React/Hono monorepo to scaffold from | A separate starter repo; not required |
Repo shape: works anywhere, monorepos recommended. The Groundwork tool is a single flat npm package (no workspaces, no build, zero runtime deps) and installs into any repo — monorepo, single package, or split repos.
But in practice agents work noticeably better in a monorepo: one source tree to reason
over, shared types/contracts in one place, atomic cross-package changes, and — for swarms —
a single coordination bus and one worktree space. Split repos are supported, but you'd
run a coord-mcp bus per module, which adds coordination overhead and makes cross-repo
changes harder for agents to get right. So a monorepo isn't required, it's recommended —
which is why the methodology's apps/web + apps/api layout is the default shape.
Design principles
These emerged from real use and shape every decision:
- Harness-agnostic first. The value lives in portable markdown skills + a plain
node/npxCLI — not harness-specific glue like session-start hooks. So it behaves identically across Claude Code, Cursor, and parallel multi-agent / multi-harness runs. - Single source → generated. Anything that would otherwise be duplicated is generated
from one source: IDE mirrors from
SKILL.md,ARTIFACTS.mdfrom a manifest, versions fromSTACK_MAP. Drift is prevented by construction, not discipline. - Deterministic where the model is weak. Counting, version checks, and drift detection
run as scripts/CLI (
check-task,groundwork status,doctor) — not LLM guesswork. - Spec-first, minimal tests. Rigor lives in the docs/spec; tests are an opt-in tripwire, not a default (see methodology §4b — and its caveat for human handover).
The flow
┌─────────────────────────── one-time ───────────────────────────┐
groundwork init ──▶ │ /create-prd ──▶ /kickstart ──▶ /check-versions ──▶ /plan-phase 1 │
└──────────────────────────────────────────────────────┬──────────┘
│
┌──────────────────────────── per session / per stream ───────────────────┘
▼
/start-session ─▶ …code… ─▶ /check-task ─▶ /update-workstreams ─▶ /log-decision (progress: `groundwork status`)
▲
external coordinator ┘ (reads QUEUE, writes WORKSTREAMS + DONE)initdrops skills, IDE mirrors, docs, and scripts into the repo./create-prdis the first step — the single product-discovery interview (problem, users, goals, scope, requirements, high-level phases) →docs/PRD.md./kickstartconsumes the PRD to scaffold the project docs (tech stack, architecture, roadmap, phases, WORKSTREAMS, QUEUE/DONE) — it does not re-ask what the PRD already covered./check-versionspins the stack to latest stable soSTACK_MAP.mdstarts honest./plan-phase Nturns each phase into a checkbox task file and aQUEUE.mditem.- Work loop:
/start-sessionloads context;/check-taskmarks tasks done andgroundwork statusreports progress deterministically;/update-workstreamsrecords live parallel work;/log-decisioncaptures ADRs.
The skills
min = installed by --minimal · opt = optional (add with groundwork add <name>).
mode is how the VS Code mirror is generated: ask = read-only, edit = can modify files.
| Skill | min/opt | mode | What it does |
| ----- | ------- | ---- | ------------ |
| kickstart | min | edit | Scaffold all project docs from the PRD (tech stack, roadmap, phases, WORKSTREAMS, QUEUE/DONE) — no re-interview |
| next | min | ask | Flow coach — inspects project state and recommends the single best next step |
| plan-phase | min | edit | Turn a phase goal into a detailed task file + add it to QUEUE |
| start-session | min | ask | Load current context: active phase, recent decisions, next backlog item |
| check-task | min | edit | Mark a task done and recompute progress (uses a deterministic script) |
| update-workstreams | min | edit | Update WORKSTREAMS.md — live state of every parallel stream |
| create-prd | opt | edit | Guided 6-stage Product Requirements Document |
| domain-model | opt | edit | Build the ubiquitous-language glossary (CONTEXT.md) + bounded-context map |
| log-decision | opt | edit | Append an Architectural Decision Record to DECISIONS.md |
| check-versions | opt | edit | Audit dependencies vs latest stable; flag drift; refresh STACK_MAP.md |
| add-data-layer | opt | edit | Add an optional Drizzle + PostgreSQL data layer (DB is opt-in) |
| remember | opt | edit | Capture a cross-project lesson in the central git knowledge repo — quick note, or a formal ADR with --adr |
All twelve are authored once as SKILL.md; the Cursor and VS Code variants are
generated (see below).
Auto-execution
Every skill is agent-invocable by default — the assistant runs the right one on its
own when a skill's description matches the situation (e.g. it reaches for next when
you ask "what should I do now?"). You can still call any of them explicitly with
/<name>. None set disable-model-invocation, so nothing is locked to manual-only. The
quality of each description is what makes auto-selection accurate — keep them
action-oriented when you add skills.
What gets installed
your-repo/
├── .claude/skills/<name>/SKILL.md # canonical skills (Claude Code)
├── .cursor/commands/<name>.md # generated mirror (Cursor)
├── .vscode/prompts/<name>.prompt.md # generated mirror (VS Code Copilot)
└── docs/
├── GROUNDWORK_METHODOLOGY.md # the full methodology
├── STACK_MAP.md # single source of truth for versions
├── COMMANDS.md, _INDEX.md # command guide + Obsidian map of content
├── WORKSTREAMS.md # live parallel-work state
├── templates/ # doc templates /kickstart fills in
├── phases/ # phase structure + task templates
└── .groundwork/
├── VERSION # installed Groundwork version
└── scripts/ # deterministic helpers (below)Project-specific docs (TECH_STACK.md, PRODUCTION_ROADMAP.md, PHASE*_TASKS.md,
QUEUE.md, …) are generated by the skills, not by init.
Helper scripts (deterministic, not LLM-guessed)
Shipped to docs/.groundwork/scripts/ and preferred by the matching skills:
| Script | Backs | Does |
| ------ | ----- | ---- |
| check-task.mjs | /check-task | Flip a checkbox, recompute Overall Progress, print % |
| phase-status.mjs | groundwork status / on-demand | Count checkboxes per phase, render progress bars |
| check-versions.mjs | /check-versions | npm view each stack dep, report pinned vs latest, exit non-zero if behind |
Versions stay honest
Two mechanisms keep dependency versions from rotting:
- One source of truth — every version number lives only in
docs/STACK_MAP.md(pinned, latest-stable, and which files to touch when bumping). No other doc restates a version; they link to it. Drift becomes impossible by construction. - A check baked into bootstrap —
/kickstartruns/check-versions, which queries the registry and flags anything a major behind. Re-run it anytime; it updatesSTACK_MAP.mdand the audit date. Major bumps are recommended as their own workstream (branch + build/test verify), never inline with feature work.
Docs stay honest (doctor)
Living docs are only worth trusting if they can't quietly lie. groundwork doctor is a
deterministic, offline lint for doc↔reality drift:
- orphaned
[[wikilinks]](alias-aware — respects each note's frontmatteraliases:), - phases 100%-done in tasks but not marked complete,
- PRDs missing core sections, phase dirs with no tasks file,
- a stale
VERSIONmarker orSTACK_MAPaudit, - ADR tripwire — an Accepted ADR whose rejected alternative (its "Alternatives Considered"
rows) now appears as a dependency in any
package.jsonor as a top-level/workspace directory (react-native/expo/ios/after "PWA over native",bcryptafter "magic link over password", …). Either supersede the ADR or record a factadr-NNN-accepted-deviationinFACTS.mdto silence it. Field case: two ADRs silently reversed in one week and stayed Accepted for five months — the docs agents read every session were wrong.
It exits non-zero on issues, so it drops straight into a pre-commit hook or CI. It's the
enforcement third of a loop: the manifest keeps the doc list single-sourced,
update --docs refreshes the generic docs, and doctor flags what drifted.
Honest boundary: doctor catches structural / consistency drift, not whether prose
matches the running code — that still needs you or the agent (or the optional test tripwire).
The ADR tripwire is keyword-based (src/lib/adr-tripwire.mjs ALIASES maps alternative names
to package/dir tokens — extend it); it catches the reversal that shows up as a dependency or a
folder, not one that is pure code. Tokens that also appear in the ADR title / Decision / Context
(alias-expanded) are the accepted path and are not hits; generic project-wide paths (docs/,
templates/) are not hits.
Data layer is opt-in
The starter ships no database — it stays generic. When a feature actually needs
persistence, run /add-data-layer (Drizzle ORM + PostgreSQL by default; MySQL/SQLite
supported). It wires the client, schema, migrations, env, docker service, and scripts,
pins to latest stable, and records an ADR. Until then, nothing about a DB clutters the
project.
Cross-project knowledge
Lessons that outlive a single project live in a central git knowledge repo — one per user, not bundled with Groundwork. Set yours up once:
groundwork knowledge init # scaffold ~/groundwork-knowledge + save the path
# or point at an existing clone:
groundwork knowledge link ~/path/to/your-knowledge-repo
groundwork knowledge sync [--push] # pull latest from origin (and optionally push)
groundwork knowledge path # show what's resolvedSync behaviour: /remember pulls from origin before writing and
pushes after — so the log stays current across machines and the swarm, and you never
write onto stale state. Run groundwork knowledge sync yourself to freshen a clone (e.g.
when you start on a new machine — init installs the project workflow, it does not touch
your separate knowledge repo).
The location resolves per user, in order: $GROUNDWORK_KNOWLEDGE → the saved user
config (~/.config/groundwork/config.json) → otherwise the skills tell you to run the
setup above. There is no hardcoded/shared default — your ADRs go in your repo.
/rememberappends a dated note (notes/lessons.md), commits, pushes./remember --adrpromotes a lesson into a formal ADR (adr/NNNN-*.md) and updates the index — for decisions that are hard-to-reverse, surprising, and a real trade-off.
Both are tool-agnostic (git + markdown), so the swarm and any assistant share one log.
Project-specific decisions still go in that project's docs/DECISIONS.md via /log-decision.
Multi-agent seam (optional)
Groundwork runs solo out of the box — a one-row WORKSTREAMS.md, no coordinator. When
you want a swarm, it hands off via a file contract split by writer, without absorbing the orchestration:
QUEUE.md— the inbound queue./plan-phaseand you write it (and nobody else); one item per phase.WORKSTREAMS.md— the live state. The coordinator/workers (and/update-workstreams) write it as work proceeds.DONE.md— the completion log. The executor appends one line per completed item (its only write in the queue seam).
One-way dependency: the coordinator depends on Groundwork's seam, never the reverse —
Groundwork has no knowledge of any coordinator and works fully without one. The reference
implementation is coord-mcp, an MCP-based coordination server (harness-agnostic, same
principle as Groundwork) that's an optional layer on top. Any orchestrator honouring the two
files drops in just as well — rooms, worktrees, and messaging stay entirely outside Groundwork.
Supported harnesses
One init installs the same workflow into three AI coding harnesses, each in its native
location:
| Harness | Skills installed to | Format |
| ------- | ------------------- | ------ |
| Claude Code | .claude/skills/<name>/SKILL.md | canonical source (frontmatter + body) |
| Cursor | .cursor/commands/<name>.md | generated mirror (skill body, no frontmatter) |
| VS Code Copilot | .vscode/prompts/<name>.prompt.md | generated mirror (mode: ask/edit) |
The CLI itself is plain node/npx and the docs are portable markdown, so the workflow also
runs unchanged in any other agent or in parallel multi-agent / multi-harness setups — those
three are the harnesses with first-class generated skill mirrors.
How the IDE mirrors stay in sync
SKILL.md (Claude Code) is the only hand-edited source. init, update, and add regenerate:
- Cursor (
.cursor/commands/*.md) — the skill body, no frontmatter. - VS Code (
.vscode/prompts/*.prompt.md) —mode: askwhen the skill'sallowed-toolsare read-only (Read, Glob, Grep), elsemode: edit.
Both carry a GENERATED … do not edit by hand banner. Edit the skill, run
groundwork update, and all three harnesses move together.
Commands
| Command | Purpose |
| ------- | ------- |
| groundwork init [dir] | Install skills + IDE mirrors + docs + scripts (--minimal, --force) |
| groundwork update [dir] | Upgrade skills + mirrors + helper scripts in place (leaves your project docs alone). --all installs skills added upstream; --docs refreshes the generic reference docs (methodology, COMMANDS, _INDEX, ARTIFACTS) |
| groundwork artifacts [dir] | Regenerate docs/ARTIFACTS.md from the manifest |
| groundwork add <skill> [dir] | Add one optional skill and its mirrors |
| groundwork list [dir] | List skills with install state, minimal/optional, and mode |
| groundwork status [dir] | Live workstreams + next backlog item + phase progress |
| groundwork doctor [dir] | Flag doc↔reality drift: orphaned wikilinks, phases 100%-done but not marked, stale version marker / versions audit |
| groundwork knowledge <init\|link\|path> | Configure your per-user central ADR/lessons repo |
| groundwork help / version | Usage / version |
This repo's structure
src/cli.mjs # entry + command dispatch
src/commands/*.mjs # init · update · add · list · status · doctor · artifacts · knowledge
src/lib/*.mjs # skills (parse + mirror gen) · artifacts (manifest) · fs · paths · progress · config · log
payload/skills/ # the 12 canonical SKILL.md files (the single source)
payload/doc-templates/ # docs scaffold (methodology, STACK_MAP, templates, phases, WORKSTREAMS)
payload/scripts/ # project-side deterministic helpers
docs/DECISIONS.md # ADRs about Groundwork itself
MIGRATION_PLAN.md # how/why it became a bolt-onPlain Node ESM (>=20), zero runtime dependencies, no build step. To add a skill: drop
a SKILL.md in payload/skills/<name>/, then groundwork update any project to pull it.
License
MIT © David Balzan
