feat: mirror opencode skills into .cursor/skills/ for Cursor agent discovery - #78
Open
WayneSimpson wants to merge 1 commit into
Open
feat: mirror opencode skills into .cursor/skills/ for Cursor agent discovery#78WayneSimpson wants to merge 1 commit into
WayneSimpson wants to merge 1 commit into
Conversation
…scovery Discover opencode's resolved skills (project + global + config.skills.paths), filter through permission config, and materialise them as a git-ignored mirror in <cwd>/.cursor/skills/ with a 'generated: opencode-cursor' sentinel. An <available_skills> catalogue is appended to the generated system rule so the Cursor agent can discover and load skills on demand. - New: src/plugin/skill-discovery.ts — filesystem walk, frontmatter parsing, permission filtering (map-form + rule-array), extraPaths, path expansion, skillSetHash including all files (mtime + size). - New: src/provider/skill-mirror.ts — materialisation with sentinel, git-ignore, idempotent writes, stale-dir pruning, user-owned protection, per-file 1MB skip, total 10MB cap, removeSkillMirror for dispose, buildSkillsCatalogue. - Updated: src/provider/system-rule.ts — writeSystemRule and resolveSystemDelivery accept optional skillsCatalogue appended to rule body. - Updated: src/plugin/index.ts — forwardSkills option (default true), skills.include/exclude override, materialisation in config hook, live re-sync in chat.params hook (hash-gated), currentSkillsCatalogue always forwarded per turn, removeSkillMirror in dispose. - Updated: src/provider/language-model.ts — dynamic + static catalogue resolution (no self-provisioning — respects forwardSkills:false). - Updated: src/provider/delegate.ts + src/plugin/cursor-tools.ts — settingSources: ['project'] passed to delegate's acquireAgent. - Updated: src/provider/index.ts — skillsCatalogue in provider options. - Tests: 403 passing (25 skill-discovery, 14 skill-mirror, 10 plugin-skill- mirror, 6 catalogue in language-model-system, plus existing). - Docs: README.md (Skills section), CHANGELOG.md ([Unreleased]), SECURITY.md (skills mirror threat model). - .gitignore: exclude .cursor/ (plugin-generated runtime artifacts).
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
This PR adds a skills bridge that mirrors opencode's resolved skills into
<cwd>/.cursor/skills/so the Cursor agent (and Cursor sub-agents) can discover and load them natively via theprojectsettings layer.What it does
.opencode/skills/,.claude/skills/,.agents/skills/(walked up to the git worktree root), global~/.config/opencode/skills/, plusconfig.skills.pathsdirectories (lowest priority, first-wins on duplicate ids).permissionconfig (allow/deny/ask).ask-permissioned skills are withheld (the ask prompt can't cross the Cursor boundary). Manualskills: { include, exclude }override is supported with wildcard patterns.generated: opencode-cursorsentinel in eachSKILL.md's frontmatter. User-owned skill directories (no sentinel) are never overwritten. Supporting files are copied alongside, with per-file 1MB and total 10MB caps.<available_skills>section appended to the generated system rule, so the Cursor agent knows what's available and can load skills on demand.chat.paramshook (hash-gated, includes all file mtimes + sizes). The current catalogue is always forwarded per turn, including an empty string when all skills are removed (clearing the catalogue from the rule).removeSkillMirrorandremoveSystemRuledelete only sentinel-bearing files on plugin dispose.New files
src/plugin/skill-discovery.tsskillSetHashsrc/provider/skill-mirror.tsscripts/verify-skill-mirror.mjstest/skill-discovery.test.tstest/skill-mirror.test.tstest/plugin-skill-mirror.test.tsUpdated files
src/plugin/index.ts—forwardSkillsoption, config-hook materialisation, chat.params live re-sync, dispose cleanupsrc/provider/language-model.ts— dynamic + static catalogue resolution (no self-provisioning — respectsforwardSkills: false)src/provider/system-rule.ts—writeSystemRule/resolveSystemDeliveryaccept optionalskillsCataloguesrc/provider/delegate.ts+src/plugin/cursor-tools.ts—settingSources: ["project"]for delegatesrc/provider/index.ts—skillsCataloguein provider optionsREADME.md— Skills section, options table, limitationsCHANGELOG.md—[Unreleased]entrySECURITY.md— skills mirror threat model.gitignore— exclude.cursor/(plugin-generated runtime artifacts)Test results
Security
No API keys, tokens, or personal identifiers in any committed file. The
CURSOR_API_KEYis only referenced by name (existing pattern). The skills mirror threat model is documented in SECURITY.md: skill instructions cross the permission boundary once written to disk,deny/askskills are excluded, and user-owned files are never overwritten.Limitations
config.skills.urls(HTTP catalogs) are not supported — documented in README and SECURITY.md.cursor_cloud_agenttargets a remote repo and does not inherit skills.cursor_delegatewith a non-session cwd does not mirror skills (but does passsettingSources: ["project"]so pre-existing.cursor/skills/there still loads).Verification
Live tested with
opencode run --model cursor/composer-2.5— the Cursor agent successfully discovered, read, and used the mirroredusing-agent-skillsskill. Standalone verification (node scripts/verify-skill-mirror.mjs) confirms all 46 skills discovered, mirrored, catalogued, and disposed cleanly.