- use-skills.sh: symlink to $CODEX_HOME/skills when CODEX_HOME is set - docs: update PER-REPO-SKILLS.md and RFC-SKILLS-MANIFEST.md with Codex flow - hq: add model configuration section (sonnet-4.5, Claude Max) - hq: update launch commands with explicit --model flag Closes skills-legi Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
242 lines
6.5 KiB
Markdown
242 lines
6.5 KiB
Markdown
# RFC: .skills Manifest Pattern
|
|
|
|
**Status**: Draft
|
|
**Created**: 2024-11-30
|
|
**Author**: dan + claude
|
|
|
|
## Summary
|
|
|
|
A lightweight pattern for per-repo skill deployment where projects declare desired skills in a `.skills` manifest file. This enables:
|
|
- Team members get skills on clone + `direnv allow`
|
|
- Agents can query installed skills without loading full docs
|
|
- Agents can install skills by editing the manifest
|
|
- Central skills repo remains single source of truth
|
|
|
|
## Motivation
|
|
|
|
### Current State
|
|
- Skills live in central `skills` repo
|
|
- Global deployment via Nix Home Manager to `~/.claude/skills/`
|
|
- Per-repo deployment undocumented and manual
|
|
|
|
### Problems
|
|
1. **No per-repo differentiation** - all projects get same global skills
|
|
2. **Agent context bloat** - loading full skill docs is expensive
|
|
3. **No standard pattern** - each project reinvents .envrc setup
|
|
4. **Agent can't help** - no standard way for agent to install skills
|
|
|
|
### Goals
|
|
1. Projects declare which skills they need
|
|
2. Team members get skills automatically (via direnv)
|
|
3. Agents can answer "what skills do we have?"
|
|
4. Agents can add skills with minimal context
|
|
|
|
## Design
|
|
|
|
### The `.skills` Manifest
|
|
|
|
A simple text file in project root:
|
|
|
|
```
|
|
# .skills - AI agent skills for this project
|
|
# Run `direnv reload` after editing
|
|
|
|
worklog
|
|
web-search
|
|
```
|
|
|
|
**Format**:
|
|
- One skill name per line
|
|
- Lines starting with `#` are comments
|
|
- Empty lines ignored
|
|
- Skill names match flake package names
|
|
|
|
### The `.envrc` Integration
|
|
|
|
Projects add to their `.envrc`:
|
|
|
|
```bash
|
|
# AI Agent Skills
|
|
if [[ -f .skills ]]; then
|
|
export CODEX_HOME="$PWD/.codex" # Optional: per-repo Codex skills
|
|
SKILLS_REPO="${SKILLS_REPO:-git+file://$HOME/proj/skills}"
|
|
mkdir -p .claude/skills .opencode/skills
|
|
while IFS= read -r skill || [[ -n "$skill" ]]; do
|
|
[[ -z "$skill" || "$skill" =~ ^[[:space:]]*# ]] && continue
|
|
skill="${skill%%#*}" # strip inline comments
|
|
skill="${skill// /}" # strip whitespace
|
|
out=$(nix build --print-out-paths --no-link "${SKILLS_REPO}#${skill}" 2>/dev/null)
|
|
if [[ -n "$out" ]]; then
|
|
ln -sfn "$out" ".claude/skills/${skill}"
|
|
ln -sfn "$out" ".opencode/skills/${skill}"
|
|
if [[ -n "${CODEX_HOME:-}" ]]; then
|
|
mkdir -p "${CODEX_HOME}/skills"
|
|
ln -sfn "$out" "${CODEX_HOME}/skills/${skill}"
|
|
fi
|
|
fi
|
|
done < .skills
|
|
fi
|
|
```
|
|
|
|
Or source the helper:
|
|
|
|
```bash
|
|
if [[ -f .skills ]]; then
|
|
export CODEX_HOME="$PWD/.codex" # Optional: per-repo Codex skills
|
|
source ~/proj/skills/bin/use-skills.sh
|
|
load_skills_from_manifest
|
|
fi
|
|
```
|
|
|
|
### The `.gitignore` Entries
|
|
|
|
```
|
|
.claude/skills/
|
|
.opencode/skills/
|
|
.codex/skills/
|
|
```
|
|
|
|
The manifest (`.skills`) IS committed. The symlinks are not.
|
|
|
|
### Agent Context Blurb
|
|
|
|
Add to project's `CLAUDE.md` or `AGENTS.md`:
|
|
|
|
```markdown
|
|
## Skills
|
|
|
|
This project uses AI agent skills. Skills are declared in `.skills` and installed via direnv.
|
|
|
|
**Installed**: See `.skills`
|
|
**Available**: worklog, web-search, web-research, update-opencode, update-spec-kit, niri-window-capture, screenshot-latest, tufte-press
|
|
**To add**: Edit `.skills`, then run `direnv reload`
|
|
**Docs**: See ~/proj/skills for full skill documentation
|
|
```
|
|
|
|
This gives the agent enough context (~4 lines) to:
|
|
- Answer "what skills do we have?" → read `.skills`
|
|
- Add a skill → edit `.skills`, tell user to `direnv reload`
|
|
- Know where to find full docs if needed
|
|
|
|
## Workflow
|
|
|
|
### Initial Setup (one-time per project)
|
|
|
|
1. Create `.skills` with desired skills
|
|
2. Add skills loader to `.envrc`
|
|
3. Add `.claude/skills/` to `.gitignore`
|
|
4. Add brief context to project's CLAUDE.md
|
|
5. Commit
|
|
|
|
### Team Member Onboarding
|
|
|
|
1. Clone repo
|
|
2. Run `direnv allow`
|
|
3. Skills are installed automatically
|
|
|
|
### Adding a Skill
|
|
|
|
**Human workflow**:
|
|
1. Edit `.skills`, add skill name
|
|
2. Run `direnv reload`
|
|
|
|
**Agent-assisted workflow**:
|
|
1. Human: "add the worklog skill"
|
|
2. Agent: edits `.skills`, adds `worklog`
|
|
3. Agent: "Added worklog to .skills. Run `direnv reload` to install."
|
|
|
|
### Querying Skills
|
|
|
|
**"What skills do we have?"**
|
|
- Agent reads `.skills` file
|
|
- Or runs `ls .claude/skills/`
|
|
|
|
**"What skills are available?"**
|
|
- Agent references the list in CLAUDE.md context
|
|
- Or runs `nix flake show $SKILLS_REPO`
|
|
|
|
## File Locations
|
|
|
|
```
|
|
project/
|
|
├── .skills # Manifest (committed)
|
|
├── .envrc # Loads skills from manifest (committed)
|
|
├── .gitignore # Ignores .claude/skills/ (committed)
|
|
├── CLAUDE.md # Agent context blurb (committed)
|
|
├── .claude/
|
|
│ └── skills/ # Symlinks to nix store (NOT committed)
|
|
│ ├── worklog -> /nix/store/xxx
|
|
│ └── web-search -> /nix/store/yyy
|
|
└── .opencode/
|
|
└── skills/ # Same symlinks (NOT committed)
|
|
```
|
|
|
|
## Helper Script
|
|
|
|
`skills/bin/use-skills.sh` provides:
|
|
|
|
```bash
|
|
# Load skills from .skills manifest
|
|
load_skills_from_manifest() {
|
|
[[ ! -f .skills ]] && return
|
|
mkdir -p .claude/skills .opencode/skills
|
|
while IFS= read -r skill || [[ -n "$skill" ]]; do
|
|
[[ -z "$skill" || "$skill" =~ ^[[:space:]]*# ]] && continue
|
|
use_skill "${skill%%#*}"
|
|
done < .skills
|
|
}
|
|
```
|
|
|
|
## Migration
|
|
|
|
### Existing Projects
|
|
|
|
1. Survey current `.envrc` files for skill-related setup
|
|
2. Extract skill list to `.skills`
|
|
3. Replace custom logic with standard pattern
|
|
4. Add CLAUDE.md context blurb
|
|
|
|
### New Projects
|
|
|
|
Use the template:
|
|
```bash
|
|
cp ~/proj/skills/templates/skills-envrc-snippet.sh .envrc.skills
|
|
cat .envrc.skills >> .envrc
|
|
echo "worklog" > .skills
|
|
echo ".claude/skills/" >> .gitignore
|
|
```
|
|
|
|
## Alternatives Considered
|
|
|
|
### Full flake.nix in each project
|
|
- Heavier than needed
|
|
- Not all projects want/have flake.nix
|
|
- Decided: .envrc + nix build is lighter
|
|
|
|
### Central config mapping repos to skills
|
|
- Single view of all projects
|
|
- But adds indirection and sync complexity
|
|
- Decided: per-repo manifest is simpler
|
|
|
|
### Agent edits .envrc directly
|
|
- Fragile - .envrc has other content
|
|
- Decided: separate .skills file is cleaner for agent editing
|
|
|
|
## Open Questions
|
|
|
|
1. **Should we validate skill names?** Currently fails silently if skill doesn't exist.
|
|
2. **Should we support skill versions?** e.g., `worklog@v1.2.0`
|
|
3. **Should there be a `skills` CLI?** e.g., `skills add worklog`, `skills list`
|
|
|
|
## Implementation Checklist
|
|
|
|
- [x] Create `bin/use-skills.sh` helper
|
|
- [x] Create `docs/PER-REPO-SKILLS.md` documentation
|
|
- [x] Create this RFC
|
|
- [ ] Update `bin/use-skills.sh` with `load_skills_from_manifest`
|
|
- [ ] Create template `.skills` file
|
|
- [ ] Create template CLAUDE.md blurb
|
|
- [ ] Survey existing projects for migration
|
|
- [ ] Migrate pilot project
|
|
- [ ] Update AGENTS.md with pattern reference
|