skills/docs/PER-REPO-SKILLS.md
dan e921fd96df feat: add per-repo skill deployment pattern
- Add bin/use-skills.sh helper with use_skill and load_skills_from_manifest
- Add .skills manifest pattern for declarative skill configuration
- Fix ai-skills.nix: remove broken npm plugin code, update skill list
- Add update-opencode, web-search, web-research to flake.nix availableSkills
- Add RFC and documentation for team adoption

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 14:47:02 -08:00

3.7 KiB

Per-Repo Skill Deployment

Deploy selected skills to individual projects using direnv + Nix.

Overview

Each project can declare which skills it needs. When team members enter the directory (via direnv), skills are symlinked from the Nix store into .claude/skills/ and .opencode/skills/.

teammate clones repo
        ↓
    direnv allow
        ↓
    nix builds skills (cached)
        ↓
    symlinks created in .claude/skills/
        ↓
    Claude Code sees project-local skills

Quick Start

1. Add to .envrc

Option A: Source the helper (if skills repo is accessible)

source ~/proj/skills/bin/use-skills.sh
use_skills worklog web-search

Option B: Self-contained (copy-paste, no external dependency)

# AI Agent Skills
SKILLS_REPO="git+file://$HOME/proj/skills"  # or git+http://... for remote

use_skill() {
  local skill="$1"
  local out
  out=$(nix build --print-out-paths --no-link "${SKILLS_REPO}#${skill}" 2>/dev/null)
  if [[ -n "$out" ]]; then
    mkdir -p .claude/skills .opencode/skills
    ln -sfn "$out" ".claude/skills/${skill}"
    ln -sfn "$out" ".opencode/skills/${skill}"
    echo "use_skill: ${skill}"
  fi
}

use_skill worklog
use_skill web-search

2. Add to .gitignore

.claude/skills/
.opencode/skills/

3. Done

Team members clone and run direnv allow. Skills appear.

Available Skills

Run nix flake show git+ssh://git@forgejo.delmore.io/dan/skills.git to see all available skills.

Current list:

  • worklog - Create org-mode worklogs
  • web-search - Search the web via Claude
  • web-research - Deep research with multiple backends
  • update-opencode - Update OpenCode via Nix
  • update-spec-kit - Update spec-kit ecosystem
  • niri-window-capture - Capture window screenshots
  • screenshot-latest - Find latest screenshots
  • tufte-press - Generate study card JSON

How It Works

  1. direnv triggers on directory entry
  2. nix build fetches/builds the skill package (cached locally)
  3. symlink points .claude/skills/<name> to /nix/store/xxx-ai-skill-<name>
  4. Claude Code reads skills from .claude/skills/ when in that directory

Skills are always fetched from the latest commit on the skills repo. Nix caches builds locally, so subsequent loads are fast.

Customization

Different skills per project

# Project A - .envrc
use_skill worklog
use_skill web-search

# Project B - .envrc
use_skill worklog
use_skill tufte-press

Claude Code only (no OpenCode)

SKILLS_REPO="git+file://$HOME/proj/skills"
mkdir -p .claude/skills
for skill in worklog web-search; do
  ln -sfn $(nix build --print-out-paths --no-link "${SKILLS_REPO}#${skill}") ".claude/skills/${skill}"
done

Pin to specific version

SKILLS_REPO="git+file://$HOME/proj/skills?rev=abc123def"  # pin to commit
use_skill worklog  # uses pinned revision

Troubleshooting

Skills not appearing

  1. Check direnv allow was run
  2. Check .claude/skills/ exists and has symlinks
  3. Restart Claude Code (it loads skills at startup)

nix build fails

  1. Check network access to skills repo
  2. Check nix flake show $SKILLS_REPO works
  3. Check skill name is correct

Re-run direnv reload to rebuild and re-link.

Comparison with Global Skills

Aspect Global (~/.claude/skills/) Per-Repo (.claude/skills/)
Scope All projects Single project
Deployment Nix Home Manager direnv + nix build
Team sharing Via dotfiles Via project .envrc
Selection User-wide Per-project

Use global for personal defaults. Use per-repo for project-specific or team-shared skills.