--- name: project-bootstrap version: 1.9.0 description: > Initializes or upgrades a project in the current folder: git, .gitignore, README.md, .wiki/ using Karpathy's method, .tasks/ for task tracking, CLAUDE.md with skill triggers. Creates remote Gitea repo and syncs projects-meta cache for greenfield projects. Use this skill when the user says "initialize project", "bootstrap", "setup project", "upgrade project", "add wiki", "add tasks", "start project", "set everything up", "create new project", or launches the agent in a new folder and wants a full setup. Trigger even if the user just says "let's start a project" or "set it all up". --- # Project Bootstrap Sets up a complete working environment for a monorepo project in one pass. Operates in three modes: **greenfield-full** (new project + remote create), **add-remote** (existing git without remote), and **upgrade** (existing project). --- ## Step 0 — Detect mode Check what already exists in the current directory: ```bash ls -la git rev-parse --git-dir 2>/dev/null && echo "git:yes" || echo "git:no" git remote get-url origin 2>/dev/null && echo "remote:yes" || echo "remote:no" ls -A 2>/dev/null | grep -q . && echo "empty:no" || echo "empty:yes" [ -d .wiki ] && echo "wiki:yes" || echo "wiki:no" [ -d .tasks ] && echo "tasks:yes" || echo "tasks:no" [ -f CLAUDE.md ] && echo "claude:yes" || echo "claude:no" [ -f README.md ] && echo "readme:yes" || echo "readme:no" ``` Determine mode: - **greenfield-full**: `git:no` + `empty:yes` — new project, will create remote - **add-remote**: `git:yes` + `remote:no` — existing git, offer to create remote - **upgrade**: otherwise — existing project, upgrade only Show the user a summary in one block — what was found, what will be created: ``` Mode: greenfield-full (new project + remote create) Found: (empty directory) Create: git .wiki .tasks CLAUDE.md .gitignore README.md remote ``` Ask one question: "Looks right? Shall we proceed?" — and wait for confirmation. **Create nothing before confirmation.** --- ## Step 1 — Git If git is not initialized: ```bash git init ``` If `.gitignore` does not exist — create from template `assets/.gitignore.template`. If it exists — leave it untouched. --- ## Step 1.5 — Remote create (greenfield-full / add-remote modes) Only in **greenfield-full** or **add-remote** mode. Skip for upgrade mode. ### Prerequisites Read `~/.config/projects-mcp/auth.toml` to get Gitea credentials: ```bash # POSIX (Linux/macOS/git-bash): source ~/.config/projects-mcp/auth.toml 2>/dev/null || true # Windows PowerShell: Get-Content ~/.config/projects-mcp/auth.toml | Select-String "base_url|token" ``` If auth file missing → stop and tell user: run `/setup-projects-meta` first. ### Validate project name Current folder name becomes the repo name. Must be: - **Latin only** — a-z, 0-9, hyphens - **kebab-case** — lowercase, hyphens between words - **Not a duplicate** — check via Gitea API ```bash PROJECT_NAME=$(basename "$PWD") # Validate: only latin alnum + hyphen, no leading/trailing hyphen echo "$PROJECT_NAME" | grep -qE '^[a-z0-9]+(-[a-z0-9]+)*$' || { echo "❌ Invalid project name: '$PROJECT_NAME'. Use latin kebab-case (e.g. 'my-project')." exit 1 } ``` ### Create repo via Gitea API ```bash # Extract base_url and token from auth.toml (POSIX): BASE_URL=$(grep "^base_url" ~/.config/projects-mcp/auth.toml | cut -d'"' -f2) TOKEN=$(grep "^token" ~/.config/projects-mcp/auth.toml | cut -d'"' -f2) # Create repo: curl -X POST "$BASE_URL/api/v1/user/repos?token=$TOKEN" \ -H "Content-Type: application/json" \ -d "{\"name\":\"$PROJECT_NAME\",\"private\":false,\"auto_init\":false}" ``` On failure → stop and show error. Duplicate name = suggest rename or delete existing. ### Add remote and push ```bash git remote add origin "$BASE_URL/$USER/$PROJECT_NAME.git" git branch -M master git push -u origin master ``` For **add-remote** mode (git exists, push local commits after adding remote): ```bash git push -u origin master # or main if that's the current branch ``` --- ## Step 2 — README.md If it does not exist — create a minimal one: ```markdown # ## About ## Quick start ``` If it exists — leave it untouched. --- ## Step 3 — .wiki/ **Delegate to the `setup-wiki` skill.** It handles greenfield creation, canon migration, and the no-op case (already canon) uniformly, with its own confirmation gate. Don't recreate the layout inline here — that's how drift happens. If `setup-wiki` is not installed on this machine, **stop** and tell the user: project-bootstrap requires `setup-wiki` (and `setup-tasks`) installed. Don't fall back to ad-hoc creation. **Reference (for context only — `setup-wiki` is the source of truth):** the canonical layout per Karpathy (gist: https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f) and `using-wiki`: ``` .wiki/ CLAUDE.md ← schema: project-specific wiki conventions index.md ← catalog of all pages (by type), updated on every ingest log.md ← append-only op log: ## [YYYY-MM-DD] op | desc overview.md ← single human-readable project overview raw/ README.md ← raw/ is immutable; this file documents that entities/ ← entity pages (people, services, modules) — empty .gitkeep concepts/ ← concept / design decision pages — empty .gitkeep packages/ ← package pages — empty .gitkeep sources/ ← one summary per ingested source — empty .gitkeep ``` Page-level workflow (ingest, query, lint) and file formats are owned by the `wiki-maintainer` skill. Bootstrap only lays the skeleton; the skill takes over from there. ### `.wiki/CLAUDE.md` (schema) ```markdown # Wiki Schema — Project-specific wiki conventions. Read this before any wiki operation. This wiki follows Karpathy's LLM Wiki pattern: **https://gist.github.com/karpathy/442a6bf555914893e9891c11519de94f** The `wiki-maintainer` skill enforces the workflow and file formats. This file overrides the skill where they conflict. ## Page types - `entities/` — discrete things the project tracks (people, services, modules). - `concepts/` — recurring ideas, design decisions, gotchas. - `packages/` — code packages this project produces or consumes. - `sources/` — one summary page per ingested external doc; frontmatter carries `ingested:` and `raw_path:`. - `overview.md` — single project-wide overview. ## Naming - `kebab-case.md`, **Latin only**. Transliterate Cyrillic in filenames; keep the original title in the H1 + frontmatter. ## Domain conventions ``` ### `.wiki/index.md` ```markdown # Wiki Index Catalog of all wiki pages. One line per page, organized by type. The agent updates this on every ingest. ## Overview - [overview.md](overview.md) — project overview ## Entities ## Concepts ## Packages ## Sources ``` ### `.wiki/log.md` ```markdown # Wiki Log Append-only operation log. One entry per operation. Format: \`\`\` ## [YYYY-MM-DD] | \`\`\` Operations: `init`, `ingest`, `query`, `lint`, `refactor`, `decision`. Parseable: `grep "^## \[" .wiki/log.md | tail -20`. --- ## [] init | bootstrap empty wiki via project-bootstrap ``` ### `.wiki/overview.md` ```markdown # — overview ``` ### `.wiki/raw/README.md` ```markdown # Raw Sources **Immutable.** Read, never edit. The only allowed modification is appending a `> Status:` blockquote when the user explicitly asks for a status audit. Place raw inputs here — articles, transcripts, PDFs, screenshots — exactly as they came in. The agent reads from `raw/`, writes summaries into `../sources/`, and never modifies raw files. For large or path-sensitive sources that live outside the repo, register them here: \`\`\` - short-name → /absolute/path/to/source \`\`\` ``` The empty subdirectories (`entities/`, `concepts/`, `packages/`, `sources/`) each get a `.gitkeep` so git tracks them. --- ## Step 4 — .tasks/ **Delegate to the `setup-tasks` skill.** It handles greenfield creation, migration from flat STATUS.md, and the no-op case uniformly, with its own confirmation gate. Don't recreate the layout inline. If `setup-tasks` is not installed, **stop** and tell the user — same rule as Step 3. **Reference (for context only — `setup-tasks` is the source of truth):** the canonical layout is `.tasks/STATUS.md` (the board, with emoji status 🔴/🟡/⚪/🟢/🔵) plus `.tasks/.md` per active or paused task. The full pattern is documented in this repo at `.wiki/raw/setup-task-status-wiki.md`. --- ## Step 5 — CLAUDE.md Two paths, picked by file presence: ### Init (file does not exist) Create `CLAUDE.md` from `assets/CLAUDE.md.template`. Substitute the platform line on non-Windows hosts (`we're on Linux` / `we're on macOS` instead of `we're on Windows`). ### Upgrade (file exists) — idempotent merge Treat the template as the canonical trigger set and reconcile the existing file against it. Re-runs are no-ops once the file is in canon. 1. Read the existing `CLAUDE.md`. 2. For each non-empty, non-comment line in the template, decide whether it's already present: - **Trigger lines** (everything except the platform line) — present iff any existing line, after `trim` + `tolower`, contains the template line's trigger text. Substring match, not equality — tolerates user rewording or trailing punctuation. - **Platform line** (`we're on Windows`) — present iff any existing line matches `we're on (windows|linux|macos)` case-insensitively. If the user pinned a different platform on purpose, **leave it alone**. Only append the host-appropriate platform line when none of the three is present. 3. Collect missing lines. If none → print `CLAUDE.md already canon — no changes` and skip to Step 5.5. 4. Show the user the diff (N lines, exact text to append) and ask one question: "Append these N missing canonical triggers to the end of CLAUDE.md?" Wait for explicit confirmation before writing. 5. On confirm: append a single newline (if the file doesn't end with one) and then the missing lines, one per line. Don't rewrite the file — only append. Don't reorder existing lines. Don't dedupe within the existing file. Template contents (`assets/CLAUDE.md.template` — source of truth): ```markdown # CLAUDE.md # Agent instructions. Each line is a trigger for an installed skill. talk like a caveman use superpowers use project wiki use task management system check across all projects pull remote before work follow project discipline delegate to interns when allowed we're on Windows ``` The `check across all projects` line activates the `using-projects-meta` skill so cross-project task aggregation and the shared `projects-wiki` are available without an explicit verbal trigger. The skill is a no-op until the `projects-meta-mcp` server is registered — install via `setup-projects-meta` on a fresh machine if `mcp__projects-meta__*` tools are missing. The `pull remote before work` line activates the `pulling-before-work` skill, which runs one `git pull --ff-only` at session start (and on explicit re-sync requests like "sync"). It's a no-op outside git repos and skips with a one-line warning if the working tree is dirty, HEAD is detached, or the branch has no upstream — never auto-merges, stashes, or pushes. Install the skill on the host if `pulling-before-work` is not in `~/.claude/skills/`; otherwise the trigger is silently dead like any other absent skill. The `follow project discipline` line activates the `project-discipline` skill, which codifies four cross-project rules: (1) project CLAUDE.md / .wiki/CLAUDE.md / .tasks/ override defaults from any other skill; (2) all work on master/main, no feature branches without explicit user approval; (3) version bump on every edit of versioned artifacts per semver, recorded in commit; (4) commit freely, push only after explicit per-session approval. Install the skill on the host if `project-discipline` is not in `~/.claude/skills/`; otherwise the trigger is silently dead like any other absent skill. The `delegate to interns when allowed` line activates the `using-interns` skill, which lets Claude offload predictable bulk I/O and summarization tasks (reading 3+ files, distilling long transcripts) to cheap intern LLMs via the local `interns` MCP server (`mcp__interns__bulk_text_read`, `mcp__interns__transcript_distill`, etc.) — saves Anthropic quota at ~125× the per-call cost reduction on bulk reads. Per-session permission grant mirrors `project-discipline` Rule 4: ask-mode default, conversational grant / revoke, always-ask paths for `.env` / secrets / keys / SSH credentials even with an active grant, session-end reset. The skill is a no-op until the `interns` MCP server is registered — install via `setup-interns` on a fresh machine if `mcp__interns__*` tools are missing. Full design at `.wiki/concepts/interns-design.md` in the `claude-skills` repo. The `we're on Windows` line activates the `active-platform` skill and pins the project's default platform to Windows / PowerShell — so generated commands and README quick-starts use PS-native syntax. Bootstrapping on a Linux or macOS host? Substitute `we're on Linux` or `we're on macOS` instead. --- ## Step 5.5 — Bootstrap manifest Write `.wiki/concepts/bootstrap-manifest.md`. The manifest records which skills (and at which versions) initialized this project's `.wiki/` and `.tasks/` layout, so layout drift between projects bootstrapped at different times is debuggable. Read each delegated skill's `SKILL.md` frontmatter to pick up the live `version:` value (don't hardcode): ```markdown --- title: Bootstrap Manifest type: concept updated: generator: project-bootstrap@ --- # Bootstrap Manifest Skills used to initialize this project's `.wiki/` and `.tasks/` layout, with their versions at install time. | Skill | Version | Role | |---|---|---| | `project-bootstrap` | | orchestrator | | `setup-wiki` | | wiki canonical layout | | `setup-tasks` | | tasks canonical layout | | `project-discipline` | | cross-project policy | | `setup-interns` | | interns MCP server install (one-time, per machine) | | `using-interns` | | interns runtime policy + per-session permission grant | This file is overwritten if `project-bootstrap` is re-run on the same project. For history, use `git log .wiki/concepts/bootstrap-manifest.md`. ``` If a delegated setup-skill is unavailable on this machine (e.g. user installed only a subset), record the missing skill as `unknown` in the version column so the gap is visible. --- ## Step 5.6 — Skill dependencies check (chat-only, never auto-install) The `CLAUDE.md` template just written contains canonical trigger lines. Each one is a no-op unless the corresponding skill or plugin is installed on the host. On a fresh machine these are often absent, and the user won't know the trigger is silently dead. Detect what's missing on this machine and print one informational block in chat — never write into any project file, never auto-install. ### Trigger → fulfiller map Source of truth for this map is the canonical `assets/CLAUDE.md.template`. When a new trigger is added there, also add a row here in the same commit. Mismatch between template and map → silent gaps in the recommendation. | Trigger line in `CLAUDE.md` | Fulfiller | Kind | Detection path | Install command | |---|---|---|---|---| | `talk like a caveman` | `caveman` | skill | `~/.claude/skills/caveman/SKILL.md` | `bash scripts/install.sh caveman` | | `use superpowers` | `superpowers@claude-plugins-official` | plugin | key `plugins["superpowers@claude-plugins-official"]` in `~/.claude/plugins/installed_plugins.json` | `/plugin install superpowers@claude-plugins-official` | | `use project wiki` | `using-wiki` | skill | `~/.claude/skills/using-wiki/SKILL.md` | `bash scripts/install.sh using-wiki` | | `use task management system` | `using-tasks` | skill | `~/.claude/skills/using-tasks/SKILL.md` | `bash scripts/install.sh using-tasks` | | `check across all projects` | `using-projects-meta` | skill | `~/.claude/skills/using-projects-meta/SKILL.md` | `bash scripts/install.sh using-projects-meta` | | `pull remote before work` | `pulling-before-work` | skill | `~/.claude/skills/pulling-before-work/SKILL.md` | `bash scripts/install.sh pulling-before-work` | | `follow project discipline` | `project-discipline` | skill | `~/.claude/skills/project-discipline/SKILL.md` | `bash scripts/install.sh project-discipline` | | `delegate to interns when allowed` | `using-interns` | skill | `~/.claude/skills/using-interns/SKILL.md` | `bash scripts/install.sh using-interns` | | `recommend, don't menu` | `recommend-dont-menu` | skill | `~/.claude/skills/recommend-dont-menu/SKILL.md` | `bash scripts/install.sh recommend-dont-menu` | | `we're on Windows` / `we're on Linux` / `we're on macOS` | `active-platform` | skill | `~/.claude/skills/active-platform/SKILL.md` | `bash scripts/install.sh active-platform` | ### Algorithm 1. Read the project's `CLAUDE.md` (just-written or pre-existing). Extract every non-empty, non-comment line — these are the active triggers for THIS project. The user may have removed canonical lines on purpose; respect that — only check what's actually in the file. 2. Match each line against the trigger column above using `trim` + `tolower` substring (same matching as Step 5 idempotent merge). Lines that don't match any row are user-custom — skip silently. The platform line matches the `active-platform` row regardless of which platform is pinned. 3. For each matched canonical line, check the detection path: - `kind: skill` → does `~/.claude/skills//SKILL.md` exist? - `kind: plugin` → does `~/.claude/plugins/installed_plugins.json` contain the plugin key under `plugins`? (Treat malformed JSON as "missing" and continue — don't crash the bootstrap over a detection edge case.) 4. Collect every fulfiller that's missing. Two outcomes: - **All present** — print one line: ``` ✅ all skill dependencies satisfied — every CLAUDE.md trigger has its fulfiller on this host. ``` Skip to Step 6. - **Some missing** — print one block in chat exactly once. Do **not** write it into any project file: ``` ℹ️ Recommended: install the following to fulfill CLAUDE.md triggers The triggers below are present in CLAUDE.md but their fulfillers are missing on this machine — they're silently no-ops until installed: trigger fulfiller (kind) () () … Install (run inside Claude Code or terminal): … After install + (for plugins) a Claude Code restart, the triggers pick them up. ``` ### Notes - **MCP-server-backed skills** (`using-context7`, `using-projects-meta`, `using-interns`) — only the `using-X` policy skill is checked here. If the MCP isn't registered, the `using-X` Prerequisites pointer fires `setup-X` at first use; bootstrap doesn't duplicate that detection. - The `~/.claude/skills/` and `~/.claude/plugins/` paths resolve identically on Windows / Linux / macOS — `~` works under git-bash too. - **Hard rule — never auto-install.** Slash commands aren't callable from a skill, and silently mutating user-level skill / plugin state without consent is overreach. The recommendation is informational. The user can install some / all / none of the recommendations, or remove canonical lines from `CLAUDE.md` to lean the project's trigger set down. ## Step 6 — Commit ```bash git add . git commit -m "chore: bootstrap project structure" ``` If the repo already had commits — commit only the files just created: ```bash git add .wiki/ .tasks/ CLAUDE.md .gitignore README.md git commit -m "chore: upgrade project structure" ``` --- ## Step 7 — Summary Print a final report: ``` ✅ Done! Created: .wiki/ — project wiki (Karpathy method) .tasks/ — task tracking system CLAUDE.md — skill triggers .gitignore — standard template README.md — starter file remote — Gitea repo created and pushed Skipped (already existed): git — left untouched Next step: describe the project in README.md and start your first task — say "use task management system". ``` For **greenfield-full** mode, append to summary: ``` Remote: ``` --- ## Step 8 — projects-meta sync (greenfield-full mode) Only in **greenfield-full** mode. Re-sync the projects-meta cache so the new project becomes visible to `mcp__projects-meta__*` tools. ```bash # POSIX: node ~/projects/.common/lib/projects-meta-mcp/dist/sync.js # Windows PowerShell: node ~/projects/.common/lib/projects-meta-mcp/dist/sync.js ``` Verify the project is now visible: ```bash # Via MCP (if available in current session): # mcp__projects-meta__meta_status # Or manually check the cache file exists: ls -la ~/projects/.common/lib/projects-meta-mcp/cache/projects.json ``` If the sync script doesn't exist → skip with informational message: ``` ℹ️ projects-meta sync script not found at ~/projects/.common/lib/projects-meta-mcp/dist/sync.js Run /setup-projects-meta to install it. The new repo is already created in Gitea. ``` --- ## Rules - **Never overwrite** existing files without explicit user confirmation - **Always show the plan first** — one question, one confirmation - **Never invent details** — if the project already exists, read what's there - **Commit only what was just created** — do not touch the rest of the file tree - **Commit automatically** after each successful step, no extra questions - **Push only after explicit user confirmation** — ask "Push to remote?" and wait for "yes"