Files
claude-skills/.wiki/concepts/bootstrap-skill-deps-check.md
vitya 8c547d73af feat(project-bootstrap): generic Step 5.6 skill-deps check
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)
2026-05-05 21:21:19 +03:00

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:

  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.