# 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/` (and `$CODEX_HOME/skills` if set). ``` 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) ```bash source ~/proj/skills/bin/use-skills.sh export CODEX_HOME="$PWD/.codex" # Optional: per-repo Codex skills use_skills worklog web-search ``` **Option B: Self-contained** (copy-paste, no external dependency) ```bash # 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}" if [[ -n "${CODEX_HOME:-}" ]]; then mkdir -p "${CODEX_HOME}/skills" ln -sfn "$out" "${CODEX_HOME}/skills/${skill}" fi echo "use_skill: ${skill}" fi } use_skill worklog use_skill web-search ``` ### 2. Add to `.gitignore` ``` .claude/skills/ .opencode/skills/ .codex/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/` to `/nix/store/xxx-ai-skill-` (and `$CODEX_HOME/skills/` if set) 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 ```bash # 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) ```bash 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 ```bash 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 ### Symlinks broken after nix-collect-garbage 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.