- Transform tufte-press from reference guide to conversation-aware generator - Add JSON generation from conversation context following strict schema - Create build automation scripts with Nix environment handling - Integrate CUPS printing with duplex support - Add comprehensive workflow documentation Scripts added: - skills/tufte-press/scripts/generate-and-build.sh (242 lines) - skills/tufte-press/scripts/build-card.sh (23 lines) Documentation: - Updated SKILL.md with complete workflow instructions (370 lines) - Updated README.md with usage examples (340 lines) - Created SKILL-DEVELOPMENT-STRATEGY-tufte-press.md (450 lines) - Added worklog: 2025-11-10-tufte-press-skill-evolution.org Features: - Agent generates valid JSON from conversation - Schema validation before build (catches errors early) - Automatic Nix shell entry for dependencies - PDF build via tufte-press toolchain - Optional print with duplex support - Self-contained margin notes enforced - Complete end-to-end testing Workflow: Conversation → JSON → Validate → Build → Print Related: niri-window-capture, screenshot-latest, worklog skills
12 KiB
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
-
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
- Location:
-
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
- Copied from
-
Current state: Files are identical (verified by diff)
SKILL.md- identicalREADME.md- identicalexamples/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:
- Changes happen in: skills repo only
- Deployment:
nix flake lock --update-input skillsin ops-dev, then rebuild - Benefits:
- Single source of truth
- Automatic propagation to all consumers
- Clear ownership (skills repo maintainers)
- Version pinning via flake.lock
- 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:
- Changes can happen in: Either repo
- Sync process:
# 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" - Benefits:
- Fast local iteration
- No network dependency
- Can experiment freely
- 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:
- Changes happen in: skills repo
- Update in ops-dev:
git submodule update --remote - Benefits:
- Version control of dependency
- Can pin to specific commit
- Clear separation of concerns
- 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:
- Initial copy: Copy skill from skills repo
- Local changes: Modify freely in ops-dev repo
- Upstream changes: Manually review and cherry-pick from skills repo
- Benefits:
- Full local control
- Can diverge intentionally
- Can still pull upstream improvements
- 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:
- Make changes in skills repo
- Commit and push to git
- Update flake.lock in consumer projects
- Rebuild systems
- Example:
# 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:
- Create skill in skills repo on a branch or WIP commit
- Copy to consumer project for testing
- Iterate rapidly with local changes
- When stable, commit to skills repo
- 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:
- Skill is stable and documented
- Clear shared value (Tufte-inspired study cards)
- No urgent need for project-specific changes
- Better pattern for future skills
Migration Steps:
-
Skills repo (already done):
- ✅ Skill exists at
skills/tufte-press/ - ✅ Added to flake packages
- ✅ Available via
skillsFlake.packages.${system}.tufte-press
- ✅ Skill exists at
-
ops-dev repo (to do):
# 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" ]; }; -
Remove local copy:
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" -
Deploy:
ssh root@192.168.1.73 "cd /home/dev/ops-dev && nixos-rebuild switch --flake .#dev"
Future Updates:
# 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-v2skill - Deprecate old version gracefully
- Document migration path
For Experimental Changes
Use branches:
tufte-press-experimental-latex-engineskill 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
- Default to Model 1 - Flake input is the standard pattern
- Skills repo is source of truth - All changes happen here
- Model 2 is temporary only - Use during development, not production
- No forking or local modifications - Request features instead
- Modern Nix with flakes - Declarative, version-controlled, reproducible
- Always communicate before/after significant changes
- Version breaking changes carefully (consider skill-v2 naming)
Next Actions
- ✅ Document collaboration patterns (this file)
- ⏳ Migrate tufte-press in ops-dev to flake input (when ready)
- ⏳ Build worklog-compression skill (Model 2 initially)
- ⏳ Test skills Nix module on ops-dev VM
- ⏳ Document per-skill deployment decisions in each SKILL.md
Related Documentation:
AGENTS.md- Skill development guidelinesNIX-FLAKE-USAGE.md- How to consume skills via Nixdocs/SKILL-DEVELOPMENT-STRATEGY-prox-setup.md- Hybrid development approach