Files
reliquary/docs/workpad/designs/spire-project-override-and-init.md
T
g4borg c9d0d183ff 📝 Add design: Spire project override + spire:init
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.
2026-09-17 14:06:45 +02:00

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:

  1. Detect — read the project to auto-fill what we can:

    • Workpad location via the spire:workpad resolution chain
    • Pinned agents from .claude/agents/*.md
    • Verification commands from Justfile (recipe names like check, test, lint, build), Makefile, package.json scripts, Cargo.toml
    • Conventions from root CLAUDE.md
    • Tome skill presence (check if a *-tome:navigate skill exists or tome@reliquary is enabled)
  2. Scaffold — create the following:

    • .claude/spire/project.md — filled template with status: generated front matter (re-init safe: only overwrite while status is generated, never clobber authored)
    • <workpad>/adepts/_template/CLAUDE.md — the adept CLAUDE.md template that agents/adept.md:23,26 references but doesn't ship
    • <workpad>/adepts/ directory (if missing)
  3. Gitignore (if personal install) — add spire/ to .claude/.gitignore

  4. Alias (optional) — offer to create .claude/skills/assistant/SKILL.md that invokes spire:igor as /assistant, so the project can use a generic entry point

  5. 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 in
  • status: generated front matter protects hand-edits from re-init