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>
This commit is contained in:
dan 2025-11-30 14:47:02 -08:00
parent 0e098ba0bb
commit e921fd96df
8 changed files with 800 additions and 60 deletions

3
.gitattributes vendored Normal file
View file

@ -0,0 +1,3 @@
# Use bd merge for beads JSONL files
.beads/issues.jsonl merge=beads

68
bin/use-skills.sh Executable file
View file

@ -0,0 +1,68 @@
#!/usr/bin/env bash
# Helper for per-repo skill deployment via direnv
# Source this from your .envrc or copy the functions
#
# Usage in .envrc:
# source /path/to/skills/bin/use-skills.sh
# use_skills worklog web-search
#
# Or without sourcing (copy-paste into .envrc):
# SKILLS_REPO="git+ssh://git@forgejo.example/dan/skills.git"
# use_skill() { ... }
# use_skill worklog
# Default repo - uses local git, override with SKILLS_REPO for remote
# Local: git+file:///home/dan/proj/skills (default, works offline)
# Network: git+http://192.168.1.108:3000/dan/skills.git
SKILLS_REPO="${SKILLS_REPO:-git+file://$HOME/proj/skills}"
# Install a single skill via nix build + symlink
use_skill() {
local skill="$1"
local out
out=$(nix build --print-out-paths --no-link "${SKILLS_REPO}#${skill}" 2>/dev/null)
if [[ -z "$out" ]]; then
echo "use_skill: failed to build ${skill}" >&2
return 1
fi
# Claude Code
if [[ -d .claude ]] || [[ -n "${SKILLS_CLAUDE:-}" ]]; then
mkdir -p .claude/skills
ln -sfn "$out" ".claude/skills/${skill}"
fi
# OpenCode
if [[ -d .opencode ]] || [[ -n "${SKILLS_OPENCODE:-}" ]]; then
mkdir -p .opencode/skills
ln -sfn "$out" ".opencode/skills/${skill}"
fi
echo "use_skill: ${skill} -> ${out}"
}
# Install multiple skills
use_skills() {
# Ensure at least one target exists
mkdir -p .claude/skills .opencode/skills
for skill in "$@"; do
use_skill "$skill"
done
}
# Load skills from .skills manifest file
load_skills_from_manifest() {
[[ ! -f .skills ]] && return 0
mkdir -p .claude/skills .opencode/skills
while IFS= read -r skill || [[ -n "$skill" ]]; do
# Skip empty lines and comments
[[ -z "$skill" || "$skill" =~ ^[[:space:]]*# ]] && continue
# Strip inline comments and whitespace
skill="${skill%%#*}"
skill="${skill// /}"
[[ -n "$skill" ]] && use_skill "$skill"
done < .skills
}

144
docs/PER-REPO-SKILLS.md Normal file
View file

@ -0,0 +1,144 @@
# 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)
```bash
source ~/proj/skills/bin/use-skills.sh
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}"
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
```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.

234
docs/RFC-SKILLS-MANIFEST.md Normal file
View file

@ -0,0 +1,234 @@
# 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
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}"
fi
done < .skills
fi
```
Or source the helper:
```bash
if [[ -f .skills ]]; then
source ~/proj/skills/bin/use-skills.sh
load_skills_from_manifest
fi
```
### The `.gitignore` Entries
```
.claude/skills/
.opencode/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

View file

@ -0,0 +1,133 @@
# RFC: Per-Project AI Agent Skills
**Status**: Proposal
**Date**: 2025-11-30
**Audience**: All project teams using Claude Code or OpenCode
## Summary
A standard pattern for projects to declare which AI agent skills they need. Team members automatically get the right skills when they clone and enter the project directory.
## Problem
Currently, AI agent skills are deployed globally to everyone's machine. This means:
- All projects get all skills, whether they need them or not
- No way to share project-specific skills with teammates
- No visibility into what skills a project uses
## Solution
Projects declare their skills in a `.skills` file. When you enter the directory (via direnv), the skills are automatically installed.
```
# .skills
worklog
web-search
```
That's it. Clone the repo, run `direnv allow`, and you have the skills.
## How It Works
```
You clone a repo with .skills file
Run `direnv allow`
direnv reads .skills, builds each skill via Nix
Skills symlinked to .claude/skills/ and .opencode/skills/
Claude Code / OpenCode sees the skills
```
Skills come from the central skills repo (`~/proj/skills`), so everyone gets the same version.
## Available Skills
| Skill | Description |
|-------|-------------|
| `worklog` | Create org-mode worklogs documenting sessions |
| `web-search` | Search the web via Claude subprocess |
| `web-research` | Deep research with multiple backends |
| `update-opencode` | Update OpenCode version via Nix |
| `niri-window-capture` | Capture window screenshots (security-sensitive) |
| `tufte-press` | Generate Tufte-style study cards |
## Adopting This Pattern
### 1. Create `.skills` file
```bash
echo "worklog" > .skills
```
### 2. Update `.envrc`
Add to your project's `.envrc`:
```bash
# AI Agent Skills
if [[ -f .skills ]]; then
source ~/proj/skills/bin/use-skills.sh
load_skills_from_manifest
fi
```
### 3. Update `.gitignore`
```bash
echo ".claude/skills/" >> .gitignore
echo ".opencode/skills/" >> .gitignore
```
### 4. (Optional) Add agent context
Add to your `AGENTS.md` or `CLAUDE.md`:
```markdown
## Skills
This project uses AI agent skills declared in `.skills`.
- **Installed**: See `.skills`
- **To add**: Edit `.skills`, run `direnv reload`
```
### 5. Commit and share
```bash
git add .skills .envrc .gitignore
git commit -m "Add AI agent skills support"
```
Teammates will get the skills when they `direnv allow`.
## FAQ
**Q: Do I need Nix?**
A: Yes. Skills are built via Nix for reproducibility.
**Q: What if I'm offline?**
A: Works fine. Skills build from the local `~/proj/skills` repo.
**Q: Can I pin a specific version?**
A: Yes. Use `SKILLS_REPO="git+file://$HOME/proj/skills?rev=abc123"` in your `.envrc`.
**Q: What if a skill doesn't exist?**
A: The build will fail silently for that skill. Check the name matches a skill in the repo.
**Q: How do I see what skills are installed?**
A: `ls .claude/skills/` or `cat .skills`
**Q: How do I add a skill after setup?**
A: Edit `.skills`, then run `direnv reload`.
## Future Improvements
1. **Global direnv helper** - Add `load_project_skills` to `~/.config/direnv/direnvrc` so `.envrc` only needs one line
2. **CLI tool** - `skills init` to set up a project, `skills add <name>` to add skills
3. **Validation** - Warn if a skill name doesn't exist
## Questions / Feedback
Open an issue in the skills repo or ask in the team channel.

View file

@ -0,0 +1,211 @@
#+TITLE: Per-Repo Skill Deployment: Design and RFC
#+DATE: 2025-11-30
#+KEYWORDS: skills, per-repo, direnv, nix, deployment, rfc, beads, manifest
#+COMMITS: 0 (uncommitted work)
#+COMPRESSION_STATUS: uncompressed
* Session Summary
** Date: 2025-11-30 (Sunday)
** Focus Area: Designing and documenting per-repo skill deployment pattern
* Accomplishments
- [X] Explored skills repository structure and identified 9 outstanding issues
- [X] Populated beads issue tracker with all identified work items
- [X] Set up dependency relationships between design decisions and documentation tasks
- [X] Fixed ai-skills.nix module - removed broken opencode-skills npm plugin code
- [X] Updated flake.nix to include all 8 skills (was missing update-opencode, web-search, web-research)
- [X] Designed per-repo skill deployment pattern using direnv + nix build
- [X] Created bin/use-skills.sh helper script with use_skill, use_skills, load_skills_from_manifest
- [X] Created docs/PER-REPO-SKILLS.md with quick start documentation
- [X] Created docs/RFC-SKILLS-MANIFEST.md with full pattern specification
- [X] Introduced .skills manifest file concept for agent-friendly skill configuration
- [ ] Survey existing repos for .envrc patterns (next step)
- [ ] Migrate pilot project to new pattern
* Key Decisions
** Decision 1: Per-repo skills via direnv + nix build (not devShell)
- Context: User has Nix but wanted something lighter than full flake.nix in each consumer project
- Options considered:
1. Home Manager module - writes to global ~/.claude/skills/, no per-repo differentiation
2. devShell symlinks - requires flake.nix in every consumer project
3. direnv + nix build - lighter, just add to .envrc
- Rationale: direnv already used in many repos, nix build caches builds, no new files needed
- Impact: Each project can specify its own skill set via .envrc or .skills file
** Decision 2: .skills manifest file for agent editing
- Context: Agent needs to be able to add/query skills without bloating context
- Options considered:
1. Agent edits .envrc directly - fragile, .envrc has other content
2. Central config mapping repos to skills - indirection, sync complexity
3. Separate .skills file - clean for agent editing, .envrc reads it
- Rationale: .skills is simple text (one skill per line), easy for agent to read/modify
- Impact: Agent can answer "what skills do we have?" by reading .skills, can add skills by appending
** Decision 3: Keep both Claude Code and OpenCode support
- Context: Asked whether to simplify to Claude Code only
- Decision: Keep dual-agent support
- Rationale: Infrastructure already supports both, minimal extra complexity
- Impact: Skills symlinked to both .claude/skills/ and .opencode/skills/
** Decision 4: Always latest from skills repo (no version pinning)
- Context: User preference for simplicity over reproducibility here
- Decision: Default to latest, optional rev pinning if needed
- Impact: nix build fetches latest, caches locally for performance
* Problems & Solutions
| Problem | Solution | Learning |
|---------|----------|----------|
| ai-skills.nix had broken fetchFromNpm with empty sha256 | Removed entire opencode-skills npm plugin section | Keep modules simple, remove dead code |
| availableSkills list in flake.nix was stale | Added update-opencode, web-search, web-research | Need process to keep lists in sync |
| bd dep syntax confusion (from vs to) | bd dep add A B means "A depends on B" not "A blocks B" | Read help output carefully |
| Home Manager module writes to global paths, not per-repo | Per-repo uses .claude/skills/ in project, not global | Different deployment targets, different mechanisms |
* Technical Details
** Code Changes
- Total files modified: 2 existing + 3 new
- Key files changed:
- `modules/ai-skills.nix` - Removed 60 lines of broken npm plugin code, updated skill list in docs
- `flake.nix` - Added 3 skills to availableSkills list
- New files created:
- `bin/use-skills.sh` - Helper script with use_skill, use_skills, load_skills_from_manifest functions
- `docs/PER-REPO-SKILLS.md` - Quick start documentation for per-repo deployment
- `docs/RFC-SKILLS-MANIFEST.md` - Full RFC documenting the .skills manifest pattern
** Commands Used
#+begin_src bash
# Beads workflow
bd ready # See available work
bd create --title="..." --type=task --description="..."
bd update <id> --status=in_progress
bd close <id> --reason="..."
bd dep add <from> <to> # from depends on to
bd list
bd stats
# Nix validation
nix flake check # Verified all packages build
# Skill deployment pattern
nix build --print-out-paths --no-link "git+ssh://...#worklog"
ln -sfn "$out" ".claude/skills/worklog"
#+end_src
** Architecture Notes
- Skills repo flake exports individual packages per skill
- Consumer projects don't need flake.nix, just .envrc with nix build calls
- Symlinks point to /nix/store paths - Claude Code follows them fine
- .skills manifest is committed, .claude/skills/ symlinks are gitignored
- Brief context blurb in project CLAUDE.md tells agent about skills (~4 lines)
* Process and Workflow
** What Worked Well
- Beads for tracking issues - good visibility into work items
- Plan mode for thinking through architecture before coding
- Iterative questioning to clarify user requirements (Nix available? Source of truth?)
- "Ultrathink" prompt to go deeper on design questions
** What Was Challenging
- Initial confusion about what "per-repo" meant (global HM module vs project-local)
- Getting beads dependency direction right (had to remove and re-add)
- Balancing thoroughness with "don't overengineer" guidance
* Learning and Insights
** Technical Insights
- Claude Code loads skills from both ~/.claude/skills/ (global) AND .claude/skills/ (project-local)
- Project-local skills add to or shadow global - good for per-repo customization
- nix build --print-out-paths gives store path without building if cached
- direnv + nix build is lighter than devShell for simple cases
** Process Insights
- "Ultrathink" is a good trigger for deeper analysis
- Questioning assumptions early ("do you need flake.nix in every project?") saves design churn
- Agent-friendly design (like .skills manifest) is worth thinking about explicitly
** Architectural Insights
- Separation of concerns: manifest (.skills) vs loader (.envrc) vs runtime (symlinks)
- Agent context efficiency: brief blurb in CLAUDE.md, not full skill docs
- The .skills file serves multiple purposes: human config, agent query, agent edit
* Context for Future Work
** Open Questions
- Should we validate skill names? Currently fails silently if skill doesn't exist
- Should we support skill versions? e.g., `worklog@v1.2.0`
- Should there be a `skills` CLI? e.g., `skills add worklog`, `skills list`
- How to handle skills that need secrets (like web-research with KAGI_API_KEY)?
** Next Steps
- Survey existing repos for .envrc patterns
- Migrate pilot project to new .skills pattern
- Clean up beads.left.jsonl merge artifact
- Commit and push this session's work
** Related Work
- Previous: [[file:2025-11-09-nix-flake-module-development-opencode-skills-integration.org][Nix Flake Module Development]] - original HM module design
- Previous: [[file:2025-11-22-create-web-search-skill.org][Create Web Search Skill]] - skill that motivated this work
- Related: docs/CROSS-REPO-SKILL-COLLABORATION.md - Nix flake input pattern (for HM deployments)
- Created: docs/RFC-SKILLS-MANIFEST.md - this session's main artifact
* Raw Notes
Beads status at session end:
- 4 closed: skills-3o7 (nix fix), skills-pu4 (cleanup), skills-cnc (helper), skills-39g (RFC)
- 7 open: README updates, design decisions, code review items
Key insight: The question "how does an agent help configure skills?" led to the .skills manifest design. Agent-friendly != human-friendly, need both.
The pattern is intentionally minimal:
1. .skills file lists skill names
2. .envrc reads .skills and symlinks
3. CLAUDE.md tells agent about available skills
4. Agent can read/edit .skills, tell user to direnv reload
* Session Continuation: Pilot Migration and Flow Design
** Pilot Migration: orch
Successfully migrated orch project as pilot for .skills pattern:
- Created `.skills` manifest with `worklog`
- Updated `.envrc` to source helper and call `load_skills_from_manifest`
- Updated `.gitignore` to exclude `.claude/skills/` and `.opencode/skills/`
- Added Skills section to `AGENTS.md`
** Technical Fix: Local Nix Build
- Original default URL `git+ssh://git@forgejo.delmore.io/dan/skills.git` didn't resolve
- Changed to `git+file://$HOME/proj/skills` for offline/local development
- `path:` scheme failed due to `.beads/bd.sock` (unsupported file type)
- `git+file://` only includes git-tracked files, works correctly
** Verified Working
#+begin_src
orch/.claude/skills/worklog -> /nix/store/...-ai-skill-worklog
orch/.opencode/skills/worklog -> /nix/store/...-ai-skill-worklog
#+end_src
** Dotfiles Analysis
Explored how dotfiles manages Claude Code:
- `home/claude.nix` deploys 4 skills via Home Manager
- `~/.claude/settings.json` has `bd prime` hooks (global, not Nix-managed)
- Drift: dotfiles has 4 skills, skills repo has 8
- Global skills come from dotfiles copy, per-repo from skills repo directly
** Flow Design Discussion
Identified need to simplify per-repo flow. Current requires 4 file changes.
Options discussed:
1. Global direnv helper (add `load_project_skills` to direnvrc)
2. CLI tool (`skills init`, `skills add`)
3. Convention over configuration (auto-load if `.skills` exists)
Direction: Simplify with global direnv helper + team-facing RFC.
* Session Metrics
- Commits made: 0 (uncommitted)
- Files touched: 7+ (skills repo + orch pilot)
- Lines added/removed: ~500 lines new content
- New documentation: RFC-SKILLS-MANIFEST.md, PER-REPO-SKILLS.md
- Beads created: 9 issues
- Beads closed: 4 issues
- Pilot project: orch migrated successfully

View file

@ -18,6 +18,9 @@
"tufte-press"
"worklog"
"update-spec-kit"
"update-opencode"
"web-search"
"web-research"
];
in
flake-utils.lib.eachDefaultSystem

View file

@ -4,22 +4,6 @@ with lib;
let
cfg = config.services.ai-skills;
# Helper to install opencode-skills npm package
opencodeSkillsPlugin = pkgs.buildNpmPackage rec {
pname = "opencode-skills";
version = "0.1.0";
src = pkgs.fetchFromNpm {
name = pname;
version = version;
sha256 = ""; # TODO: Get actual hash
};
# Alternative: install from npm directly at runtime
# This is a placeholder - actual implementation would fetch from npm
};
in {
options.services.ai-skills = {
enable = mkEnableOption "AI agent skills for Claude Code and OpenCode";
@ -34,8 +18,11 @@ in {
- tufte-press: Generate study card JSON
- worklog: Create org-mode worklogs
- update-spec-kit: Update spec-kit ecosystem
- update-opencode: Update OpenCode via Nix
- web-search: Search the web via Claude
- web-research: Deep web research with multiple backends
'';
example = [ "worklog" "screenshot-latest" ];
example = [ "worklog" "web-search" ];
};
skillsPath = mkOption {
@ -55,12 +42,6 @@ in {
default = true;
description = "Deploy skills to OpenCode (~/.config/opencode/skills/)";
};
installOpencodePlugin = mkOption {
type = types.bool;
default = true;
description = "Install opencode-skills npm plugin";
};
};
config = mkIf cfg.enable {
@ -91,43 +72,6 @@ in {
}) cfg.skills
)
))
# OpenCode plugin installation
(mkIf (cfg.enableOpenCode && cfg.installOpencodePlugin) {
".config/opencode/package.json" = {
text = builtins.toJSON {
dependencies = {
"@opencode-ai/plugin" = "1.0.44";
"opencode-skills" = "^0.1.0";
};
};
};
})
];
# Ensure opencode-skills plugin is in config
home.activation.opencodeSkillsPlugin = mkIf (cfg.enableOpenCode && cfg.installOpencodePlugin) (
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
# Install npm dependencies for OpenCode
if [ -f "$HOME/.config/opencode/package.json" ]; then
cd "$HOME/.config/opencode"
if command -v bun &> /dev/null; then
${pkgs.bun}/bin/bun install
elif command -v npm &> /dev/null; then
${pkgs.nodejs}/bin/npm install
fi
fi
# Ensure plugin is enabled in config
CONFIG_FILE="$HOME/.config/opencode/config.json"
if [ -f "$CONFIG_FILE" ]; then
# Check if plugin array includes opencode-skills
if ! ${pkgs.jq}/bin/jq -e '.plugin | index("opencode-skills")' "$CONFIG_FILE" &> /dev/null; then
echo "Warning: opencode-skills plugin not in config.json plugin array"
echo "Add it manually: { \"plugin\": [\"opencode-skills\"] }"
fi
fi
''
);
};
}