From 9ce4c83a1779a9097d0a045d0c996d5ead800111 Mon Sep 17 00:00:00 2001 From: dan Date: Sun, 25 Jan 2026 11:49:29 -0800 Subject: [PATCH] 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. --- .../approach/2026-01-25-skill-organization.md | 150 ++++++++++++++++++ docs/intent/2026-01-25-skill-organization.md | 42 +++++ docs/work/2026-01-25-skill-organization.md | 74 +++++++++ modules/ai-skills.nix | 20 +++ skills.nix | 3 + skills/ralph-work-loop/README.md | 15 ++ skills/ralph-work-loop/SKILL.md | 51 ++++++ .../scripts/find-latest-work.sh | 25 +++ 8 files changed, 380 insertions(+) create mode 100644 docs/approach/2026-01-25-skill-organization.md create mode 100644 docs/intent/2026-01-25-skill-organization.md create mode 100644 docs/work/2026-01-25-skill-organization.md create mode 100644 skills/ralph-work-loop/README.md create mode 100644 skills/ralph-work-loop/SKILL.md create mode 100755 skills/ralph-work-loop/scripts/find-latest-work.sh diff --git a/docs/approach/2026-01-25-skill-organization.md b/docs/approach/2026-01-25-skill-organization.md new file mode 100644 index 0000000..4d1ec3d --- /dev/null +++ b/docs/approach/2026-01-25-skill-organization.md @@ -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// # Development (universal) + │ + │ deploy-skill.sh + ▼ +~/proj/dotfiles/skills// # Nix source (universal) + │ + │ home-manager rebuild + ▼ +~/.claude/skills// # Claude Code + Pi +~/.codex/skills// # Codex +~/.config/opencode/skills// # OpenCode + + +~/proj/skills/skills// # Development (pi-only) + │ + │ deploy-skill.sh --pi-only + ▼ +~/proj/dotfiles/pi/skills// # Nix source (pi-only) + │ + │ home-manager rebuild + ▼ +~/.pi/agent/skills// # 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 diff --git a/docs/intent/2026-01-25-skill-organization.md b/docs/intent/2026-01-25-skill-organization.md new file mode 100644 index 0000000..8274e3d --- /dev/null +++ b/docs/intent/2026-01-25-skill-organization.md @@ -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 diff --git a/docs/work/2026-01-25-skill-organization.md b/docs/work/2026-01-25-skill-organization.md new file mode 100644 index 0000000..32d9b44 --- /dev/null +++ b/docs/work/2026-01-25-skill-organization.md @@ -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 diff --git a/modules/ai-skills.nix b/modules/ai-skills.nix index 9bcf68d..4a67a27 100644 --- a/modules/ai-skills.nix +++ b/modules/ai-skills.nix @@ -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" = { diff --git a/skills.nix b/skills.nix index dab50ce..ce00cb5 100644 --- a/skills.nix +++ b/skills.nix @@ -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"; diff --git a/skills/ralph-work-loop/README.md b/skills/ralph-work-loop/README.md new file mode 100644 index 0000000..5411ea4 --- /dev/null +++ b/skills/ralph-work-loop/README.md @@ -0,0 +1,15 @@ +# Ralph Work Loop Skill + +Runs the Ralph Wiggum loop on an existing Work document. + +## Usage + +``` +/ralph start docs/work/.md +``` + +If you don't know the work doc, run: + +```bash +./.pi/skills/ralph-work-loop/scripts/find-latest-work.sh +``` diff --git a/skills/ralph-work-loop/SKILL.md b/skills/ralph-work-loop/SKILL.md new file mode 100644 index 0000000..3031f9e --- /dev/null +++ b/skills/ralph-work-loop/SKILL.md @@ -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 + ``` + 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 ` 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 ` to point directly to an existing Work doc. diff --git a/skills/ralph-work-loop/scripts/find-latest-work.sh b/skills/ralph-work-loop/scripts/find-latest-work.sh new file mode 100755 index 0000000..061e3cc --- /dev/null +++ b/skills/ralph-work-loop/scripts/find-latest-work.sh @@ -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}"