Design covering findings 1/2/3 — shell injection for project.md override, shared-vs-personal gitignore handling, spire:init skill modelled on tome:init, and adept scaffolding. Ready for plan.
5.3 KiB
Design: Spire project override + spire:init
Date: 2026-09-17
Covers: Findings 1 (no spire:init), 2 (project.md cannot be overridden), 3 (adept scaffolding not shipped)
Source research: research/2026-09-17-project-md-override-mechanics.md
Goal: goals/igor-project-adoption.md
The problem
Igor and Athanor hard-bind references/project.md via @ directives that resolve into the plugin cache. Every project gets the blank template. There is no init, no override, and no adept scaffolding — three gaps that compound into "every session rediscovers the project from scratch."
Solution: three new pieces
1. spire:project skill (the injection vehicle)
A tiny skill whose only job is loading the right project.md at skill-load time via shell injection:
---
name: project
description: Loads per-project Spire configuration (override or bundled template).
allowed-tools: Bash(cat:*)
---
!`cat "${CLAUDE_PROJECT_DIR}/.claude/spire/project.md" 2>/dev/null || cat "${CLAUDE_SKILL_DIR}/../igor/references/project.md"`
<!-- If the above block is the blank template, run /spire:init to configure this project. -->
Igor (agents/igor.md) and Athanor (agents/athanor.md) add spire:project to their skills: list and drop their @ imports. The skill loads at agent startup — same timing as today's @, but with fallback.
Runtime belt: Igor's skill text keeps a one-line instruction — "if the project block is the blank template, try reading .claude/spire/project.md before orienting from scratch" — so it degrades gracefully if disableSkillShellExecution is on.
2. Shared vs. personal installs
.claude/ is often committed to git. But Spire may be personal — installed via settings.local.json or user-level settings — in which case .claude/spire/ should not leak into the project's history.
The rule: spire:init detects where Spire is enabled:
| Spire enabled in | .claude/spire/ should be |
Init action |
|---|---|---|
settings.json (project-level, committed) |
Committed with the project | Write files, commit |
settings.local.json or user settings |
Gitignored | Write files, add /spire/ to .claude/.gitignore, do not commit |
| Not detected / ambiguous | Ask the user | Prompt: "Should the Spire config be shared with the project or personal?" |
Detection: check whether "spire@reliquary" (or any spire plugin ref) appears in .claude/settings.json vs. .claude/settings.local.json. If in settings.json → shared. If in settings.local.json or absent from both → personal/ask.
The .claude/.gitignore approach (a gitignore inside .claude/) keeps the ignore scoped — it only affects .claude/spire/, not the rest of .claude/.
A project.local.md sibling can follow later for personal overrides on top of shared config — but that's out of scope for the first pass.
3. spire:init skill
Human-triggered (disable-model-invocation: true). Modelled on tome:init Phase 2.1.
Phases:
-
Detect — read the project to auto-fill what we can:
- Workpad location via the
spire:workpadresolution chain - Pinned agents from
.claude/agents/*.md - Verification commands from
Justfile(recipe names likecheck,test,lint,build),Makefile,package.jsonscripts,Cargo.toml - Conventions from root
CLAUDE.md - Tome skill presence (check if a
*-tome:navigateskill exists ortome@reliquaryis enabled)
- Workpad location via the
-
Scaffold — create the following:
.claude/spire/project.md— filled template withstatus: generatedfront matter (re-init safe: only overwrite while status isgenerated, never clobberauthored)<workpad>/adepts/_template/CLAUDE.md— the adept CLAUDE.md template thatagents/adept.md:23,26references but doesn't ship<workpad>/adepts/directory (if missing)
-
Gitignore (if personal install) — add
spire/to.claude/.gitignore -
Alias (optional) — offer to create
.claude/skills/assistant/SKILL.mdthat invokesspire:igoras/assistant, so the project can use a generic entry point -
Commit (if shared install) — commit the scaffolded files with gitmoji
4. Adept template
The adept agent (agents/adept.md) references <workpad>/adepts/_template/CLAUDE.md and <workpad>/adepts/CLAUDE.md — neither exists. spire:init creates both:
adepts/CLAUDE.md— root-level orientation for the adepts directory (what it is, how adepts use it)adepts/_template/CLAUDE.md— the default starting CLAUDE.md for a newly spawned adept's domain folder
These are status: generated and re-init safe.
5. Changes to existing files
| File | Change |
|---|---|
skills/igor/SKILL.md:32 |
Remove @references/project.md. Add a one-line runtime fallback instruction. |
agents/igor.md |
Add spire:project to skills: list |
agents/athanor.md:25 |
Remove @skills/igor/references/project.md. Add spire:project to skills: list |
references/project.md |
Add "run /spire:init" hint at top. Keep as fallback template. |
6. Backward compatibility
- No
.claude/spire/project.md→ shell injection falls back to bundled template → same as today - Template gains a hint to run init, turning the dead-end into a prompt
disableSkillShellExecution→ runtime fallback instruction kicks instatus: generatedfront matter protects hand-edits from re-init