Repository navigation
fix(registries): resolve GitLab marketplace plugins - #314
Merged
Merged
Conversation
Two bugs kept plugins from gitlab-org/ai/skills from installing: - "./.claude-plugin/plugins/glab" lost its leading dot. The parser stripped "./" and the path join stripped a leading "." again, so capa looked for "claude-plugin/plugins/glab". Only a leading "./" (or a bare ".") is stripped now, in the generic marketplace parser and the bundled claude-plugins adapter (pin updated). - Each plugin's skills/<name> is a symlink to the repo's top-level skills/. Skill discovery skipped symlinked dirs, and the stable plugin copy kept the relative link, which broke once copied. Discovery now accepts symlinked skill dirs, and the plugin copy goes through copySkillTree, which dereferences symlinks that resolve inside the repo snapshot and still rejects ones that point outside it. copySkillTree also stops silently dropping symlinks and guards against link cycles. Closes #312
Review follow-ups for the symlink support in this PR: - copySkillTree walks the real tree first, then follows symlinks, and enters each real directory once per walk. The per-chain cycle guard still allowed links pointing at each other to copy 2^N trees (a hang and a full disk for capa install and the server's re-resolve); a link to a directory already copied is now skipped, and a real directory always lands at its own path. - The plugin copy skips broken links and links leaving the repository with an install warning instead of failing the whole plugin, as cpSync used to copy them. Other copySkillTree callers still throw. - The stable-copy stamp is versioned (copy-v2) so plugins copied by the old cpSync path, with broken relative links, are copied again once. - The marketplace plugin preview checks the subpath with assertSafeRepoPath, like install does.
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.
Summary
Plugins from GitLab's marketplace (
gitlab-org/ai/skills) failed with "Plugin subpath not found". There were two bugs; this PR fixes both. Closes #312.What changed
Leading dot stripped twice
./.claude-plugin/plugins/glab. The parser stripped./, then the path join stripped a leading.again, so capa looked forclaude-plugin/plugins/glab../(or a bare.) is stripped now. Fixed in the genericclaude-marketplaceparser and the bundledclaude-pluginsadapter, with its pin updated inbundled.ts.Symlinked plugin skills
skills/<name>is a symlink to the repo's top-levelskills/<name>.cpSync, which keeps the relative link, and the link breaks once copied.getSkillEntriesFromPath) now accepts symlinked skill dirs.copySkillTreewith the snapshot as the root:cpSyncbehavior.copySkillTreedecided file vs directory fromlstat, so it silently dropped every symlink. It now follows contained links and skips links back to an enclosing directory, so a cycle can't recurse forever.Review follow-ups
copy-v2), so plugins copied by the oldcpSyncpath are copied again once.assertSafeRepoPath, like install does.Notes
claude-plugin/plugins/...) incapabilities.yamlneed to re-add the plugin or fix the path.Test plan
Marketplace test:
./.claude-plugin/...,.agents/...and.map to the right subpaths.copySkillTreetest (junctions, so it also runs on Windows):rootis copied;rootis rejected;Integration test of GitLab's layout:
detectAndParseManifestfinds the linked skill;ensureStablePluginCopywrites a real directory.The test fails without the fix.
Windows build, isolated HOME, real
gitlab-org/ai/skills: the subpath now resolves. The symlinked skill couldn't be checked end to end on this machine, because Windows checks the links out as text files.execbits preserved by the new copy path on Linux (checked with a compiled Linux binary).bunx tsc --noEmit. On Windows the full suite fails only on the usual EBUSY temp cleanup and on symlink creation without privilege.Checklist
bunx tsc --noEmitpasses🤖 Generated with Claude Code