hub
Hub
Manage current directory as a hub. Shell hubs shows all; this skill manages one.
Registry
~/.claude/hubs/registry.json - single source of truth:
{
"hubs": [
{
"name": "security",
"path": "/Users/brew/learning/cyber",
"status": "active",
"last_accessed": 1737785000,
"progress": "24/100",
"next_action": "Complete CSRF exercise",
"note": "working through OWASP top 10",
"current_level": 2,
"levels_completed": [0, 1]
},
{
"name": "mountain",
"path": "/Users/brew/projects/mountain",
"status": "active",
"last_accessed": 1737780000,
"progress": "",
"next_action": "Fix auth bug",
"note": ""
}
]
}
All fields live here. No separate hub.json files. Shell reads this, Claude writes this.
Commands
/hub (no args)
Check if current directory is a hub.
- If yes: show status, offer to update
- If no: offer to add it
/hub add [name]
Add current directory as hub. Name defaults to directory name.
/hub progress
Set progress (e.g., "30/100", "3/10 chapters", or "" to clear).
/hub next
Set next action.
/hub note
Set note.
/hub done
Update last_accessed to now. Run this after meaningful work, or Claude runs it automatically after commits.
/hub archive
Set status to "archived". Hidden from shell hubs output.
/hub unarchive
Set status to "active".
/hub remove
Remove from registry entirely.
Implementation
Use jq via Bash. Registry path: ~/.claude/hubs/registry.json
# Check if current dir is a hub
jq --arg p "$(pwd)" '.hubs[] | select(.path == $p)' ~/.claude/hubs/registry.json
# Add hub
jq --arg name "foo" --arg path "$(pwd)" --arg now "$(date +%s)" \
'.hubs += [{"name": $name, "path": $path, "status": "active", "last_accessed": ($now | tonumber), "progress": "", "next_action": "", "note": ""}]' \
~/.claude/hubs/registry.json > /tmp/reg.json && mv /tmp/reg.json ~/.claude/hubs/registry.json
# Update field
jq --arg p "$(pwd)" --arg val "new value" \
'(.hubs[] | select(.path == $p) | .next_action) = $val' \
~/.claude/hubs/registry.json > /tmp/reg.json && mv /tmp/reg.json ~/.claude/hubs/registry.json
# Update last_accessed
jq --arg p "$(pwd)" --arg now "$(date +%s)" \
'(.hubs[] | select(.path == $p) | .last_accessed) = ($now | tonumber)' \
~/.claude/hubs/registry.json > /tmp/reg.json && mv /tmp/reg.json ~/.claude/hubs/registry.json
Auto-update
After commits in a hub directory, Claude should run /hub done to update last_accessed.