Claude-skill-registry Automated Updates
How the devbox automatically updates llm-agents (claude-code) via GitHub Actions and systemd timers. Use when debugging update failures or understanding the update flow.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/automated-updates" ~/.claude/skills/majiayu000-claude-skill-registry-automated-updates && rm -rf "$T"
manifest:
skills/data/automated-updates/SKILL.mdsource content
Automated Updates
The devbox automatically keeps
llm-agents packages up to date via a GitHub Actions + systemd timer pipeline.
What Gets Updated
The pipeline updates the
llm-agents input in flake.lock, which provides:
- claude-code: Official Claude Code CLI
- ccusage: Usage analytics and statusline
- beads: Distributed issue tracker
- opencode: OpenCode CLI (alternative AI coding tool)
- ccusage-opencode: Usage tracking for OpenCode
All packages use Numtide's binary cache for fast updates.
Note: The oh-my-opencode plugin is NOT managed by this pipeline. It's an npm package installed per-machine via
npx oh-my-opencode install. See the setting-up-oh-my-opencode skill for configuration details.
How It Works
┌─────────────────────────────────────────────────────────────┐ │ GitHub Actions (every 4 hours) │ │ │ │ 1. update-llm-agents.yml runs │ │ 2. Updates flake.lock (llm-agents input only) │ │ 3. Opens/updates PR on auto/update-llm-agents branch │ │ 4. Enables auto-merge (squash) │ │ │ │ CI (ci.yml) runs nix flake check on PR │ │ ↓ │ │ Checks pass → PR auto-merges to main │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ Devbox (systemd timer, every 4 hours) │ │ │ │ 1. pull-workstation.timer triggers │ │ 2. Fetches origin/main │ │ 3. If updates: git pull --ff-only │ │ 4. Runs: home-manager switch --flake .#dev │ └─────────────────────────────────────────────────────────────┘
Components
| Component | Location | Purpose |
|---|---|---|
| | Runs on PRs |
| | Updates llm-agents, opens PR with auto-merge |
| GitHub Secrets | PAT for PR creation + CI triggers |
| | Script to pull + apply home-manager |
| systemd user | Triggers every 4h + 10min after boot |
| systemd user | Cleans old generations daily |
Checking Status
GitHub Side
# Recent workflow runs gh run list --workflow=update-llm-agents.yml --limit=5 # Open update PRs gh pr list --head auto/update-llm-agents # CI status on a PR gh pr checks <pr-number>
Devbox Side
# Timer status systemctl --user status pull-workstation.timer systemctl --user status home-manager-auto-expire.timer # When timers will next run systemctl --user list-timers # Recent pull-workstation runs journalctl --user -u pull-workstation -n 50 # Recent auto-expire runs journalctl --user -u home-manager-auto-expire -n 50
Manual Trigger
Trigger GitHub Update
gh workflow run update-llm-agents.yml
Trigger Devbox Pull
~/.local/bin/pull-workstation
Or via systemd:
systemctl --user start pull-workstation
Troubleshooting
PR not being created
- Check workflow ran:
gh run list --workflow=update-llm-agents.yml --limit=1 - Check for errors:
gh run view <run-id> --log - Verify
secret exists:UPDATE_TOKENgh secret list
PR not auto-merging
- Check CI passed:
gh pr checks <pr-number> - Check auto-merge is enabled:
gh pr view <pr-number> - Check branch protection: Settings → Branches → main
Devbox not pulling updates
- Check timer is active:
systemctl --user status pull-workstation.timer - Check for dirty working tree:
git -C ~/projects/workstation status - Check logs:
journalctl --user -u pull-workstation -n 50 - Manual test:
~/.local/bin/pull-workstation
"Working tree not clean" error
The pull script refuses to run if there are uncommitted changes:
cd ~/projects/workstation git status # Either commit, stash, or discard changes
SSH errors in pull-workstation
The script uses
BatchMode=yes which fails if:
- SSH key missing: Check
exists~/.ssh/id_ed25519_github - Host key missing: Run
once manuallyssh -T git@github.com
Old generations piling up
Check auto-expire is running:
systemctl --user status home-manager-auto-expire.timer journalctl --user -u home-manager-auto-expire -n 20
Manual cleanup:
home-manager expire-generations "-7 days" nix-collect-garbage
Configuration
Update Frequency
Both GitHub Action and devbox timer run every 4 hours. To change:
GitHub Action: Edit
.github/workflows/update-llm-agents.yml:
schedule: - cron: '0 */4 * * *' # Change */4 to desired interval
Devbox timer: Edit
users/dev/home.linux.nix:
Timer = { OnStartupSec = "10min"; OnUnitInactiveSec = "4h"; # Change to desired interval };
Generation Retention
Edit
users/dev/home.linux.nix:
services.home-manager.autoExpire = { frequency = "daily"; timestamp = "-7 days"; # Keep generations from last 7 days };