✨ Add spire:init skill with adept scaffolding
Human-triggered skill that detects install type, auto-fills project facts, scaffolds .claude/spire/project.md and workpad adept templates, handles gitignore for personal installs, and optionally commits for shared installs. All seven phases from the design.
This commit is contained in:
@@ -0,0 +1,296 @@
|
|||||||
|
---
|
||||||
|
name: init
|
||||||
|
description: >
|
||||||
|
Initialize Spire for the current project — detect project facts,
|
||||||
|
scaffold .claude/spire/project.md, create adept templates, and
|
||||||
|
handle shared vs. personal install. Human-triggered.
|
||||||
|
disable-model-invocation: true
|
||||||
|
allowed-tools: Bash(cat:*), Bash(grep:*), Bash(ls:*), Bash(just:*), Bash(git:*), Read, Write, Glob, Grep
|
||||||
|
---
|
||||||
|
|
||||||
|
# Spire — Init
|
||||||
|
|
||||||
|
Initialize Spire for the current project. Run this once after installing the
|
||||||
|
Spire plugin, or again after major structural changes. Re-init is safe — it
|
||||||
|
will not clobber hand-edited files.
|
||||||
|
|
||||||
|
Seven phases: detect install type, detect project facts, scaffold project.md,
|
||||||
|
scaffold adept templates, gitignore (if personal), optional alias, and commit
|
||||||
|
(if shared).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 1 — Detect install type
|
||||||
|
|
||||||
|
Determine whether Spire is a **shared** (project-level) or **personal**
|
||||||
|
(user-level) install. This governs whether scaffolded files get committed or
|
||||||
|
gitignored.
|
||||||
|
|
||||||
|
1. Read `.claude/settings.json` (if it exists). Search for any string
|
||||||
|
containing `spire` in the `plugins` or `mcpServers` keys — typically
|
||||||
|
`"spire@reliquary"` or a path containing `/spire/`.
|
||||||
|
2. Read `.claude/settings.local.json` (if it exists). Same search.
|
||||||
|
3. Classify:
|
||||||
|
|
||||||
|
| Spire found in | Install type | Action |
|
||||||
|
|---|---|---|
|
||||||
|
| `settings.json` | **Shared** | Files will be committed |
|
||||||
|
| `settings.local.json` only | **Personal** | Files will be gitignored |
|
||||||
|
| Neither file | **Ambiguous** | Ask the user: "Should the Spire config be shared with the project (committed) or personal (gitignored)?" |
|
||||||
|
|
||||||
|
Store the result as `$INSTALL_TYPE` (shared or personal) for later phases.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 2 — Detect project facts
|
||||||
|
|
||||||
|
Auto-detect as much as possible. Each fact that cannot be detected becomes a
|
||||||
|
placeholder in the scaffolded `project.md`.
|
||||||
|
|
||||||
|
### 2.1 — Workpad location
|
||||||
|
|
||||||
|
Resolve the workpad using the `spire:workpad` resolution chain (environment
|
||||||
|
variable, `just workpad-folder`, `docs/workpad/`, `.workpad/`). Record the
|
||||||
|
path as `$WORKPAD`.
|
||||||
|
|
||||||
|
### 2.2 — Pinned agents
|
||||||
|
|
||||||
|
List `.claude/agents/*.md`. For each file, read its frontmatter to extract
|
||||||
|
`name` and `description`. These become the "Pinned agents" list.
|
||||||
|
|
||||||
|
### 2.3 — Verification commands
|
||||||
|
|
||||||
|
Check these files in order for verification commands:
|
||||||
|
|
||||||
|
- **Justfile**: Look for recipes named `check`, `test`, `lint`, `build`,
|
||||||
|
`verify`, `ci`, or similar. Run `just --list` if available.
|
||||||
|
- **Makefile**: Look for targets named `check`, `test`, `lint`, `build`.
|
||||||
|
- **package.json**: Read `scripts` for `test`, `lint`, `build`, `check`.
|
||||||
|
- **Cargo.toml**: If present, `cargo check`, `cargo test`, `cargo clippy`
|
||||||
|
are likely verification commands.
|
||||||
|
|
||||||
|
### 2.4 — Conventions
|
||||||
|
|
||||||
|
Read the root `CLAUDE.md` for project conventions — commit message style,
|
||||||
|
branching strategy, review process, language/framework preferences.
|
||||||
|
Summarize relevant conventions concisely.
|
||||||
|
|
||||||
|
### 2.5 — Tome presence
|
||||||
|
|
||||||
|
Check whether the `tome` plugin is installed:
|
||||||
|
- Search `.claude/settings.json` and `.claude/settings.local.json` for
|
||||||
|
`tome` references.
|
||||||
|
- Check for a `*-tome:navigate` skill or `tome@reliquary` plugin reference.
|
||||||
|
- If found, note the tome skill name for the project.md template.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 3 — Scaffold `project.md`
|
||||||
|
|
||||||
|
Write `.claude/spire/project.md` using the detected facts.
|
||||||
|
|
||||||
|
### 3.1 — Re-init safety check
|
||||||
|
|
||||||
|
If `.claude/spire/project.md` already exists:
|
||||||
|
- Read its YAML frontmatter.
|
||||||
|
- If `status: authored` — **stop**. Tell the user: "project.md has been
|
||||||
|
manually edited (status: authored). Skipping to avoid clobbering your
|
||||||
|
changes. Delete or change status to `generated` to allow re-scaffolding."
|
||||||
|
- If `status: generated` — proceed, overwriting the file.
|
||||||
|
- If no status field — treat as authored, do not overwrite.
|
||||||
|
|
||||||
|
### 3.2 — Write the file
|
||||||
|
|
||||||
|
Create `.claude/spire/` directory if needed. Write `project.md` with this
|
||||||
|
structure:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
status: generated
|
||||||
|
generated: <YYYY-MM-DD>
|
||||||
|
---
|
||||||
|
# Project Knowledge (per-project — swap this file when adopting Igor)
|
||||||
|
|
||||||
|
Project-specific facts for Igor and the athanor. The generic behavior files
|
||||||
|
stay unchanged across projects; only this file (and any tome/navigation skill
|
||||||
|
preload) changes.
|
||||||
|
|
||||||
|
## This project
|
||||||
|
|
||||||
|
- **Tome skill**: <detected tome skill or "none detected — Igor will orient via direct file reads">
|
||||||
|
- **Workpad**: <detected workpad path with subfolder structure>
|
||||||
|
- **Adepts**: Domain knowledge agents with persistent folders at `<workpad>/adepts/<domain-slug>/`.
|
||||||
|
- **Pinned agents** (prefer these over generic tiers):
|
||||||
|
<list of detected agents with name and description, or placeholder comment>
|
||||||
|
- **Verification commands**: <detected commands, or placeholder comment>
|
||||||
|
- **Domain skills to route to subagents when relevant**: <!-- detect and list, or leave as placeholder -->
|
||||||
|
- **Conventions**: <summarized conventions from CLAUDE.md, or placeholder comment>
|
||||||
|
```
|
||||||
|
|
||||||
|
Fill every field that was detected; leave a `<!-- placeholder -->` comment for
|
||||||
|
fields that were not.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 4 — Scaffold adept templates
|
||||||
|
|
||||||
|
Create the adept directory structure in the workpad. These files are
|
||||||
|
referenced by the `adept` agent during genesis (see `agents/adept.md`).
|
||||||
|
|
||||||
|
### 4.1 — Create the adepts directory
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p "${WORKPAD}/adepts/_template"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 — Write `adepts/CLAUDE.md`
|
||||||
|
|
||||||
|
If `${WORKPAD}/adepts/CLAUDE.md` already exists and contains
|
||||||
|
`status: authored` in its frontmatter, skip it. Otherwise write:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
status: generated
|
||||||
|
---
|
||||||
|
# Adepts
|
||||||
|
|
||||||
|
This directory holds domain knowledge accumulated by adept agents. Each
|
||||||
|
subfolder is one domain — a subsystem, a library, a cross-cutting concern —
|
||||||
|
named with a short kebab-case slug.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
adepts/
|
||||||
|
CLAUDE.md ← you are here
|
||||||
|
_template/CLAUDE.md ← starter template for new domains
|
||||||
|
<domain-slug>/
|
||||||
|
CLAUDE.md ← domain orientation, key files, conventions
|
||||||
|
YYYY-MM-DD-HH-journal-*.md ← session journals from adept work
|
||||||
|
```
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- **One domain per folder.** If two domains overlap, pick the stricter scope.
|
||||||
|
Broad names are gravity wells — prefer specificity.
|
||||||
|
- **CLAUDE.md is the handoff document.** When an adept spawns into an existing
|
||||||
|
domain, it reads this file first. Write it for your successor, not yourself.
|
||||||
|
- **Journals are append-only.** Each session gets a new journal entry. Include
|
||||||
|
what you found, what you changed, what's still unclear, and what steps you
|
||||||
|
took to orient (files read, searches run, what was useful vs. noise).
|
||||||
|
- **Don't hoard.** If a finding belongs in the project's main docs or workpad
|
||||||
|
reports, put it there and link from here. The adept folder is for domain
|
||||||
|
context that helps the next adept orient, not a shadow wiki.
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 — Write `adepts/_template/CLAUDE.md`
|
||||||
|
|
||||||
|
If `${WORKPAD}/adepts/_template/CLAUDE.md` already exists and contains
|
||||||
|
`status: authored`, skip it. Otherwise write:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
status: generated
|
||||||
|
---
|
||||||
|
# <Domain Name>
|
||||||
|
|
||||||
|
<!-- Replace this heading with the domain name. Fill in the sections below
|
||||||
|
during your genesis orientation. -->
|
||||||
|
|
||||||
|
## Domain
|
||||||
|
|
||||||
|
<!-- What this domain covers. One paragraph: scope, boundaries, why it exists
|
||||||
|
as a separate domain. -->
|
||||||
|
|
||||||
|
## Key files
|
||||||
|
|
||||||
|
<!-- Files and directories central to this domain. Use a table or bullet list.
|
||||||
|
Include paths relative to the repo root. -->
|
||||||
|
|
||||||
|
| Path | What it is |
|
||||||
|
|------|-----------|
|
||||||
|
| <!-- e.g. src/auth/ --> | <!-- e.g. Authentication module --> |
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
<!-- Domain-specific conventions: naming patterns, error handling style,
|
||||||
|
testing expectations, dependency rules. Only note things that differ
|
||||||
|
from or add to the project-wide conventions. -->
|
||||||
|
|
||||||
|
## Open questions
|
||||||
|
|
||||||
|
<!-- Things the founding adept couldn't resolve. Future adepts should
|
||||||
|
attempt these before adding new ones. Remove entries as they're
|
||||||
|
answered. -->
|
||||||
|
|
||||||
|
- <!-- e.g. "Why does FooService bypass the standard auth middleware?" -->
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 5 — Gitignore (personal install only)
|
||||||
|
|
||||||
|
If `$INSTALL_TYPE` is **personal**:
|
||||||
|
|
||||||
|
1. Read `.claude/.gitignore` (create it if it does not exist).
|
||||||
|
2. Check whether it already contains a line matching `spire/`.
|
||||||
|
3. If not present, append `spire/` on its own line.
|
||||||
|
|
||||||
|
If `$INSTALL_TYPE` is **shared**, skip this phase entirely.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 6 — Optional alias
|
||||||
|
|
||||||
|
Offer the user an optional convenience alias:
|
||||||
|
|
||||||
|
> "Would you like to create `/assistant` as an alias for `/spire:igor`?
|
||||||
|
> This creates `.claude/skills/assistant/SKILL.md` so you can invoke Igor
|
||||||
|
> as just `/assistant`."
|
||||||
|
|
||||||
|
If the user accepts:
|
||||||
|
|
||||||
|
1. Create `.claude/skills/assistant/` directory if needed.
|
||||||
|
2. Write `.claude/skills/assistant/SKILL.md`:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
---
|
||||||
|
name: assistant
|
||||||
|
description: Start an Igor session — alias for spire:igor.
|
||||||
|
user-invocable: true
|
||||||
|
---
|
||||||
|
|
||||||
|
Invoke the `spire:igor` skill. Pass through any arguments:
|
||||||
|
|
||||||
|
/spire:igor $ARGUMENTS
|
||||||
|
```
|
||||||
|
|
||||||
|
If the user declines or doesn't respond, skip.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Phase 7 — Commit (shared install only)
|
||||||
|
|
||||||
|
If `$INSTALL_TYPE` is **shared**:
|
||||||
|
|
||||||
|
1. Stage all files created or modified by this init run:
|
||||||
|
- `.claude/spire/project.md`
|
||||||
|
- `${WORKPAD}/adepts/CLAUDE.md`
|
||||||
|
- `${WORKPAD}/adepts/_template/CLAUDE.md`
|
||||||
|
- `.claude/skills/assistant/SKILL.md` (if created in Phase 6)
|
||||||
|
2. Commit with message: `🤖 Initialize Spire project config`
|
||||||
|
|
||||||
|
If `$INSTALL_TYPE` is **personal**, do not commit — the files are gitignored.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
After all phases, report to the user:
|
||||||
|
|
||||||
|
- Install type detected (shared / personal)
|
||||||
|
- What was scaffolded (list files created or updated)
|
||||||
|
- What was skipped (files with `status: authored`, phases that didn't apply)
|
||||||
|
- Next steps: "Edit `.claude/spire/project.md` to fill in any remaining
|
||||||
|
placeholders, then change `status` from `generated` to `authored` to
|
||||||
|
lock it against future re-inits."
|
||||||
Reference in New Issue
Block a user