skills/DEPLOYMENT.md
dan d8c2e92f0a Initial commit: Agentic coding skills repository
- Add comprehensive documentation (README, WORKFLOW, DEPLOYMENT)
- Add skill template for creating new skills
- Port worklog skill from dotfiles (org-mode session documentation)
- Port update-spec-kit skill from dotfiles (ecosystem updates)
- Include spec-kit framework for structured development
- Add OpenCode commands for spec-kit workflow integration

Repository provides unified skill development for both Claude Code and OpenCode agents.
2025-11-08 10:55:15 -08:00

10 KiB

Deployment Guide

This guide covers all deployment methods for skills to both Claude Code and OpenCode.

Quick Reference

Method Use Case Pros Cons
Symlink Active development Live updates Manual per-skill
Copy Testing specific version Isolated Must re-copy for updates
Nix Home Manager Production (NixOS) Declarative, versioned Requires rebuild
Git Submodule Multi-repo sharing Centralized updates More complexity

Best for active development - changes in repo immediately available to agent.

Claude Code

# Single skill
ln -s $(pwd)/skills/worklog ~/.claude/skills/worklog

# All skills
for skill in skills/*/; do
    skill_name=$(basename "$skill")
    if [ "$skill_name" != "template" ]; then
        ln -s "$(pwd)/skills/$skill_name" ~/.claude/skills/$skill_name
    fi
done

OpenCode

# Single skill
ln -s $(pwd)/skills/worklog ~/.config/opencode/skills/worklog

# All skills
for skill in skills/*/; do
    skill_name=$(basename "$skill")
    if [ "$skill_name" != "template" ]; then
        ln -s "$(pwd)/skills/$skill_name" ~/.config/opencode/skills/$skill_name
    fi
done
# Claude Code
ls -la ~/.claude/skills/

# OpenCode
ls -la ~/.config/opencode/skills/
# Claude Code - single skill
rm ~/.claude/skills/worklog

# OpenCode - all skills (keeps directories, removes symlinks)
find ~/.config/opencode/skills -type l -delete

Method 2: Copy Deployment (Testing)

Best for testing specific versions without affecting your main deployment.

Claude Code

# Single skill
cp -r skills/worklog ~/.claude/skills/

# All skills (excluding template)
for skill in skills/*/; do
    skill_name=$(basename "$skill")
    if [ "$skill_name" != "template" ]; then
        cp -r "skills/$skill_name" ~/.claude/skills/
    fi
done

OpenCode

# Single skill
cp -r skills/worklog ~/.config/opencode/skills/

# All skills (excluding template)
for skill in skills/*/; do
    skill_name=$(basename "$skill")
    if [ "$skill_name" != "template" ]; then
        cp -r "skills/$skill_name" ~/.config/opencode/skills/
    fi
done

Update After Changes

# Must re-copy after making changes
cp -r skills/worklog ~/.claude/skills/
cp -r skills/worklog ~/.config/opencode/skills/

Method 3: Nix Home Manager (Production)

Best for NixOS users - declarative, version-controlled, atomic deployments.

Configuration

Add to your home.nix or equivalent:

{ config, pkgs, ... }:

{
  # Claude Code skills
  home.file.".claude/skills/worklog" = {
    source = /home/user/proj/skills/skills/worklog;
    recursive = true;
  };

  home.file.".claude/skills/update-spec-kit" = {
    source = /home/user/proj/skills/skills/update-spec-kit;
    recursive = true;
  };

  # OpenCode skills
  home.file.".config/opencode/skills/worklog" = {
    source = /home/user/proj/skills/skills/worklog;
    recursive = true;
  };

  home.file.".config/opencode/skills/update-spec-kit" = {
    source = /home/user/proj/skills/skills/update-spec-kit;
    recursive = true;
  };

  # OpenCode plugin configuration
  home.file.".config/opencode/config.json".text = builtins.toJSON {
    plugin = [ "opencode-skills" ];
    # ... other config
  };
}

Deploy All Skills Programmatically

For many skills, use a loop:

{ config, pkgs, lib, ... }:

let
  skillsPath = /home/user/proj/skills/skills;
  
  # List of skills to deploy (exclude template)
  skills = [
    "worklog"
    "update-spec-kit"
    # Add more skills here
  ];

  # Generate home.file entries for a skill
  mkSkillDeployment = skillName: {
    ".claude/skills/${skillName}" = {
      source = "${skillsPath}/${skillName}";
      recursive = true;
    };
    ".config/opencode/skills/${skillName}" = {
      source = "${skillsPath}/${skillName}";
      recursive = true;
    };
  };

  # Merge all skill deployments
  allSkillDeployments = lib.foldl' (acc: skill: acc // (mkSkillDeployment skill)) {} skills;

in {
  home.file = allSkillDeployments // {
    # Other file configurations
    ".config/opencode/config.json".text = builtins.toJSON {
      plugin = [ "opencode-skills" ];
    };
  };
}

Apply Configuration

# Home Manager standalone
home-manager switch

# NixOS with flake
sudo nixos-rebuild switch --flake .#hostname

# Test first
sudo nixos-rebuild test --flake .#hostname

Rollback

# Home Manager
home-manager generations
home-manager switch --rollback

# NixOS
sudo nixos-rebuild switch --rollback

Method 4: Git Submodule (Shared Projects)

Best when multiple repositories need to share the same skills.

Setup in Target Repository

# In your project repository
cd ~/proj/my-project

# Add skills as submodule
git submodule add https://github.com/yourusername/skills.git .skills

# Initialize submodule
git submodule update --init --recursive

Deploy from Submodule

# Create deployment script: scripts/deploy-skills.sh
#!/usr/bin/env bash
set -euo pipefail

SKILLS_DIR=".skills/skills"

# Deploy to Claude Code
for skill in "$SKILLS_DIR"/*; do
    skill_name=$(basename "$skill")
    if [ "$skill_name" != "template" ]; then
        ln -sf "$(realpath "$skill")" ~/.claude/skills/"$skill_name"
    fi
done

# Deploy to OpenCode
for skill in "$SKILLS_DIR"/*; do
    skill_name=$(basename "$skill")
    if [ "$skill_name" != "template" ]; then
        ln -sf "$(realpath "$skill")" ~/.config/opencode/skills/"$skill_name"
    fi
done

echo "Skills deployed from submodule"

Update Submodule

# Update to latest
git submodule update --remote .skills

# Or specific commit
cd .skills
git checkout main
git pull
cd ..
git add .skills
git commit -m "Update skills submodule"

OpenCode Plugin Setup

OpenCode requires the opencode-skills plugin to discover skills.

Manual Installation

# Edit OpenCode config
vim ~/.config/opencode/config.json

Add plugin:

{
  "plugin": ["opencode-skills"],
  "other-settings": "..."
}

Verify Plugin Loaded

# Start OpenCode and check for skills in output
opencode

# Or check logs for plugin loading
# (Plugin installation happens on first start after config change)

Nix Configuration

home.file.".config/opencode/config.json".text = builtins.toJSON {
  plugin = [ "opencode-skills" ];
};

Verification

Check Deployment

# Claude Code
ls -la ~/.claude/skills/
cat ~/.claude/skills/worklog/SKILL.md | head -5

# OpenCode
ls -la ~/.config/opencode/skills/
cat ~/.config/opencode/skills/worklog/SKILL.md | head -5

Test Skill Discovery

Claude Code:

# Start Claude Code
claude

# In chat, try triggering a skill
# Example: "Create a worklog"

OpenCode:

# Start OpenCode
opencode

# In chat, try triggering a skill
# Example: "Document today's work"

Debug Discovery Issues

Claude Code:

  • Check SKILL.md frontmatter is valid YAML
  • Verify file permissions are readable
  • Restart Claude Code
  • Check Claude logs (if available)

OpenCode:

  • Verify opencode-skills plugin is installed
  • Check plugin loaded at startup
  • Restart OpenCode after config changes
  • Check SKILL.md frontmatter

Multi-Environment Deployment

Deploy same skills to multiple machines.

Using Dotfiles Repository

# In your dotfiles repo
mkdir -p skills
cd skills
git submodule add https://github.com/yourusername/skills.git

# Create deployment script in dotfiles
cat > scripts/deploy-skills.sh << 'EOF'
#!/usr/bin/env bash
for skill in skills/skills/*; do
    skill_name=$(basename "$skill")
    [ "$skill_name" = "template" ] && continue
    
    ln -sf "$(realpath "$skill")" ~/.claude/skills/"$skill_name"
    ln -sf "$(realpath "$skill")" ~/.config/opencode/skills/"$skill_name"
done
EOF

chmod +x scripts/deploy-skills.sh

Using Configuration Management

Ansible example:

- name: Deploy agentic skills
  file:
    src: "{{ playbook_dir }}/skills/{{ item }}"
    dest: "~/.claude/skills/{{ item }}"
    state: link
  loop:
    - worklog
    - update-spec-kit

Cleanup

Remove All Skills

# Claude Code
rm -rf ~/.claude/skills/*

# OpenCode
rm -rf ~/.config/opencode/skills/*

Remove Specific Skill

# Claude Code
rm -rf ~/.claude/skills/worklog

# OpenCode
rm -rf ~/.config/opencode/skills/worklog

Nix Cleanup

Remove from home.nix and rebuild:

# Edit home.nix to remove skill entries
vim home.nix

# Rebuild
home-manager switch

Troubleshooting

# Check symlink
ls -la ~/.claude/skills/worklog

# If broken, recreate
rm ~/.claude/skills/worklog
ln -s $(pwd)/skills/worklog ~/.claude/skills/worklog

Permission Denied

# Fix permissions on scripts
chmod +x skills/*/scripts/*.sh

# Fix ownership
chown -R $USER:$USER skills/

Skills Not Updating (Nix)

# Nix copies files, doesn't symlink by default
# Changes to source won't appear until rebuild
sudo nixos-rebuild switch --flake .#hostname

OpenCode Plugin Not Loading

# Check config
cat ~/.config/opencode/config.json | jq .plugin

# Ensure valid JSON
jq . ~/.config/opencode/config.json

# Restart OpenCode
pkill opencode
opencode

Best Practices

  1. Development: Use symlinks for instant updates
  2. Testing: Use copies to test specific versions
  3. Production: Use Nix for declarative, atomic deployments
  4. Multi-machine: Use git submodules or dotfiles
  5. Version Control: Always commit before deploying
  6. Documentation: Keep deployment notes in project README
  7. Rollback Plan: Know how to revert (especially for Nix)

See Also