# Cross-Repo Skill Collaboration Strategy **Context**: Skills may be developed in one repo but deployed/modified in others **Example**: tufte-press skill - developed in `dan/skills`, deployed to `dan/ops-dev` **Decision**: Use skills repo as single source of truth, consume via Nix flake inputs **Philosophy**: Modern Nix with flakes, declarative deployment, version control ## Current Situation: tufte-press ### Lifecycle So Far 1. **2025-11-09 (skills repo)**: We built tufte-press skill - Location: `~/proj/skills/skills/tufte-press/` - Complete SKILL.md, README.md, example JSON - Committed to skills repository 2. **2025-11-09 (ops-dev deployment)**: They deployed to VM - Copied from `~/proj/skills/skills/tufte-press/` to `~/proj/ops-dev/skills/tufte-press/` - Deployed via NixOS environment.etc (flake bundling) - Now lives at `/etc/opencode/skills/tufte-press/` on ops-dev VM 3. **Current state**: Files are identical (verified by diff) - `SKILL.md` - identical - `README.md` - identical - `examples/lambda-calculus-example.json` - identical ### The Question **What happens when changes are needed?** - Who makes the change - us or them? - Where is the change made - skills repo or ops-dev repo? - How do changes sync between repos? - Who owns which version? ## Primary Pattern: Skills Repo as Single Source of Truth **Decision**: This repository (`dan/skills`) is the canonical source for all skills. Other projects consume via Nix flake inputs. **Rationale**: - Modern Nix with flakes is declarative and version-controlled - Clear ownership and maintenance responsibility - Automatic propagation of updates to all consumers - Consistent deployment across all environments - Leverages Nix's reproducibility guarantees ## Collaboration Models ### Model 1: Single Source of Truth via Flake Input (PRIMARY PATTERN ✅) **Approach**: Skills repo is canonical, others consume via Nix flake input **Architecture**: ``` ~/proj/skills/ (git@forgejo:dan/skills.git) ↓ [Nix flake input] ~/proj/ops-dev/flake.nix inputs.skills.url = "git+http://192.168.1.108:3000/dan/skills.git" ↓ [module import] NixOS configuration uses skills.lib.getSkillPath ↓ [deployment] /etc/opencode/skills/tufte-press → /nix/store/.../skills/tufte-press ``` **Workflow**: 1. **Changes happen in**: skills repo only 2. **Deployment**: `nix flake lock --update-input skills` in ops-dev, then rebuild 3. **Benefits**: - Single source of truth - Automatic propagation to all consumers - Clear ownership (skills repo maintainers) - Version pinning via flake.lock 4. **Trade-offs**: - Can't make quick local changes - Requires git commit + push to update - Dependency on skills repo availability **Use for**: All skills (this is the default pattern) ### Model 2: Local Copy with Manual Sync (DEVELOPMENT ONLY) **Approach**: Copy skill to destination repo, manually sync when needed **Architecture**: ``` ~/proj/skills/skills/tufte-press/ [original] ↓ [manual copy] ~/proj/ops-dev/skills/tufte-press/ [deployed copy] ↓ [flake bundling] /etc/opencode/skills/tufte-press/ [runtime] ``` **Workflow**: 1. **Changes can happen in**: Either repo 2. **Sync process**: ```bash # Push changes from ops-dev → skills repo cp -r ~/proj/ops-dev/skills/tufte-press/ ~/proj/skills/skills/ cd ~/proj/skills && git add skills/tufte-press/ && git commit -m "Update from ops-dev" # Pull changes from skills → ops-dev repo cp -r ~/proj/skills/skills/tufte-press/ ~/proj/ops-dev/skills/ cd ~/proj/ops-dev && git add skills/ && git commit -m "Update tufte-press from skills repo" ``` 3. **Benefits**: - Fast local iteration - No network dependency - Can experiment freely 4. **Trade-offs**: - Manual sync required - Risk of divergence - No clear source of truth - Must remember to sync changes **Use for**: - Temporary during initial skill development (before committing to skills repo) - Emergency hotfixes before proper deployment - **NOT for production use** ### Model 3: Git Submodule (NOT RECOMMENDED) **Approach**: ops-dev repo includes skills repo as submodule **Architecture**: ``` ~/proj/ops-dev/ skills/ → git submodule (points to dan/skills.git) ↓ [flake source] /nix/store/.../skills/tufte-press/ ``` **Workflow**: 1. **Changes happen in**: skills repo 2. **Update in ops-dev**: `git submodule update --remote` 3. **Benefits**: - Version control of dependency - Can pin to specific commit - Clear separation of concerns 4. **Trade-offs**: - Submodule complexity - Still need git operations to update - Can't make quick local edits **Use for**: Legacy compatibility only - use Model 1 instead **Why not recommended**: Adds submodule complexity without Nix benefits ### Model 4: Fork + Upstream (RARE CASES ONLY) **Approach**: Fork skill to project repo, selectively merge upstream changes **Architecture**: ``` ~/proj/skills/skills/tufte-press/ [upstream] ↓ [initial copy] ~/proj/ops-dev/skills/tufte-press/ [fork with modifications] ``` **Workflow**: 1. **Initial copy**: Copy skill from skills repo 2. **Local changes**: Modify freely in ops-dev repo 3. **Upstream changes**: Manually review and cherry-pick from skills repo 4. **Benefits**: - Full local control - Can diverge intentionally - Can still pull upstream improvements 5. **Trade-offs**: - Merge conflicts possible - Tracking upstream changes is manual - Unclear which changes should go back to upstream **Use for**: - Skills requiring heavy project-specific customization - Non-NixOS environments (copy the skill files manually) - When you need to diverge significantly from upstream **Better approach**: Request features in skills repo, use configuration options ## Recommended Approach by Skill Type ### All Skills (Default Pattern) **Use Model 1**: Nix flake input from skills repo - **Why**: Single source of truth, version controlled, declarative - **Deployment**: All projects pull from skills repo via flake input - **Changes**: 1. Make changes in skills repo 2. Commit and push to git 3. Update flake.lock in consumer projects 4. Rebuild systems - **Example**: ```nix # ops-dev/flake.nix inputs.skills.url = "git+http://192.168.1.108:3000/dan/skills.git"; # Import and use the module imports = [ inputs.skills.nixosModules.ai-skills ]; services.ai-skills = { enable = true; selectedSkills = [ "tufte-press" "worklog" "screenshot-latest" ]; deployTargets = [ "claude" "opencode" ]; }; ``` ### During Development (Before Skill is Ready) **Use Model 2 temporarily**: Local copy for rapid iteration - **Why**: Fast feedback loop while building/testing - **Process**: 1. Create skill in skills repo on a branch or WIP commit 2. Copy to consumer project for testing 3. Iterate rapidly with local changes 4. When stable, commit to skills repo 5. Switch consumer to flake input (Model 1) - **Duration**: Hours to days, not weeks - **Transition**: Always move to Model 1 once stable ## Implementation Plan: Migrate Existing Skills to Flake Input ### Tufte-Press Migration (ops-dev) **Current State**: - ✅ Skill exists in skills repo at `skills/tufte-press/` - ✅ Added to flake packages - ✅ Deployed to ops-dev VM via local copy (Model 2) - ✅ Files are identical between repos **Target State**: Consume via flake input (Model 1) **Rationale**: 1. Skill is stable and documented 2. Clear shared value (Tufte-inspired study cards) 3. No urgent need for project-specific changes 4. Better pattern for future skills **Migration Steps**: 1. **Skills repo** (already done): - ✅ Skill exists at `skills/tufte-press/` - ✅ Added to flake packages - ✅ Available via `skillsFlake.packages.${system}.tufte-press` 2. **ops-dev repo** (to do): ```nix # flake.nix - add input inputs.skills = { url = "git+http://192.168.1.108:3000/dan/skills.git"; inputs.nixpkgs.follows = "nixpkgs"; }; # Use the module imports = [ inputs.skills.nixosModules.ai-skills ]; services.ai-skills = { enable = true; selectedSkills = [ "tufte-press" "worklog" ]; deployTargets = [ "claude" "opencode" ]; }; ``` 3. **Remove local copy**: ```bash cd ~/proj/ops-dev rm -rf skills/tufte-press # Now comes from flake input git add -A && git commit -m "Switch tufte-press to skills repo flake input" ``` 4. **Deploy**: ```bash ssh root@192.168.1.73 "cd /home/dev/ops-dev && nixos-rebuild switch --flake .#dev" ``` **Future Updates**: ```bash # Update to latest skills cd ~/proj/ops-dev nix flake lock --update-input skills ssh root@192.168.1.73 "cd /home/dev/ops-dev && nixos-rebuild switch --flake .#dev" ``` ## Worklog-Compression Skill Strategy **Context**: prox-setup repo has mature worklog compression workflow ### Development Approach **Phase 1** (Development - use Model 2 temporarily): - Build skill in skills repo (commit to main or feature branch) - Copy to ops-dev for testing if needed - Fast iteration with local changes - Duration: Hours to 1-2 days **Phase 2** (Deployment - switch to Model 1): - Skill is working and tested - Add to skills repo flake packages (if not already) - ops-dev switches to flake input - Remove local copy **Phase 3** (Maintenance - stay on Model 1): - All changes happen in skills repo - Consumers update via `nix flake lock --update-input skills` - Version controlled and declarative **No forking or local copies in production** - this keeps the architecture clean ## Sync Coordination Practices ### Before Making Changes **Check with stakeholders**: - "Planning to update tufte-press skill - anyone else working on it?" - Prevents conflicting changes ### After Making Changes **Notify consumers**: - Comment in shared chat: "Updated tufte-press skill - added X feature" - Update CHANGELOG in skill directory - Tag releases for significant changes ### For Breaking Changes **Version carefully**: - Consider creating `tufte-press-v2` skill - Deprecate old version gracefully - Document migration path ### For Experimental Changes **Use branches**: - `tufte-press-experimental-latex-engine` skill name - Or git branches in skills repo - Don't break the main version ## Summary ### Quick Decision Tree ``` Is the skill ready for use? ├─ Yes → Model 1 (Nix flake input) ✅ DEFAULT │ - All stable skills │ - tufte-press │ - worklog │ - screenshot-latest │ - niri-window-capture │ - Everything in production │ └─ No, still developing → Model 2 (Temporary local copy) - Use for 1-2 days max - Switch to Model 1 when stable - Don't leave in this state ``` ### Key Principles 1. **Default to Model 1** - Flake input is the standard pattern 2. **Skills repo is source of truth** - All changes happen here 3. **Model 2 is temporary only** - Use during development, not production 4. **No forking or local modifications** - Request features instead 5. **Modern Nix with flakes** - Declarative, version-controlled, reproducible 6. **Always communicate** before/after significant changes 7. **Version breaking changes** carefully (consider skill-v2 naming) ## Next Actions 1. ✅ Document collaboration patterns (this file) 2. ⏳ Migrate tufte-press in ops-dev to flake input (when ready) 3. ⏳ Build worklog-compression skill (Model 2 initially) 4. ⏳ Test skills Nix module on ops-dev VM 5. ⏳ Document per-skill deployment decisions in each SKILL.md --- **Related Documentation**: - `AGENTS.md` - Skill development guidelines - `NIX-FLAKE-USAGE.md` - How to consume skills via Nix - `docs/SKILL-DEVELOPMENT-STRATEGY-prox-setup.md` - Hybrid development approach