Auto-Updating CLI Tools for Claude Code Skills
Auto-Updating CLI Tools for Claude Code Skills
Claude Code skills often depend on external CLI tools. The bird skill needs the bird CLI for Twitter. The gifgrep skill needs gifgrep for searching GIFs. The obsidian skill needs obsidian-cli. These tools ship updates regularly, and falling behind means missing bug fixes, new features, and security patches.
I just saw bird 0.7.0 drop with home timeline support and a bunch of fixes. My system was running 0.6.0. That got me thinking: how many other CLI tools are silently outdated across my 74 skills?
The answer: build a system that automatically discovers what CLI tools my skills need and keeps them updated.
The Problem: Hidden Dependencies
Claude Code skills declare their CLI dependencies in SKILL.md metadata. Here's what the bird skill looks like:
metadata: {"clawdbot":{"emoji":"🐦","requires":{"bins":["bird"]},"install":[{"id":"brew","kind":"brew","formula":"steipete/tap/bird","bins":["bird"],"label":"Install bird (brew)"}]}}
This structured metadata tells us:
- The skill needs
birdbinary - It can be installed via Homebrew from
steipete/tap/bird
The same pattern works for Go modules and Node packages. But manually checking 74 skills for outdated dependencies? Not happening.
Why This Matters for Agents
When Claude Code invokes a skill that shells out to a CLI tool, outdated versions can cause silent failures. The agent doesn't know why
bird readsuddenly returns different JSON. Keeping tools current prevents debugging sessions that waste both your time and tokens.
The Solution: Metadata-Driven Discovery
The update system works in three phases:
- Discovery: Parse all SKILL.md files, extract install metadata
- Inventory: Build a JSON registry of all CLI dependencies
- Update: Check each source (Homebrew, Go, Node) and apply updates
Phase 1: Discovering CLI Dependencies
The script iterates through `(local path) and parses the metadata JSON from each SKILL.md:
for skill_dir in "$SKILLS_DIR"/*/; do
skill_file="${skill_dir}SKILL.md"
-f "$skill_file" || continue
# Extract metadata JSON line
metadata_line=$(grep -E "^metadata:" "$skill_file" | head -1 | sed 's/^metadata: //')
-z "$metadata_line" && continue
# Parse install entries using jq
while IFS= read -r line; do
kind=$(echo "$line" | cut -d'|' -f1)
value=$(echo "$line" | cut -d'|' -f2)
case "$kind" in
brew) BREW_FORMULAS+=("$value") ;;
go) GO_MODULES+=("$value") ;;
node) NODE_PACKAGES+=("$value") ;;
esac
done < <(echo "$metadata_line" | jq -r '.clawdbot.install[]? | "\(.kind)|\(.formula // .module // .package)"')
done
This discovered 34 CLI tools across my 73 skills:
- 21 Homebrew formulas
- 10 Go modules
- 3 Node packages
Phase 2: Building the Inventory
The script generates a JSON inventory at `(local path)
{
"generated": "2026-01-12T11:19:01-05:00",
"skills_scanned": 73,
"cli_tools": 34,
"brew_formulas": [
"steipete/tap/bird",
"steipete/tap/gifgrep",
"steipete/tap/summarize",
"yakitrak/yakitrak/obsidian-cli"
],
"go_modules": [
"github.com/steipete/blucli/cmd/blu@latest",
"github.com/Hyaxia/blogwatcher/cmd/blogwatcher@latest"
],
"node_packages": [
"clawdhub",
"@steipete/oracle"
]
}
This inventory serves two purposes: tracking what needs updating and documenting what CLI ecosystem the skills depend on.
Version Pinning Decision
I chose not to implement version pinning. These are dev tools, not production dependencies. Weekly updates give enough time to catch issues before they compound. If a specific tool causes problems, pinning can be added later.
Phase 3: Applying Updates
Each package manager gets handled differently:
Homebrew: Check brew outdated, then brew upgrade
for formula in "${BREW_FORMULAS[@]}"; do
formula_short="${formula##*/}"
if brew outdated --quiet | grep -q "^${formula_short}$"; then
brew upgrade "$formula_short"
fi
done
Go: Reinstall with @latest (Go modules are idempotent)
for module in "${GO_MODULES[@]}"; do
bin_name="${module##*/}"
bin_name="${bin_name%@*}"
go install "$module"
done
Node: Use npm update -g
for package in "${NODE_PACKAGES[@]}"; do
npm update -g "$package"
done
Scheduling with LaunchAgent
The script runs weekly via macOS LaunchAgent. Create `(local path)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.bioinfo.skills-updater</string>
<key>ProgramArguments</key>
<array>
<string>/Users/bioinfo/scripts/skills-updater.sh</string>
<string>--quiet</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Weekday</key>
<integer>0</integer>
<key>Hour</key>
<integer>4</integer>
</dict>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/opt/homebrew/bin:/usr/local/go/bin:...</string>
</dict>
</dict>
</plist>
Load it with:
launchctl load (local path)
Now every Sunday at 4 AM, the script runs automatically. All updates get logged to `(local path)
Running It: First Test Results
[2026-01-12 11:19:01] Skills CLI Updater - 2026-01-12 11:19
[2026-01-12 11:19:01] Phase 1: Discovering CLI dependencies from skills...
[2026-01-12 11:19:01] Discovered 34 CLI tools across 73 skills
[2026-01-12 11:19:01] Homebrew: 21 formulas
[2026-01-12 11:19:01] Go: 10 modules
[2026-01-12 11:19:01] Node: 3 packages
...
[2026-01-12 11:19:18] bird: 0.6.0 -> 0.7.0 (updating...)
[2026-01-12 11:19:19] SUCCESS: bird updated
Bird went from 0.6.0 to 0.7.0. The new version includes home timeline support, better pagination, and a bunch of bug fixes. All without me having to remember to check.
Tap Freshness
Homebrew taps don't always reflect new versions immediately. The script runs
brew updatefirst, but third-party taps may lag. If you know a new version exists and the script doesn't see it, runbrew tap --repair <tap-name>manually.
The Practical Benefits
Reduced debugging time. When a skill fails, outdated CLI tools are one less thing to check. You know they're current.
Security patches applied automatically. CLI tools get vulnerability fixes too. Weekly updates mean you're never more than 7 days behind.
New features available immediately. Bird 0.7.0 added home timeline support. Now the bird skill can use it without manual intervention.
Discoverable dependencies. The inventory JSON documents exactly what CLI ecosystem your skills depend on. Useful for documentation, auditing, or setting up a new machine.
Manual Commands
# Run manually
(local path)
# Dry run (see what would update)
(local path) --dry-run
# Check LaunchAgent status
launchctl list | grep skills-updater
# View last run
tail -100 (local path)
# View inventory
cat (local path) | jq
What's Next
This handles the happy path. Future improvements could include:
- Slack/Discord notifications when updates are applied
- Rollback support if an update breaks something
- Version constraint parsing for skills that need specific versions
- Cross-machine sync for homelab setups with multiple nodes
For now, the system does what I need: keeps 34 CLI tools current across 73 skills without me thinking about it.
The code is straightforward bash. If you're running Claude Code with skills that depend on CLI tools, adapt it to your setup. The core insight is that skill metadata already contains the dependency information. You just need to parse it.
Related Articles
- Claude Skills vs MCP ServersshippedPractical ApplicationsNov 6, 2025Claude Skills vs MCP Servers: Why Context Efficiency MattersLearn how Claude Code skills provide a lightweight alternative to MCP servers with 30% better context efficiency while maintaining flexibility
- Claude Code Best PracticesshippedAI Development & AgentsApr 20, 2025Claude Code Best Practices: Setup, Commands, and the Defaults Worth ChangingThe Claude Code setup, skills, subagents, and hooks I run in production, plus the defaults worth changing first. Updated for the 2026 feature set.
- Debugging Claude Code with ClaudeshippedPractical ApplicationsJan 10, 2026Debugging Claude Code with Claude: A Meta-Optimization JourneyUsing Claude to analyze its own debug logs and session data reveals hidden performance bottlenecks and provides a systematic approach to optimizing AI development tools.
About the Author: Justin Johnson builds AI systems and writes about practical AI development.
justinhjohnson.com | Twitter | LinkedIn | Run Data Run | Subscribe
Follow the lab
Get the next experiment
Enjoyed the breakdown on Auto-Updating CLI Tools for Claude Code Skills? New entries land roughly weekly. No digest, no roundup. Just the next build log, when it ships.
Related experiments
Apparatus
758 words · 8 min read
- claude-code
- automation
- bash
- homebrew
- devops