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)
101 lines
6.9 KiB
Markdown
101 lines
6.9 KiB
Markdown
---
|
|
title: "project-bootstrap@1.7.0 — generic skill-dependencies check (Step 5.6)"
|
|
type: concept
|
|
updated: 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:
|
|
|
|
1. Reads the project's `CLAUDE.md` (just-written or pre-existing).
|
|
2. Walks every non-empty, non-comment line.
|
|
3. Looks each line up in a `trigger → fulfiller` map embedded in the SKILL.
|
|
4. Checks the corresponding detection path on disk:
|
|
- `kind: skill` → `~/.claude/skills/<name>/SKILL.md` exists?
|
|
- `kind: plugin` → key under `plugins.<id>` in `~/.claude/plugins/installed_plugins.json`?
|
|
5. 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 via `bash scripts/install.sh <name>` (or via the `find-skills` skill). 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.
|