New `skills update [skill]` subcommand decoupled from workspace sync. Walks
the `sources` map in sync-state (introduced for content-hashing in #374),
fetches each plugin (cached), and diffs the upstream hash against the
recorded `contentHash` to decide:
- `up-to-date` — recorded hash matches upstream
- `available` — drift detected; reported in --dry-run / TTY default
- `updated` — applied in --all (or non-TTY default) mode
- `pinned` — `pinnedRef` set; skipped unless --unpin
- `skipped` — fetch failed (kept fail-safe)
Flags:
- `--all` apply without prompting (default behaviour in non-TTY too)
- `--force` re-write the source provenance even when hashes match
- `--dry-run` report drift, no file writes
- `--unpin` clear `pinnedRef` so the resolver picks up the default branch
- `--scope` project (default) or user
JSON envelope shape:
```
{
success: true,
command: "skills update",
data: { checked, updates: [...], upToDate: [...], pinned: [...] }
}
```
Includes:
- `skillsUpdateMeta` in metadata, wired into agent-help.
- Tests for the new agent-help entry.
End-to-end verified against `obra/superpowers@v3.1.0`: dry-run is a
read-only no-op, JSON envelope matches the contract, --all applies in a
non-TTY shell without blocking, pinned skills are skipped unless --unpin,
--force re-stamps updatedAt, and TTY-default with no --all does not hang.
Closes #375
Summary
Adds
allagents skills update [skill]for per-skill refresh, decoupled from the heavierallagents updateworkspace sync. Walks thesourcesmap in.allagents/sync-state.json, fetches each plugin (cached), and compares upstream content hashes against the recorded ones.Behaviour, mirroring
gh skill update:--all— apply without prompting (default in non-TTY shells).--force— re-stamp source/skill rows even when hashes match (refreshesupdatedAt).--dry-run— read-only report.--unpin— clearpinnedRefbefore resolving so the default branch is picked up.--scope— project (default) or user.JSON envelope:
{ "success": true, "command": "skills update", "data": { "checked": N, "updates": [...], "upToDate": [...], "pinned": [...] } }Depends on the sync-state shape introduced by #374 (per-skill
contentHash) and the pinning shape from #372 (pinnedRef). The branch is rebased onto both so the diff is self-contained; if those land first this PR will rebase trivially.Test plan
bun run build,bun run typecheckbun test— 1195 pass / 0 fail (agent-help fixture updated for the new meta)allagents skill updatefor per-skill refresh (separate from workspace sync) #375 (usingobra/superpowers@v3.1.0as the stable public alt):.claude,.agents, or.allagents(sha256 of the tree is unchanged).--json skills update --dry-runproduces an envelope withcommand == "skills update"anddata.{upToDate,updates,pinned}all present.--allapplies without prompting in non-TTY.pinned;--unpinthen--allclearspinnedRefin sync-state.--force --allkeeps the samecontentHash(no upstream drift) but rewritesupdatedAt.--alldoes not block (10-second timeout).Closes #375