Collapse Step 5.6 from a single-skill detector (only the superpowers@claude-plugins-official plugin) into a generic `trigger -> fulfiller` table walker that scales to every canonical CLAUDE.md trigger. Inline 9-row map in SKILL.md covers: caveman, superpowers (kind: plugin), using-wiki, using-tasks, using-projects-meta, pulling-before-work, project-discipline, using-interns, active-platform. The `kind` flag (skill | plugin) drives which install command is emitted in the chat-only recommendation block. Detection paths: ~/.claude/skills/<name>/SKILL.md for skills, plugins.<id> in ~/.claude/plugins/installed_plugins.json for plugins. Algorithm: read project's CLAUDE.md -> match each non-comment line vs map (substring + tolower, mirrors Step 5 idempotent merge) -> for each canonical match check disk -> print one chat block listing every missing fulfiller with copy-pasteable install commands, OR a single "all dependencies satisfied" line. User-custom lines and removed canonical lines are silently skipped. Hard rule "never auto-install" preserved verbatim. version: 1.6.0 -> 1.7.0 (MINOR per project-discipline Rule 3 -- adds capability, absorbs prior superpowers-only detector cleanly). Closes [bootstrap-skill-deps-check] (.tasks/STATUS.md done). Closes [bootstrap-recommend-projects-meta] by absorption -- the deferred mirror task was the seed of this generalization; the generic walker now handles using-projects-meta along with everything else, no per-skill mirror needed. Design rationale at .wiki/concepts/bootstrap-skill-deps-check.md: - why generic over per-skill mirrors (5x mirror explosion) - skill vs plugin kind distinction - MCP-server-backed skills (only check using-X policy skill; setup-X self-fires via Prerequisites pointer) - source-of-truth invariant: SKILL map + assets/CLAUDE.md.template must stay in sync (a future CI lint could enforce)
6.9 KiB
title, type, updated
| title | type | updated |
|---|---|---|
| project-bootstrap@1.7.0 — generic skill-dependencies check (Step 5.6) | concept | 2026-05-05 |
project-bootstrap@1.7.0 — generic skill-dependencies check (Step 5.6)
2026-05-05.
Problem
Step 5.6 in project-bootstrap@1.6.0 detected exactly one missing fulfiller — the superpowers@claude-plugins-official plugin — and printed a recommendation if absent. The shape worked but doesn't scale.
The canonical CLAUDE.md template grew from 5 lines (1.0.0) to 9 lines (1.6.0) — every release added a new trigger:
| Release | Added trigger | Fulfiller |
|---|---|---|
| 1.1.0 | we're on Windows / Linux / macOS |
active-platform (skill) |
| 1.2.0 | check across all projects |
using-projects-meta (skill) |
| 1.4.0 | pull remote before work |
pulling-before-work (skill) |
| 1.5.0 | follow project discipline |
project-discipline (skill) |
| 1.6.0 | delegate to interns when allowed |
using-interns (skill) |
Each new trigger silently no-ops on hosts where the corresponding skill / plugin isn't installed. The Step 5.6 superpowers detector was the right idea, but mirroring it as Step 5.7, Step 5.8, … per missing-skill — five mirror sections to cover the gaps above, and one more per future trigger — is a copy-paste explosion. Worse: a deferred task [bootstrap-recommend-projects-meta] was already opened in 1.2.0's wake to mirror the superpowers detector for using-projects-meta, and the same gap is structurally inevitable for every line in the template.
Decision
Collapse Step 5.6 into a single generic "Skill dependencies check" that:
- Reads the project's
CLAUDE.md(just-written or pre-existing). - Walks every non-empty, non-comment line.
- Looks each line up in a
trigger → fulfillermap embedded in the SKILL. - Checks the corresponding detection path on disk:
kind: skill→~/.claude/skills/<name>/SKILL.mdexists?kind: plugin→ key underplugins.<id>in~/.claude/plugins/installed_plugins.json?
- Prints one chat-only block listing every missing fulfiller with a copy-pasteable install command.
The superpowers-only Step 5.6 from 1.6.0 is subsumed cleanly: superpowers becomes one row in the map, with kind: plugin so its install command is /plugin install … rather than bash scripts/install.sh ….
[bootstrap-recommend-projects-meta] (the deferred mirror task) is closed by absorption — the generic step handles using-projects-meta along with everything else in the same commit.
Bumps project-bootstrap 1.6.0 → 1.7.0 (MINOR — adds capability, doesn't break the existing detector since it's absorbed).
Why generic over per-skill mirrors
Per-skill mirror shape:
Step 5.6 — Recommend superpowers if missing
Step 5.7 — Recommend setup-projects-meta if MCP missing
Step 5.8 — Recommend project-discipline if missing
Step 5.9 — Recommend pulling-before-work if missing
…
Each section is ~30 lines of nearly-identical "read detection path → if absent print recommendation" prose. Adding a new canonical trigger means writing another mirror section. Five-skill template → five mirror sections; ten-skill template → ten. The detection logic is the same; only the path and install command differ.
Generic shape replaces the prose mirrors with one ~10-row table. Adding a new canonical trigger means adding one row in the map (plus the line in assets/CLAUDE.md.template, in the same commit). The detection algorithm is invariant.
Skill vs plugin distinction
Two install pathways exist on a Claude Code host:
- Skills live at
~/.claude/skills/<name>/, installed viabash scripts/install.sh <name>(or via thefind-skillsskill). Detection: file existence. - Plugins are a higher-level Claude Code concept (slash commands, hooks, sub-agents, MCP servers); installed via
/plugin install <id>@<marketplace>. Detection: key lookup in~/.claude/plugins/installed_plugins.json.
The map's kind column flags which pathway each fulfiller uses, so the recommendation block emits the correct install command. Currently only superpowers is kind: plugin; everything else is kind: skill. Future triggers may add more plugins.
MCP-server-backed skills
using-context7, using-projects-meta, using-interns each depend on an MCP server that's separately installed (setup-context7, setup-projects-meta, setup-interns). Step 5.6 only checks the using-X policy skill — not whether the MCP server is registered or running. Rationale: every using-X skill carries a "Prerequisites" pointer in its body that fires setup-X at first use if the MCP tools are missing. Bootstrap doesn't need to duplicate that detection — the skill itself self-bootstraps when invoked. Step 5.6 only ensures the using-X skill is present so the trigger isn't silently dead.
Hard rule — never auto-install carries over
The superpowers detector at 1.6.0 had a hard rule: "never auto-install". Reasons:
- Slash commands (
/plugin install …) aren't callable from inside a skill. - Silently mutating user-level skill / plugin state without consent is overreach.
Both reasons generalize. The 1.7.0 generic check is recommendation-only — it prints to chat and never writes into project files or user-level config. 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.
What about user-custom triggers?
Step 5.6 ignores any line in the project's CLAUDE.md that doesn't match a trigger row in the map. If the user added a custom trigger like use my-team-style-guide, it's their responsibility — bootstrap's contract is "we own canonical triggers; non-canonical lines are your responsibility". The check is permissive on custom lines (silent skip), strict on canonical lines (recommend if missing).
Removed canonical lines work symmetrically: if the user deleted delegate to interns when allowed on purpose, Step 5.6 reads from the actual file and never sees that line, so it never recommends using-interns. Correct behavior — the user opted out.
Source-of-truth invariant
The map embedded in SKILL.md and the trigger list in assets/CLAUDE.md.template must stay in sync. Adding a new canonical trigger requires editing both in the same commit. Mismatch = silent gap (template adds a trigger, map doesn't have its row, the recommendation never fires for it). A future hardening could lint the two against each other in CI; for now it's a discipline rule for whoever bumps the version.
Composition with the rest of bootstrap
Step 5 (idempotent merge) ensures the trigger lines are present in the project's CLAUDE.md. Step 5.6 (this) ensures the fulfillers are installed on the host. Together they close the loop:
- 5 → trigger in the file.
- 5.6 → fulfiller on disk.
Either alone is partial. Together a fresh bootstrap on a fresh machine surfaces every install gap in one shot.