feat: install pulled skills for every agent, not just Claude Code - #227
Merged
Conversation
`skill pull` wrote only to `.claude/skills`, so a hub skill was usable by Claude Code and nothing else — a gap in a product whose flagship agent is CoDev Code. Which directory each agent reads was established from the agents' own source, not their docs: the table baked into the CoDev Code bundle lists only the `~/…` paths and omits the project-scope walk, which is the opposite of what `packages/opencode/src/skill/index.ts#discoverSkills` does. It scans `.claude` AND `.agents` under `$HOME` and again walking cwd up to the worktree root. Codex reads `.agents/skills` at both scopes; Claude Code reads `.claude/skills` at both. So two directories cover all four agents with one rule at both scopes, and nothing needs a per-agent directory. resolveTargets extracts once into whichever directory covers the most selected agents and links the other only when some selected agent can't reach it — when Codex isn't selected, `.claude/skills` alone serves everyone and no link is created at all. A hub skill can run to thousands of files, so a copy per agent is not free. Links are relative symlinks, matching this repo's own committed skill (`.claude/skills/vercel-… -> ../../.agents/skills/vercel-…`, git mode 120000) — relative is what survives a clone. linkOrCopy degrades to a Windows junction (no Developer Mode or admin needed) and then to a copy, reporting the mode verbatim so a copy is never called a link. Claude Code follows symlinked skill dirs only from v2.1.203, so that one link probes `claude --version` and copies below the floor. `--here`/`--global` now select scope only; `--agent <list>`/`--all-agents` select agents, reusing the launch names `restore` accepts. CoDev Code is always in the set and the picker renders it locked. `--dir` is unchanged and rejects `--agent`. Verified end-to-end against the real agents: CoDev Code lists the skill via `/skill` (v1 — `/api/skill` is v2 and reports nothing from these directories, which looks exactly like a broken install), Codex has it in its session context, and Claude Code follows the relative symlink. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`[x]` reads as "removed" or "wrong" more than "selected". `[✓]` keeps the checkbox affordance the brackets give while matching the ✓ the CLI already uses for a completed Step. Same single-column width, so the rows stay aligned. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Closes the gap where a hub skill was usable by Claude Code and nothing else — in a product whose flagship agent is CoDev Code.
Where the layout came from
Read from the agents' source, not their docs. The table baked into the CoDev Code bundle lists only the
~/…paths and omits the project-scope walk, which is the opposite of what the code does.packages/opencode/src/skill/index.ts#discoverSkills:.agents/skills.claude/skillsNeither directory alone covers all four; together they do, with the same rule at both scopes — scope only picks the root. Nothing needs a per-agent directory, so there is no
.codev/skillsor.opencode/skillslink to write.Design
resolveTargetsextracts once into whichever directory covers the most selected agents, and links the other only when some selected agent can't reach it. When Codex isn't selected,.claude/skillsalone serves everyone and no link is created. One hub skill is ~11k files, so a copy per agent is not free.Links are relative symlinks, matching this repo's own committed skill (
.claude/skills/vercel-react-best-practices -> ../../.agents/skills/…, git mode 120000) — relative is what survivesgit clone.linkOrCopydegrades to a Windows junction (needs neither Developer Mode nor admin, unlike a Windows symlink) and then to a recursive copy, reporting the mode verbatim so a fallback copy is never described as a link.Claude Code follows symlinked skill dirs only from v2.1.203 — below that the link reads as a file with no SKILL.md and the skill is invisible, so that one link probes
claude --versionand copies instead.Flags
--here/--globalnow select scope only;--agent claude,codex,opencode,codev/--all-agentsselect agents, reusing the launch namescodevhub restorealready accepts. Default set (prompt pre-check and non-interactive) is CoDev Code plus whateverdetectCodevTools()reports, so CI never has to pass--agent. CoDev Code is always in the set and the picker renders it locked.--diris unchanged and now rejects--agent, which would have nowhere to go.Verification
pnpm fix,pnpm typecheck,pnpm test(1285 passed),pnpm build+ smoke-run.Unit coverage: the store/link choice for every agent subset × scope against a temp
HOME/cwd; the link is asserted relative and asserted to resolve; copy fallback whensymlinkis stubbed to throw, reported ascopy; the version floor forcing a copy;--forceconverting a pre-existing real directory into a link (the upgrade path); refusal before anything is deleted.End-to-end against the real agents, since the whole design rests on what they actually scan:
codev serve, confirmed it lists the skill from.agents/skills/..agents/skills/.Two things reviewers should know
/skillvs/api/skill. They are different services./api/skillis v2 (packages/core/src/skill.ts), which registers only<configdir>/skill{,s}plusskills.pathsand reports nothing from.claude/.agents— querying it looks exactly like a broken install./skillis v1, the servicesession/system.tsbuilds the prompt from. If CoDev Code migrates the prompt to v2,.agents/skillswill need askills.pathsentry and this design changes. Documented inAGENTS.md.The
duplicate skill namewarning is expected. When both directories exist, CoDev Code and OpenCode reach the same skill twice and log it; last wins and it resolves to one entry. It is log-only, and it already happens independently of CoDev for any skill present in both directories.Follow-up, not in this PR
The landing-page Skills docs (quickbeard/codev-landing-page) describe
--here/--globalas choosing.claude/skills. That is now scope-only and there is a new agent axis, so those pages need an update.Unrelated pre-existing bug found while testing: the hub's
perplexityskill has a malformed ZIP (ADM-ZIP: No descriptor present). It fails identically on the old--dirpath, so it predates this change.🤖 Generated with Claude Code