# 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
