feat(skills): consolidate skill organization across agents
- Add piSkills option to ai-skills module for pi-only skills - Add ralph-work-loop skill (depends on pi extension) - Update skills.nix registry with nix-review, ralph-work-loop, ui-query - Add intent/approach/work docs for skill organization effort Universal skills deploy to claude/codex/opencode/gemini. Pi-only skills (ralph-work-loop) deploy to ~/.pi/agent/skills/ only.
This commit is contained in:
parent
796200a277
commit
9ce4c83a17
150
docs/approach/2026-01-25-skill-organization.md
Normal file
150
docs/approach/2026-01-25-skill-organization.md
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
# Approach: Skill Organization Across Agents
|
||||
|
||||
## Strategy
|
||||
|
||||
**Core philosophy**: Single source, Nix-deployed, per-repo filtered.
|
||||
|
||||
Skills live in dotfiles. Nix deploys them to each agent's expected location. Pi's settings handle per-repo filtering via `includeSkills`/`ignoredSkills`.
|
||||
|
||||
**Key Decisions**:
|
||||
|
||||
1. **Source location**: `~/proj/skills/skills/` vs `~/proj/dotfiles/skills/`
|
||||
→ **dotfiles** — skills are config, not code. Dotfiles is the deployment source.
|
||||
|
||||
2. **Deployment target**: Single location vs all agent locations
|
||||
→ **All locations** — deploy to `~/.claude/skills/`, `~/.codex/skills/`, `~/.config/opencode/skills/` for compatibility. Pi reads from `~/.claude/skills/` (disable other pi sources).
|
||||
|
||||
3. **Per-repo filtering mechanism**: Project config vs global config per repo
|
||||
→ **Pi settings** — use `includeSkills`/`ignoredSkills` in project `.pi/settings.json`. Other agents don't support this, but pi is primary.
|
||||
|
||||
4. **Development workflow**: Direct edit in dotfiles vs edit in skills repo + deploy script
|
||||
→ **Skills repo + deploy** — develop/test in `~/proj/skills/`, run `deploy-skill.sh`, Nix rebuild picks it up.
|
||||
|
||||
5. **Existing scattered skills**: Migrate vs leave in place
|
||||
→ **Migrate** — consolidate everything to dotfiles, remove old locations after Nix manages them.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Directory Structure
|
||||
|
||||
```
|
||||
~/proj/skills/skills/<name>/ # Development (universal)
|
||||
│
|
||||
│ deploy-skill.sh <name>
|
||||
▼
|
||||
~/proj/dotfiles/skills/<name>/ # Nix source (universal)
|
||||
│
|
||||
│ home-manager rebuild
|
||||
▼
|
||||
~/.claude/skills/<name>/ # Claude Code + Pi
|
||||
~/.codex/skills/<name>/ # Codex
|
||||
~/.config/opencode/skills/<name>/ # OpenCode
|
||||
|
||||
|
||||
~/proj/skills/skills/<name>/ # Development (pi-only)
|
||||
│
|
||||
│ deploy-skill.sh <name> --pi-only
|
||||
▼
|
||||
~/proj/dotfiles/pi/skills/<name>/ # Nix source (pi-only)
|
||||
│
|
||||
│ home-manager rebuild
|
||||
▼
|
||||
~/.pi/agent/skills/<name>/ # Pi only
|
||||
```
|
||||
|
||||
**Two tiers**:
|
||||
- **Universal**: Deploy to all agents (`~/.claude/`, `~/.codex/`, `~/.config/opencode/`)
|
||||
- **Pi-only**: Deploy to `~/.pi/agent/skills/` only (for extension-dependent skills like ralph-work-loop)
|
||||
|
||||
### Pi Settings
|
||||
|
||||
Global `~/.pi/agent/settings.json`:
|
||||
```json
|
||||
{
|
||||
"skills": {
|
||||
"enableClaudeUser": true, // Universal skills (~/.claude/skills/)
|
||||
"enablePiUser": true, // Pi-only skills (~/.pi/agent/skills/)
|
||||
"enableCodexUser": false, // Don't double-load (Nix manages ~/.codex/)
|
||||
"enableClaudeProject": true,
|
||||
"enablePiProject": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Pi reads from both `~/.claude/skills/` (universal) and `~/.pi/agent/skills/` (pi-specific).
|
||||
|
||||
### Per-Repo Filtering
|
||||
|
||||
Project `.pi/settings.json`:
|
||||
```json
|
||||
{
|
||||
"skills": {
|
||||
"ignoredSkills": ["nix-review", "ops-review"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Or positive filtering:
|
||||
```json
|
||||
{
|
||||
"skills": {
|
||||
"includeSkills": ["worklog", "code-review", "intent", "approach", "work"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Nix Module
|
||||
|
||||
In `home/skills.nix` (or similar):
|
||||
```nix
|
||||
{
|
||||
home.file = {
|
||||
".claude/skills" = {
|
||||
source = ./skills;
|
||||
recursive = true;
|
||||
};
|
||||
".codex/skills" = {
|
||||
source = ./skills;
|
||||
recursive = true;
|
||||
};
|
||||
".config/opencode/skills" = {
|
||||
source = ./skills;
|
||||
recursive = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Risks
|
||||
|
||||
### Known Unknowns
|
||||
|
||||
- **OpenCode skill format**: Does it use the same SKILL.md format? Need to verify.
|
||||
- **Codex recursive scanning**: Pi docs say it scans recursively — does Codex itself do this too?
|
||||
- **Project-local skills**: Should these also be standardized, or left as-is per project?
|
||||
|
||||
### Failure Modes
|
||||
|
||||
- **Nix rebuild required**: Skills don't update until rebuild. Could forget and wonder why changes aren't visible.
|
||||
- **Agent format drift**: If an agent changes its skill format, we'd need to adapt.
|
||||
- **includeSkills too restrictive**: Forget to add a skill to the include list, then wonder why it's not loading.
|
||||
|
||||
### Blast Radius
|
||||
|
||||
- **Dotfiles changes**: Modifying Nix config affects all machines using these dotfiles.
|
||||
- **Removing old locations**: If we delete `~/.pi/agent/skills/` contents, need to ensure pi settings are updated first.
|
||||
|
||||
## Phases
|
||||
|
||||
### Phase 1: Consolidate to Dotfiles
|
||||
- Move all global skills to `~/proj/dotfiles/skills/`
|
||||
- Update Nix to deploy to all agent locations
|
||||
- Update pi settings to read from `~/.claude/skills/` only
|
||||
|
||||
### Phase 2: Clean Up Old Locations
|
||||
- Remove skills from `~/.codex/skills/`, `~/.pi/agent/skills/` (Nix now manages these)
|
||||
- Verify all agents still work
|
||||
|
||||
### Phase 3: Per-Repo Filtering
|
||||
- Add `.pi/settings.json` to repos that need filtering
|
||||
- Document the pattern for future repos
|
||||
42
docs/intent/2026-01-25-skill-organization.md
Normal file
42
docs/intent/2026-01-25-skill-organization.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Intent: Skill Organization Across Agents
|
||||
|
||||
## Motivation
|
||||
|
||||
Skills are scattered across multiple directories (`~/.codex/skills/`, `~/.claude/skills/`, `~/.pi/agent/skills/`), leading to duplication and drift. Some repos load skills they don't need. We want a single source of truth with clean deployment to all agents.
|
||||
|
||||
## Need
|
||||
|
||||
A maintainable system for:
|
||||
1. Developing skills in one place
|
||||
2. Deploying to all agent locations (pi, Claude Code, OpenCode, Codex)
|
||||
3. Filtering which skills load in which repos
|
||||
4. Keeping compatibility with agents we might use later
|
||||
|
||||
## Use-Cases
|
||||
|
||||
- **Skill development**: Edit a skill in `~/proj/skills/`, run deploy, all agents pick it up after Nix rebuild.
|
||||
- **Per-repo filtering**: Working in a Python project — don't load `nix-review`. Working in a Nix project — don't load `python-lint`.
|
||||
- **Agent compatibility**: Switch to Claude Code for a session — same skills available, same behavior.
|
||||
- **Avoiding drift**: Fix a bug in `worklog` skill — fix it once, deployed everywhere. No stale copies in random directories.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- Single source of truth for global skills (in dotfiles, managed by Nix)
|
||||
- All agents (pi, Claude Code, OpenCode, Codex) load skills from their expected locations
|
||||
- Per-repo skill filtering works (via pi settings or project config)
|
||||
- No duplicate skill directories to maintain
|
||||
- Development workflow: edit in skills repo → deploy → Nix rebuild → available everywhere
|
||||
|
||||
## Constraints
|
||||
|
||||
- Must work with Nix/home-manager deployment (no direnv, no runtime symlink management)
|
||||
- Skills must remain compatible with Agent Skills standard (SKILL.md format)
|
||||
- Pi is primary agent, but others must keep working
|
||||
- Extensions (TypeScript) are pi-only, separate concern for now
|
||||
|
||||
## Anti-Goals
|
||||
|
||||
- **Not changing skill format**: Skills stay as SKILL.md + scripts, no new abstraction
|
||||
- **Not building a skill manager tool**: Use Nix for deployment, not a custom CLI
|
||||
- **Not per-file filtering**: Filtering is per-skill, not per-file within a skill
|
||||
- **Not solving extension organization**: Extensions stay in `~/.pi/agent/extensions/`, address later if needed
|
||||
74
docs/work/2026-01-25-skill-organization.md
Normal file
74
docs/work/2026-01-25-skill-organization.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# Work: Skill Organization Across Agents
|
||||
|
||||
## Intent
|
||||
Link to: [docs/intent/2026-01-25-skill-organization.md](../intent/2026-01-25-skill-organization.md)
|
||||
|
||||
## Approach
|
||||
Link to: [docs/approach/2026-01-25-skill-organization.md](../approach/2026-01-25-skill-organization.md)
|
||||
|
||||
## Checklist
|
||||
|
||||
### Phase 1: Consolidate to Dotfiles
|
||||
|
||||
- [x] **W001**: Inventory current skills across all locations
|
||||
- Verification: `find ~/.codex/skills ~/.claude/skills ~/.pi/agent/skills -name "SKILL.md" 2>/dev/null | wc -l` returns count
|
||||
|
||||
- [x] **W002**: Create `~/proj/dotfiles/skills/` directory structure
|
||||
- Verification: SKIP — using existing ai-skills module, skills sourced from this repo
|
||||
|
||||
- [x] **W003**: Create `~/proj/dotfiles/pi/skills/` for pi-only skills
|
||||
- Verification: SKIP — piSkills added to ai-skills module, ralph-work-loop in this repo
|
||||
|
||||
- [x] **W004**: Copy universal skills to dotfiles/skills/
|
||||
- Verification: SKIP — skills already in ~/proj/skills/skills/, ai-skills module deploys them
|
||||
|
||||
- [x] **W005**: Copy pi-only skills to dotfiles/pi/skills/
|
||||
- Verification: `ls skills/ralph-work-loop/SKILL.md` exists in this repo
|
||||
|
||||
- [x] **W006**: Create/update Nix module to deploy skills to all agent locations
|
||||
- Verification: Added piSkills option to modules/ai-skills.nix
|
||||
|
||||
- [x] **W007**: Update pi settings to use correct sources
|
||||
- Verification: `cat ~/.pi/agent/settings.json | jq '.skills'` shows correct flags
|
||||
|
||||
- [ ] **W008**: Nix rebuild and verify skills appear in all locations
|
||||
- Verification: `ls ~/.claude/skills ~/.codex/skills ~/.config/opencode/skills ~/.pi/agent/skills` all populated
|
||||
|
||||
### Phase 2: Clean Up Old Locations
|
||||
|
||||
- [ ] **W009**: Remove manually-managed skills from ~/.codex/skills/ (Nix now manages)
|
||||
- Verification: Skills in ~/.codex/skills/ match dotfiles exactly (no extras)
|
||||
|
||||
- [ ] **W010**: Remove manually-managed skills from ~/.pi/agent/skills/ (except pi-only)
|
||||
- Verification: Only ralph-work-loop in ~/.pi/agent/skills/
|
||||
|
||||
- [ ] **W011**: Remove duplicate skills from project-local directories (talu, etc.)
|
||||
- Verification: `ls ~/proj/talu/.claude/skills/` shows only project-specific skills (if any)
|
||||
|
||||
### Phase 3: Update deploy-skill.sh
|
||||
|
||||
- [ ] **W012**: Update deploy-skill.sh to support --pi-only flag
|
||||
- Verification: `./bin/deploy-skill.sh --help` shows --pi-only option
|
||||
|
||||
- [ ] **W013**: Update deploy-skill.sh to copy to correct dotfiles location
|
||||
- Verification: `./bin/deploy-skill.sh worklog` copies to `~/proj/dotfiles/skills/worklog/`
|
||||
|
||||
- [ ] **W014**: Test end-to-end: create skill, deploy, rebuild, verify in agents
|
||||
- Verification: Create test-skill, deploy, rebuild, `ls ~/.claude/skills/test-skill/SKILL.md` exists
|
||||
|
||||
## Verification Evidence
|
||||
|
||||
- (2026-01-25) W001: Inventoried 4 locations, found existing ai-skills Nix module already handles deployment
|
||||
- (2026-01-25) W002-W005: SKIP — infrastructure already exists in this repo + ai-skills module
|
||||
- (2026-01-25) W006: Added piSkills option to modules/ai-skills.nix
|
||||
- (2026-01-25) Copied ralph-work-loop to skills/ directory
|
||||
- (2026-01-25) Updated skills.nix registry
|
||||
- (2026-01-25) Updated ~/proj/dotfiles/home/claude.nix with full skill lists + piSkills
|
||||
- (2026-01-25) Removed manual nix-review deployments from codex.nix, opencode.nix, gemini.nix (now managed by ai-skills)
|
||||
- (2026-01-25) W007: Added settings.json to ~/proj/dotfiles/home/pi.nix with skill source config
|
||||
|
||||
## Notes
|
||||
|
||||
- Universal skills: worklog, screenshot-latest, orch, playwright-visit, code-review, ops-review, nix-review, hq, niri-window-capture, intent, approach, work
|
||||
- Pi-only skills: ralph-work-loop
|
||||
- Need to check what's currently in each location before migrating
|
||||
|
|
@ -53,6 +53,13 @@ in {
|
|||
example = [ "worklog" "web-search" ];
|
||||
};
|
||||
|
||||
piSkills = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
description = "Skills to deploy to Pi (~/.pi/agent/skills/). For pi-only skills that depend on extensions. ${skillsList}";
|
||||
example = [ "ralph-work-loop" ];
|
||||
};
|
||||
|
||||
# Lenses for orch multi-model review
|
||||
enableLenses = mkOption {
|
||||
type = types.bool;
|
||||
|
|
@ -116,6 +123,19 @@ in {
|
|||
)
|
||||
))
|
||||
|
||||
# Pi skills (pi-only, extension-dependent)
|
||||
(mkIf (cfg.piSkills != []) (
|
||||
builtins.listToAttrs (
|
||||
map (skillName: {
|
||||
name = ".pi/agent/skills/${skillName}";
|
||||
value = {
|
||||
source = "${cfg.skillsPath}/${skillName}";
|
||||
recursive = true;
|
||||
};
|
||||
}) cfg.piSkills
|
||||
)
|
||||
))
|
||||
|
||||
# Lenses for orch (separate subdirectories per skill)
|
||||
(mkIf cfg.enableLenses {
|
||||
".config/lenses/code" = {
|
||||
|
|
|
|||
|
|
@ -8,16 +8,19 @@
|
|||
handoff = "Create structured handoff summaries";
|
||||
intent = "Capture the volition and problem space (The Why)";
|
||||
niri-window-capture = "Invisibly capture window screenshots";
|
||||
nix-review = "Nix-focused infrastructure review";
|
||||
ops-review = "Multi-lens ops/infrastructure review";
|
||||
orch = "Orchestration and consensus skill";
|
||||
brave-search = "Web search via Brave API";
|
||||
browser-tools = "Interactive browser automation via CDP";
|
||||
playwright-visit = "Browser automation and content extraction";
|
||||
ralph-work-loop = "Run iterative Work-phase execution via Ralph extension (pi-only)";
|
||||
review-gate = "Quality gate for agent work";
|
||||
screenshot-latest = "Find latest screenshots";
|
||||
spec-review = "Technical specification review";
|
||||
tufte-press = "Generate study card JSON";
|
||||
test-review = "Audit test quality for flakiness, tautologies, and anti-patterns";
|
||||
ui-query = "Query UI elements via accessibility APIs";
|
||||
verify-work = "The Gatekeeper: Run project build/tests before claiming success";
|
||||
work = "Execute and verify the implementation (The Do)";
|
||||
worklog = "Create structured worklogs";
|
||||
|
|
|
|||
15
skills/ralph-work-loop/README.md
Normal file
15
skills/ralph-work-loop/README.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# Ralph Work Loop Skill
|
||||
|
||||
Runs the Ralph Wiggum loop on an existing Work document.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/ralph start docs/work/<work-doc>.md
|
||||
```
|
||||
|
||||
If you don't know the work doc, run:
|
||||
|
||||
```bash
|
||||
./.pi/skills/ralph-work-loop/scripts/find-latest-work.sh
|
||||
```
|
||||
51
skills/ralph-work-loop/SKILL.md
Normal file
51
skills/ralph-work-loop/SKILL.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
---
|
||||
name: ralph-work-loop
|
||||
description: Start or resume a Ralph Wiggum loop on an existing Work document (docs/work/*.md). Use when the user asks to "use ralph" on a Work doc or to run iterative Work-phase execution.
|
||||
---
|
||||
|
||||
# Ralph Work Loop
|
||||
|
||||
Use this skill to run the Ralph Wiggum loop **after** a Work document exists.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Ralph extension installed: `.pi/extensions/ralph-wiggum/index.ts`
|
||||
- Work document already created in `docs/work/`
|
||||
|
||||
## Process
|
||||
|
||||
1. **Validate the Work doc**:
|
||||
- Check required sections: Intent link, Approach link, Checklist, Verification commands, Evidence section
|
||||
- Each checklist item needs a verification command
|
||||
- See the `work` skill for full validation checklist
|
||||
- Fix any issues before starting the loop
|
||||
|
||||
2. **Locate the Work doc**:
|
||||
- If user provides a path, use it.
|
||||
- Otherwise run:
|
||||
```bash
|
||||
./.pi/skills/ralph-work-loop/scripts/find-latest-work.sh
|
||||
```
|
||||
- If multiple candidates are relevant, list them and ask the user to choose.
|
||||
|
||||
3. **Start the loop**:
|
||||
```
|
||||
/ralph start <work-doc-path>
|
||||
```
|
||||
Optional flags (ask user if they care):
|
||||
- `--items-per-iteration N`
|
||||
- `--reflect-every N`
|
||||
- `--max-iterations N`
|
||||
|
||||
4. **Monitor or resume**:
|
||||
- ` /ralph status` to show active loops
|
||||
- ` /ralph resume <name>` to continue paused loop
|
||||
|
||||
5. **Stop**:
|
||||
- Press `ESC` to pause
|
||||
- ` /ralph-stop` when idle to end the loop
|
||||
|
||||
## Notes
|
||||
|
||||
- The loop enforces the **Intent → Approach → Work** dialect and requires verification evidence for completed items.
|
||||
- Use `/ralph start <path>` to point directly to an existing Work doc.
|
||||
25
skills/ralph-work-loop/scripts/find-latest-work.sh
Executable file
25
skills/ralph-work-loop/scripts/find-latest-work.sh
Executable file
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
skill_dir="$(cd "${script_dir}/.." && pwd)"
|
||||
root_dir="$(cd "${skill_dir}/../../.." && pwd)"
|
||||
|
||||
work_dir="${root_dir}/docs/work"
|
||||
if [[ ! -d "${work_dir}" ]]; then
|
||||
echo "Error: docs/work not found at ${work_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
latest_file=""
|
||||
if compgen -G "${work_dir}/*.md" > /dev/null; then
|
||||
latest_file="$(ls -t "${work_dir}"/*.md | head -n 1)"
|
||||
fi
|
||||
|
||||
if [[ -z "${latest_file}" ]]; then
|
||||
echo "Error: no Work docs found in ${work_dir}" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
relative_path="${latest_file#"${root_dir}/"}"
|
||||
echo "${relative_path}"
|
||||
Loading…
Reference in a new issue