Repository navigation
feat(opencode): install a whole Skill Stack with codev skill stack - #361
Merged
Merged
Conversation
A Skill Stack is a public namespace on the hub — a team's curated skill set, served as one composite ZIP. `codev skill stack list` browses them and `codev skill stack pull <slug>` installs every skill in one into the same .claude/skills + .agents/skills folders `skill pull` writes, with the same agent picker and one real copy plus links. The extract-and-link half of installResolvedSkill moves into a shared placeSkill(), so a stack reuses the single-skill conflict ordering, zip guards and Claude-symlink fallback rather than growing a second copy of them. The stack lifts each skill's subtree straight out of the composite archive instead of re-zipping it, and probes `claude --version` once for the whole bundle. A stack is N installs, not a transaction: a skill that fails is reported by name and the rest still land, a folder with no SKILL.md is listed as excluded, and the interactive flow says when the hub's advertised skill count exceeds what the archive actually carries (the hub keys bundle folders by skill name, so two same-named skills in a namespace collapse into one). Archive caps are parameterized: a stack gets its own ceiling (500 MB / 50k entries) while each skill inside it still gets the 100 MB / 15k one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P1MfYkJD3tQZRgqBKB4gig
This was referenced Sep 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
P0 of the Skill Stack integration: the
@codev/skillhubpackage layer plus the CLI surface. Server endpoints (P1), the TUI dialog (P2) and the desktop Stacks tab (P3) build on this and land separately.What a Skill Stack is
A public namespace on the hub.
GET /api/v1/explore/namespaceslists them;GET /api/v1/namespaces/{slug}/download-allserves one composite ZIP —{slug}/README.mdplus{slug}/<skill-name>/…per PUBLIC skill, each skill's own root already stripped server-side. Neithercodevhubnor the hub's own CLI has a stack command, so this is new capability rather than a port.What this adds
Skills land in exactly the same
.claude/skills+.agents/skillsfoldersskill pullwrites — one real copy plus links for the other agents, same agent picker, CoDev Code always included. Interactive runs preview the archive's real contents before asking where to put it.Conflicts are asked about, never guessed. When skills in the stack are already installed, the interactive flow lists them and offers skip-vs-overwrite; the non-interactive path stops and names them unless
--skip-existingor--overwritewas passed.A stack is N installs, not a transaction. A skill that fails to install is reported by name and the rest still land (exit 1); a bundle folder with no
SKILL.mdis listed as excluded rather than dropped silently.Implementation notes
installResolvedSkillmoves into a sharedplaceSkill(). Both paths now share one copy of the conflict/rmordering, the zip-slip guard and the Claude-symlink-floor fallback. The single-skill path is behavior-identical — including still refusing an unsafe name before downloading anything.extractEntries(entries, dir, { strip }), so nothing is re-zipped.claude --versionis probed once per stack rather than once per link.STACK_LIMITS(500 MB / 50k entries) for the bundle,SKILL_LIMITS(100 MB / 15k) still enforced per skill inside it, so one skill can't spend the stack's budget.download-allgets a 300s timeout — the shared 15s JSON-handshake default would fail on any real stack.findStack(slug)resolves a name for the prompt via the public listing and returnsnullrather than throwing, because a private stack the user can see is absent from that listing but still downloads.Hub-side issue found while testing
skill-create-and-reviewadvertises 3 skills; the archive carries 2. Two distinct skill records in that namespace share the nameskill-creator, anddownloadAllSkillskeys bundle folders byskill.name, so one silently overwrites the other. The same gap appears for a PUBLIC skill with a nullzipUrl— counted in the listing, absent from the ZIP. The interactive flow now says so (the hub lists N skill(s) here, but the archive carries M) rather than installing quietly fewer than advertised. Worth a hub-side fix; nothing here depends on it.Verification
packages/codev-skillhub: 243 pass / 0 fail (49 new acrossstack,stack-install,stack-search),bun typecheckclean.packages/opencode:bun test test/cli391 pass / 0 fail,bun typecheckclean, help snapshots regenerated (+3 commands).stack list,stack pull --dir, the conflict refusal,--skip-existing, and--global --all-agents(verified one real copy in.agents/skillswith relative symlinks from.claude/skills).DIVERGENCES.mdrow 110 updated (skillsubcommand list);CHANGELOG.mdUnreleased → Skills.🤖 Generated with Claude Code
https://claude.ai/code/session_01P1MfYkJD3tQZRgqBKB4gig