with one click
setup
// Set up SDD/TDD development process for the current project. Creates CLAUDE.md, configures settings, and optionally creates spec files. Use when starting a new project or adding process to an existing one.
// Set up SDD/TDD development process for the current project. Creates CLAUDE.md, configures settings, and optionally creates spec files. Use when starting a new project or adding process to an existing one.
[HINT] Download the complete skill directory including SKILL.md and all related files
| name | setup |
| description | Set up SDD/TDD development process for the current project. Creates CLAUDE.md, configures settings, and optionally creates spec files. Use when starting a new project or adding process to an existing one. |
| disable-model-invocation | true |
| argument-hint | [new or existing] |
Set up the Spec-Driven Development and TDD workflow for this project.
FIRST ACTION (under non-interactive stdin) โ STE-251 AC-STE-251.1. When
process.stdin.isTTY === false(e.g.,claude -p), the first tool call this skill emits MUST beAskUserQuestiontool_useORRequiresInputRefusedErrorraise (viarequireOrRefuse(...)fromadapters/_shared/src/requires_input.ts).Write/Edit/NotebookEditare forbidden before that ask/refusal โ they produce silent scaffolding that bypasses the Socratic Loop Contract. Read-only orientation (Read/Grep/Glob/Bash-read-only) is allowed. Interactive (tty) sessions are byte-identical to v2.17.0 โ non-tty stdin only. Seedocs/auto-mode-protocol.md ยง Socratic Loop Contract.
Every step below is annotated as one of three kinds. The agent โ including non-interactive runs โ MUST honour the kind:
verification: โ runs unconditionally regardless of prompt mode (e.g., git status baseline check, linear list_teams MCP test call, bun --version). Failure โ loud abort with NFR-10 canonical shape per the "fail loud, don't silently skip" principle.default: <value> โ proceeds with the named value when no answer is supplied (autonomous mode or pre-baked answers). Every resolved outcome (user-supplied / pre-baked / default-applied / model-imputed) appends a ## /setup audit row to CLAUDE.md via appendAuditRow from adapters/_shared/src/setup/audit_log.ts โ provenance is recorded in the row's source: parameter and the derived imputed: column (STE-232 AC.4). The legacy appendAuditEntry wrapper is retained for callers still passing reason: directly.requires-input: <reason> โ refuses to proceed without an answer. The canonical helper requireOrRefuse(spec, key, sentinel) from adapters/_shared/src/requires_input.ts consolidates the four-outcome decision (user-supplied / pre-baked / default-applied / refused) and throws RequiresInputRefusedError (NFR-10 shape) when no answer is supplied. The auto-approve marker <dpt:auto-approve>v1</dpt:auto-approve> does NOT relax requires-input: โ it is informational for these gates. Full cross-skill contract: docs/auto-mode-protocol.md.Verification โ Q&A. The "do not prompt" instruction common in autonomous runs governs Q&A only. Verification calls always fire. The auto-approve marker (STE-226) is the byte-checkable pre-authorization signal for default:-annotated gates; it is read but never relaxes requires-input: โ see docs/auto-mode-protocol.md ยง The Rule.
The first action that writes to CLAUDE.md prepends the literal HTML comment:
<!-- generated by /dev-process-toolkit:setup -->
This marker lets gate-check probes (setup-audit-section-presence, toolkit-bootstrap-committed) distinguish toolkit-managed CLAUDE.md from hand-written ones without scanning every file's contents.
Before any detection or setup, run the Schema L probe (see docs/patterns.md ยง Tracker Mode Probe). If CLAUDE.md already exists and contains a ## Task Tracking section, this is an existing tracker-mode project โ /setup --migrate is the right entry point for changing modes. If CLAUDE.md is absent, empty of ## Task Tracking, or $ARGUMENTS contains new โ and $ARGUMENTS does not contain --migrate or --migrate-dry-run โ run the normal fresh-setup flow below. When --migrate is present, section 0b overrides this routing regardless of ## Task Tracking presence.
/setup --migrate / --migrate-dry-run)When $ARGUMENTS contains --migrate or --migrate-dry-run, skip steps 1โ8 and route into tracker-mode switching โ handles all transitions between modes. The CLI flag stays --migrate to preserve operator muscle memory. Current mode is detected via Schema L probe: absence of ## Task Tracking = mode: none (canonical form); presence = parse mode: <value>. All modes (including none) are valid starting states.
Detected current mode: <current>. Supported targets: <others>. Mode switch must change mode.none โ <tracker> / <tracker> โ none / <tracker> โ <other>. Unsupported = NFR-10 canonical refusal.mode: line + active-FR renames land in one commit; if the switch fails partway, the user reruns /setup --migrate from a clean working tree (no rollback prompt).specs/frs/*.md (not archive/) using the target-mode Provider.filenameFor(spec) and git mv each file to its new name. Archive is frozen by mode transitions. All renames + the CLAUDE.md mode: flip land in a single atomic commit.Detailed tracker-mode switching procedures live in docs/setup-tracker-mode.md.
Check for project files (package.json, pubspec.yaml, pyproject.toml, go.mod, Cargo.toml, etc.) and source directories.
If no project files are found (empty directory or only basic files), this is a new project โ go to step 2.
If project files exist, skip to step 3.
For existing projects (project files found in step 1), validate prerequisites before proceeding:
| Check | How | Remediation |
|---|---|---|
| Required tools installed | Run version commands using the per-stack declared invocation prefix (STE-209 AC-STE-209.5): when the rendered CLAUDE.md / examples/<stack>/gate-commands.md declares fvm flutter, the doctor probes fvm flutter --version (not bare flutter --version); same pattern for any wrapper (bun vs node, pnpm vs npm, etc.). Falls back to the bare command when no wrapper is declared. Examples: node -v, fvm flutter --version (when fvm is declared) or flutter --version, python3 --version. | Install the missing tool or update PATH |
| Gate commands runnable | Run the gating rule from CLAUDE.md (e.g., npm run typecheck && npm run lint && npm run test) | Fix failing commands or update CLAUDE.md gating rule |
| CLAUDE.md present | Check if CLAUDE.md exists in project root | Will be created in step 5 |
| .claude/settings.json present | Check if .claude/settings.json exists | Will be created in step 6 |
Spec anchor IDs (if specs/ exists) | Grep specs/plan/M*.md for every ## M{N}: and specs/requirements.md for every ### FR-{N}: heading; each must carry a matching {#M{N}} or {#FR-{N}} anchor | Add the missing {#M{N}} / {#FR-{N}} anchor. Missing anchors do NOT cause doctor failure โ they report under GATE PASSED WITH NOTES |
Report pass/fail for each check with remediation. Missing anchor IDs surface under GATE PASSED WITH NOTES, never as a hard failure.
For new projects, skip this step.
Ask the user what stack they want, then scaffold a working, gate-check-ready project. Every generated config must work out of the box โ no manual fixup required.
Before generating any config files, search the web for the current recommended setup for the chosen stack. Look for latest stable versions, current config file formats, recommended tsconfig/pyproject/pubspec settings, and known gotchas. Stale defaults degrade scaffolding.
Key requirements for every stack:
git init if not already in a git repository"type": "module" for Node)src/index.ts, src/__init__.py, main.go)passWithNoTests: true)init commands that generate broken defaultsStack-specific guidance:
npm init -y, set "type": "module", install typescript + vitest + eslint, create tsconfig.json (strict, ESM, src/dist dirs), vitest.config.ts, eslint config, src/index.ts, tests/ dir${CLAUDE_PLUGIN_ROOT}/examples/bun-typescript.md. Bun has no --passWithNoTests flag โ see step 2c branch + docs/setup-reference.md ยง Bun scaffold-verify branchflutter create ., add bloc_test + mocktail, verify test/ dir existsuv init or poetry init, add pytest + mypy + ruff, create src/init.py, tests/ dirgo mod init <module>, create main.go, install golangci-lintverification: Run the gate commands to verify they all pass. If anything fails, fix it immediately โ the project must be gate-check-ready before proceeding to step 3.
Bun-specific scaffold-verify branch writes a placeholder file before running the gate. See docs/setup-reference.md ยง Bun scaffold-verify branch for the placeholder location, marker comment, and layout-policy logic.
Load reference material from the plugin directory:
${CLAUDE_PLUGIN_ROOT}/templates/CLAUDE.md.template โ Base template${CLAUDE_PLUGIN_ROOT}/examples/ โ Stack-specific gate commands and patterns${CLAUDE_PLUGIN_ROOT}/docs/adaptation-guide.md โ Configuration referenceMatch the detected stack to the closest example. For other stacks, use the adaptation guide's gate command table.
Show the user what you'll create and ask for approval:
Create CLAUDE.md based on the template, filling in: project name and description, detected tech stack, actual directory structure, real gate commands, key patterns (infer from existing code, or leave as TODOs), testing conventions, DO NOT section with sensible defaults.
Important: Generate real content, not template placeholders. If you can detect the test framework, write it. If you can see the directory structure, document it.
verification: Write .claude/settings.json with the canonical permissions allow-list for the detected stack. Required, abort on failure.
${CLAUDE_PLUGIN_ROOT}/templates/permissions.json for the canonical allow-list keyed by stack (bun, node, flutter, python, generic).canonicalAllowList(template, stack) from adapters/_shared/src/setup/merge_settings.ts. Falls back to generic for unregistered stacks..claude/settings.json does NOT exist: write a fresh JSON with {"permissions": {"allow": <canonical>}}.mergeAllowList(existing, canonical), write back. Preserves user additions; never strips entries. Malformed pre-existing JSON โ abort with NFR-10 canonical shape.default: shell โ install the POSIX-shell Conventional-Commits hook (zero-dep). $ARGUMENTS contains --commitlint โ install the commitlint-delegating variant. Skip entirely when .git/hooks/ is absent (log setup: skipping commit-msg hook (not a git repo)).
The hook is a local-machine artifact (not tracked in git). commitlint.config.js, when written, IS in the bootstrap set โ step 8b appends it when --commitlint was used.
Best-effort under non-interactive runs. Hook install is best-effort โ the model-layer block on .git/hooks/ writes is expected under bypassPermissions and is logged in ## /setup audit rather than failing the run. The hook is per-clone, not part of the bootstrap set; a downstream user re-running /setup interactively (or running the manual fallback) closes the gap without re-bootstrapping. Manual fallback (run post-/setup when the audit shows setup: skipping commit-msg hook (model-layer block)): cp plugins/dev-process-toolkit/templates/git-hooks/commit-msg.sh .git/hooks/commit-msg && chmod +x .git/hooks/commit-msg.
Full procedure (idempotency tier, --commitlint extras, manual install command): docs/setup-reference.md ยง Step 6b โ commit-msg hook install.
verification: When tracker mode != none, write .mcp.json with the resolved adapter's mcpServers entry. Required, abort on failure โ the setup-output-completeness probe (gate-check #17) hard-fails when missing in tracker mode.
If .mcp.json already exists, merge โ don't overwrite.
Full procedure (rubber-duck offer, chrome-devtools-mcp for web projects): docs/setup-reference.md ยง Step 7 โ Configure MCP servers.
requires-input: tracker mode is a workspace-wide decision; no safe default exists.
Ask exactly once, near the end of the flow โ after CLAUDE.md is drafted but before it's written:
Task Tracking: where do ACs live?
1. none(ACs stay inspecs/requirements.md) /2. linear/3. jira/4. custom(copyadapters/_template). Enter 1โ4. No default โ autonomous runs MUST pre-bake an answer.
Auto Mode + first-run MCP (STE-199 AC.1..3 / AC.7..8 + STE-232 AC.3). Auto Mode does NOT relax requires-input. Step 7b's resolver returns --tracker=<mode>, an interactive answer, or a sentinel; the result is routed through requireOrRefuse(spec, "tracker_mode", SENTINEL) from adapters/_shared/src/requires_input.ts (per the cross-skill contract in docs/auto-mode-protocol.md). On the 'refused' outcome, the helper throws RequiresInputRefusedError carrying the canonical NFR-10 message "/setup step 7b requires an explicit answer for \"tracker_mode\"; tracker mode is a workspace-wide decision; no safe default exists. Auto Mode does not default-apply requires-input steps." + requires_input_refused row. --tracker=<mode> accepts none | linear | jira | <custom>. When the chosen tracker's MCP is not yet registered, take the first-run-deferral branch: write team: <deferred> / project: <deferred> to CLAUDE.md, audit via appendAuditRow(... source: "default-applied", reason: "<MCP> unregistered at /setup time; deferred to first downstream skill" ...) โ imputed: true is derived because the operator did not directly confirm the deferral โ and surface workspace_binding_deferred; operator runs /setup --resume-tracker-binding after authenticating to fill the binding. Full table: docs/setup-reference.md ยง Step 7b.
Schema L canonical-key constraint. When emitting the ## Task Tracking section, write only the canonical keys: mode, mcp_server, jira_ac_field, branch_template. Tracker-specific metadata (project IDs, team names) belong in a separate sub-section under ## Task Tracking (e.g., ### Linear) or in the adapter's own config โ not as Schema L keys at the top level. The task-tracking-canonical-keys probe (gate-check #21) hard-fails any non-canonical top-level key.
If the user picks 1 (or pre-baked answer is none), do NOT emit a ## Task Tracking section in CLAUDE.md โ absence is the canonical form for mode: none. Continue to step 7c.
If the user picks 2โ4, run the full numbered flow in docs/setup-reference.md ยง Step 7b โ Tracker mode (covers Bun prereq, MCP detection, test call, Jira field discovery, Schema L emit, and workspace binding). Background detail in docs/setup-tracker-mode.md.
Jira-specific prerequisite (mode: jira only): the operator must have created the Jira Space (project) in the Jira UI manually before running /setup โ the Atlassian MCP exposes no project-creation tool. After the operator supplies the project key, /setup validates visibility via mcp__atlassian__getVisibleJiraProjects and refuses with NFR-10 canonical shape on miss. AC-field discovery returning { ok: false } is also a first-class branch: the operator chooses between creating a custom field (records jira_ac_field: customfield_XXXXX) or accepting the description-body sentinel (records jira_ac_field: description); both choices are recorded under the existing canonical key โ no new Schema L key is added.
default: <default-for-mode> โ proceed with the mode-specific default if no answer is supplied. Every resolved branch_template value appends ## /setup audit entry recording step:7c value:"<resolved>" reason:"<user-supplied|default applied>" โ provenance per resolution, not per run.
Default-for-mode: {type}/m{N}-{slug} in mode: none; {type}/{ticket-id}-{slug} in any tracker mode.
/implement sanitizes LLM output at render time).branch_template: <value> in Schema L. mode: none projects that elected 1 in 7b: skip writing; branch automation stays disabled.branch_template:, do not re-ask.See docs/setup-tracker-mode.md ยง Branch template for the long-form prompt and placeholder substitution rules.
default: all-false โ when no answer is supplied (autonomous mode or skipped), the skill always emits the ## Docs section with all three flags false. Every resolved ## Docs flag appends ## /setup audit entry: step:7d (docs.<flag>) value:<bool> reason:"<user-supplied|default applied>" โ provenance per resolution.
Ask one at a time, in this order โ wait for each answer before asking the next (per docs/patterns.md ยง Pattern 26):
Generate user-facing docs (narrative + mermaid state/flow diagrams)?Generate packages-style API reference docs? โ body is stack-adaptive. TS-only project: (typedoc <detected|not found>, ts-morph <bundled>, stack: <ts|other>). Other stacks render their toolchain-probe results (Dart: dart-analyzer; Python: griffe).Is CHANGELOG.md generated by CI (if yes, /ship-milestone will not write it)?Accept y/n/yes/no case-insensitively; other inputs re-prompt with answer y or n. If both 1 and 2 are declined, refuse with NFR-10 shape and re-ask only those two; if declined again, still emit the section with all-false defaults (read-side readDocsConfig returns all-false for an absent section by design).
Write the section as Schema L (lowercase true/false, no quoting), placed immediately after ## Task Tracking. Re-runs are atomic โ splice the full block, write once.
Toolchain snapshot. When packages_mode == true, also write docs/.dpt-docs-toolchain.json recording per-stack preferred signature-extraction strategy. The signature-strategy-honors-setup probe (#24) reads this later for drift detection. docs_default_applied (STE-202 AC-STE-202.6): when the autonomous run applies the all-false default to all three flags (no pre-baked answers for any of user_facing_mode / packages_mode / changelog_ci_owned), surface a docs_default_applied row listing the defaulted flags. Interactive runs and mixed runs do NOT emit the row.
Full prompt list, NFR-10 refusal text, and section format: docs/setup-reference.md ยง Step 7d โ Docs modes. Background detail in docs/setup-docs-mode.md.
default: per-stack template โ emit a ## Release Files block in CLAUDE.md from examples/<stack>/release.yml (typescript-node / flutter-dart / python / plugin); unrecognized stack โ commented stub. Skip when CLAUDE.md already carries a ## Release Files heading โ user-edited overrides win on regenerate. Append immediately after ## Docs. Drives /ship-milestone's version bump; full schema in docs/ship-milestone-reference.md.
If the user wants the full SDD workflow (or $ARGUMENTS contains "new"):
specs/ plus specs/frs/, specs/frs/archive/, specs/plan/, specs/plan/archive/ (per-unit archival; no rolling index file).${CLAUDE_PLUGIN_ROOT}/templates/spec-templates/. Do not create or copy any archive-index.md โ archival is git mv + frontmatter flip.specs/plan/M1.md for the bootstrap milestone, add kind: scaffolding to the plan frontmatter and write a single FR row marked <scaffolding> (e.g. | <scaffolding> | Bootstrap (barrel + primary feature shipped pre-toolkit) | n/a |). Do not invoke Provider.sync for bootstrap FRs. Downstream skills route the marker through plan-only closure (STE-200). Never emit a literal <tracker-id> row in a committed bootstrap plan.Scaffold deliverables (canonical inventory, STE-189). /setup produces six artifact classes โ each a /setup deliverable, emitted unconditionally when its step runs: (1) CLAUDE.md (step 5), (2) .claude/settings.json (step 6), (3) .mcp.json (step 7, tracker mode only), (4) specs/{requirements,technical-spec,testing-spec}.md (step 8), (5) specs/plan/M1.md plus .gitkeep stubs in specs/frs/{,archive/} and specs/plan/{,archive/} (step 8), (6) src/.placeholder.test.ts (Bun, step 2c). These are emitted regardless of any phrasing in the operator's invocation context โ "only /setup completes here", "do not run /spec-write", "minimal mode" all constrain which downstream skills run after /setup, not which artifacts /setup itself produces (smoke #9 / run 2 F2). /spec-write step 1 ("Assess current state") expects these on disk; absence is a recovery-path failure mode, not the canonical contract. The scaffold list is non-negotiable; the operator can populate spec bodies later via /spec-write, but the empty templates ship from /setup.
verification: runs unconditionally before step 8b's bootstrap commit. Materialises the deterministic post-condition that every well-formed /setup run with at least one populated Schema L surface (branch_template: populated or ## Docs present) ships a ## /setup audit section โ provenance is preserved per resolution via the entry's reason: field, not gated on whether a default was applied.
hasDefaultApplicableOutcomes(content) from adapters/_shared/src/setup_audit_section_presence.ts โ single source of truth for the audit-required surfaces predicate (branch_template: populated or ## Docs present). Reused by /setup step 8a and /gate-check probe #19.branch_template: nor ## Docs).## /setup audit heading present โ no-op. Per-step appends already populated it.synthesizeAuditSection(claudeMdPath, resolvedSchemaLValues) from adapters/_shared/src/setup/synthesize_audit.ts. Pass the in-scope resolved Schema L values table populated during 7b/7c/7d โ every resolution lands here, user-supplied or default-applied. Never re-derive from CLAUDE.md. The helper is idempotent ((step, field) dedup).On AuditPostconditionUnsatisfiable (the resolved Schema L values table is empty but the file shows audit-required surfaces โ defensive invariant; unreachable on the canonical 7b/7c/7d โ 8a path), refuse with NFR-10 canonical shape and abort before 8b commits malformed output. Full refusal text + procedure: docs/setup-reference.md ยง Step 8a.
default: commit โ autonomous mode proceeds; interactive mode prompts. The bootstrap is mechanical and the diff is reviewable post-commit.
After all writes settle and step 8a's post-condition has run, /setup produces a single bootstrap commit so the canonical /setup output set lands at HEAD instead of leaking into the first feature PR.
Procedure: pre-flight git status --porcelain check, stage the canonical set (CLAUDE.md, settings.json, .mcp.json when written, specs files, .gitkeep stubs, plus commitlint.config.js when --commitlint was used), diff preview + prompt, commit (subject: chore: bootstrap dev-process-toolkit โ no parenthesized version suffix; the historic (v<plugin-version>) form referenced the project's bun init default rather than the toolkit version and was misleading), handle declines/edits/failures.
Toolkit version footer. Append a Toolkit: dev-process-toolkit v<plugin-version> line to the commit body after any existing footers (Refs:, etc.). Read <plugin-version> from plugins/dev-process-toolkit/.claude-plugin/plugin.json version field. The read is fault-tolerant / best-effort: if plugin.json is missing or unparseable, skip the footer entirely (footer absent rather than malformed v<unknown>) and emit a Step 7 advisory under setup_toolkit_version_unreadable. The bootstrap commit is load-bearing; the footer is not.
Full numbered procedure (decline + edit + failure paths): docs/setup-reference.md ยง Step 8b. Probes: toolkit-bootstrap-committed (#22, hard-fails on uncommitted toolkit-managed CLAUDE.md) + setup-bootstrap-commit-subject (#30, asserts subject + footer shape on the most recent chore: bootstrap dev-process-toolkit* commit; legacy-pre-FR-ship-date commits get a backwards-compat carve-out).
Run gate check commands to verify they all pass. If any fail, fix immediately โ don't report a broken setup.
If spec files were created, ask the user:
"Spec templates are ready. Want me to help you fill them in now? I can walk you through defining requirements, technical decisions, and the implementation plan. (Run
/dev-process-toolkit:spec-write)"
Subsequent /setup re-runs (e.g., flag changes) produce follow-up commits (chore: re-run /setup ...) โ not amendments. The bootstrap commit is canonical even if the user later refines flags.
If you skipped the bootstrap commit (n at step 8b), commit the staged files manually before running /spec-write so the first feature PR's diff is FR-scoped. Universal pre-commit branch gate (STE-228): before step 8b stages the bootstrap commit, call requireCommittableBranch({...}) from adapters/_shared/src/require_committable_branch.ts with the name from branchNameFor() at skills/setup/branch_name_for.ts (literal chore/setup-bootstrap); gate is git-only โ runs before CLAUDE.md exists; auto-mode default-apply via <dpt:auto-approve>v1</dpt:auto-approve> (STE-226).
Summarize what was created (list files created/modified), then present the SDD workflow.
Your SDD Workflow:
0. /brainstorm โ (Optional) Explore approaches before writing specs
1. /spec-write โ Fill in specs/*.md (requirements first, then technical, testing, plan)
2. /implement โ Builds features with TDD + three-stage self-review (the main entry point)
3. /gate-check โ Verify quality gates pass
4. /debug โ Investigate failing tests or unclear gate failures
5. /spec-review โ Audit implementation against specs
6. /simplify โ Clean up changed code
7. /pr โ Create pull request
Key principle: Specs are the source of truth. /implement reads specs to understand what to build, writes tests first, self-reviews against acceptance criteria, and reports for human approval before committing.
Workflow paths (Bugfix / Feature / Refactor) and the spec-fill-in checklist live in docs/setup-reference.md ยง Step 11. Surface them to the user when relevant.
plugins/dev-process-toolkit/docs/patterns.md ยง Pattern 26: Socratic Prompting {#pattern-socratic-prompting} for the canonical rule + rationalization-prevention table.AskUserQuestion tool call (closed-form options OR open-ended with the always-on "Other" free-form fallback), regardless of the autonomous-mode reminder, the auto-approve marker, or pre-baked <command-args> prose. Bare-prose Qs are forbidden. The first-turn contract additionally forbids Write / Edit / NotebookEdit tool calls before the first AskUserQuestion tool_use OR RequiresInputRefusedError raise; Read / Grep / Glob / Bash-read-only orientation is allowed. See docs/auto-mode-protocol.md ยง Socratic Loop Contract for the full contract. Audit row loop_entered: column โ appendAuditRow(...) accepts loopEntered: true when Steps 1โ6 emitted at least one AskUserQuestion clarifier, false otherwise; the column pairs with imputed: for two-axis loop visibility.