feat: align OpenCode plugin with Cursor model (vendored skills, thin config-hook, CI hardening)#16
Merged
Merged
Conversation
Add build-time vendoring of the official skills from jfrog/jfrog-skills (pinned v0.11.0) into a flat, committed skills/ tree so they ship with the package. Introduces sync-skills-vendor.json (pin config) and scripts/sync-skills.mjs (downloads + extracts + copies skills/ to repo root). Co-authored-by: Cursor <cursoragent@cursor.com>
…-skills script) Add skills/ and sync-skills-vendor.json to the package files allowlist so the vendored skills tree ships at the package root next to dist/, enabling runtime resolution via ../skills after install. Also add a sync-skills npm script and the skills keyword. Co-authored-by: Cursor <cursoragent@cursor.com>
src/version.ts does not exist and nothing generates or imports it: the build task only runs bun build, the version/publish tasks only bump package.json, and release-please-config.json defines no extra-files. Remove the phantom entry from the package files allowlist. Co-authored-by: Cursor <cursoragent@cursor.com>
…s.paths; drop runtime pull + setupPackageManagers Replace the imperative plugin (runtime download/unzip/prune + session.created package-manager setup) with a thin plugin whose only job is to register the bundled skills/ via the config hook (object form config.skills.paths), fail loud if the bundled dir is missing/empty, emit a one-line jf-setup nudge, and run a conservative one-time migration that removes only legacy version-nested managed skills (never flat/user skills). Removes pullSkills, fetchAndSaveFile, extractZip, pruneNonManifestSkillVersions, setupPackageManagers, the registry URL constants, the event hook, and the instructions-file injection. Tests trimmed to the thin behavior; comprehensive matrix lands in Phase 4. Co-authored-by: Cursor <cursoragent@cursor.com>
The repo forbids a scripts property in package.json (.mise/tasks/pkgjsonlint). Move the sync-skills entrypoint to a .mise task instead, matching repo conventions. Co-authored-by: Cursor <cursoragent@cursor.com>
…ic npm This is a public repo and must not embed internal JFrog infrastructure. - bun.lock: repoint all 281 tarball URLs from the private ctoa/carmit virtual registry to https://registry.npmjs.org (integrity hashes unchanged; the virtual repo mirrors npmjs byte-for-byte, so the lock stays reproducible). - pr.yml / publish-as-is.yml: drop the "Setup JFrog CLI" + "setup jfrog npm repo" steps, JF_URL/JF_PROJECT env, and the ctoa bunfig; resolve deps from public npm. Publish continues to target public npmjs. Note: dependency resolution now uses public npm (no JFrog curation/security gating), and npmjs publish requires an npm auth method configured by the maintainer. Co-authored-by: Cursor <cursoragent@cursor.com>
await client.tui.showToast never resolves in headless sessions (no TUI to ack), which hung the config hook on every opencode run/debug skill/CI load. Surface toasts fire-and-forget via a helper; durable signals still go through log(). Headless debug skill now returns and registers skills as expected. Co-authored-by: Cursor <cursoragent@cursor.com>
V5: drive migrateLegacyManagedSkills via a temp HOME and assert it removes only
version-nested managed skills while keeping flat (possibly user-owned), unrelated,
and unknown-shape dirs; plus a no-throw case when the skills root is absent.
V9: assert the vendored skills/ tree is exactly {jfrog, jfrog-package-safety-and-download},
flat, each SKILL.md having frontmatter name/description with name == dir.
Tests only; no behavior change.
Co-authored-by: Cursor <cursoragent@cursor.com>
…ocument breaking changes Rewrite README to describe the thin plugin that ships two vendored, pinned skills (jfrog, jfrog-package-safety-and-download) and registers them via config.skills.paths at load. Remove stale runtime-download/package-managers.json/instructions-injection content. Add VENDOR.md documenting sync-skills-vendor.json and the pin-bump workflow (mise run sync-skills) that requires a plugin release. Fix AGENTS.md test framework (bun:test, not vitest). Surface open questions (min OpenCode version, publish auth). BREAKING CHANGE: skill catalog reduced from 7 Artifactory skills (skill-install, skill-publish, jfrog-cli, opencode-jfrog-mcp, jfrog-setup-package-managers, jfrog-curation, jfrog-packages) to 2 canonical skills (jfrog, jfrog-package-safety-and-download); the removed skill names no longer exist and fold into the jfrog skill. Package-manager auto-setup on session start is removed (interim jf setup nudge; durable recovery upstream). Old version-nested skills under ~/.config/opencode/skills are auto-cleaned by a one-time migration. The instructions file and package-managers.json are no longer written, and there is no runtime skills download. Dependencies/CI now resolve from public npm. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
It's a type-only import (erased at build); dist/index.js needs only fs/path/url. Declaring it as a runtime dependency made OpenCode's post-install bun install try to fetch it, which 403s on the Artifactory- pinned npm registries common to this plugin's customer base (NpmInstallFailedError). The published package now has no runtime dependencies. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
In the same config hook that registers the vendored skills, also register the JFrog Platform remote MCP server into config.mcp. Resolve the platform URL from JFROG_URL (fallback JFROG_PLATFORM_URL), normalize to https://<host>/mcp, and set cfg.mcp.jfrog only when absent (non-destructive). Skip with a log line when no URL is set. OpenCode handles OAuth lazily, so no auth config and no network on load. Co-authored-by: Cursor <cursoragent@cursor.com>
Pivot the MCP step from Cursor's OAuth direct-MCP model to the Claude Code plugin's token-based, headless Agent Guard model. - Revert the OAuth direct config.mcp.jfrog injection (commit 23cac6c). Platform ops stay on the jfrog skill (token-based CLI). The plugin no longer writes any config.mcp entry. - Gate on the account setting mcp_gateway_plugin_enabled via a Bearer-token GET (JFROG_URL/JF_URL + JFROG_ACCESS_TOKEN/JF_ACCESS_TOKEN), bounded by a 5s AbortController and FAIL-CLOSED so load never hangs. Honor _JF_AGENT_GUARD_FORCE_DISABLE / JF_AGENT_GUARD_FORCE_ENABLE. - When enabled, inject the bundled templates/jfrog-mcp-management.md into config.instructions (absolute path, deduped). The agent then installs catalog MCPs via npx @jfrog/agent-guard as OpenCode local MCP entries. - Add the OpenCode-adapted template (opencode.json mcp, type "local" command array, environment {env:VAR}, opencode mcp auth/list, JFROG_AGENT_GUARD_REPO). - Ship templates/ via package.json files; add AbortController/setTimeout/ clearTimeout to eslint globals. Co-authored-by: Cursor <cursoragent@cursor.com>
…ll-contents check Add two mise.toml tasks: 'sync-skills:check' re-runs the vendoring and fails on any skills/ drift from the pin; 'pack:check' asserts the npm tarball includes dist/index.js + both vendored SKILL.md files and excludes *-TEST-PLAN.md / *-TEST-RESULTS.md / .opencode scratch files. Wire the full gate sequence into pr.yml: setup -> sync-skills:check -> lint -> typecheck -> test -> build -> pkgjsonlint -> pack:check. Co-authored-by: Cursor <cursoragent@cursor.com>
Resolve the "assumes published / open questions" hedges: the package is published to public npm and listed on the OpenCode ecosystem page. Give a concrete install snippet, note org-wide rollout via remote config, and state the plugin is self-contained (skills shipped in the tarball; no runtime downloads, no releases.jfrog.io dependency). Point VENDOR.md at the sync-skills:check drift guard. Co-authored-by: Cursor <cursoragent@cursor.com>
…plates leftover Move the planning/test scratch docs (E2E-TEST-PLAN.md, SKILLS-AGENTIC-TEST-PLAN.md, SKILLS-AGENTIC-TEST-RESULTS.md) out of the public plugin repo into the external planning workspace, and gitignore the runtime .opencode/ debug-log directory. The templates/ leftover from the reverted MCP work is already gone. Co-authored-by: Cursor <cursoragent@cursor.com>
|
All contributors have signed the CLA ✍️ ✅ |
….github/ Declutters the project root to the conventional essentials (README, LICENSE, NOTICE, CHANGELOG, AGENTS). Updates all internal links accordingly. No code or package contents change (docs/ and .github/ are not in the npm `files` set). Co-authored-by: Cursor <cursoragent@cursor.com>
The cursor and claude JFrog plugins don't carry an AGENTS.md, and ours was generic template content (referenced a nonexistent test, .memory/, etc.). Code-style guidance is already covered by ESLint/Prettier + CONTRIBUTING.md. Co-authored-by: Cursor <cursoragent@cursor.com>
Flatten CONTRIBUTING.md and VENDOR.md back to the root (matching the cursor and claude JFrog plugins), drop the docs/ folder, and remove NOTICE (neither peer ships one and the MIT devDeps are not redistributed). CHANGELOG.md and RELEASE.md stay, as they are required by this repo's npm/release-please flow. Co-authored-by: Cursor <cursoragent@cursor.com>
Drops the one-time cleanup of old version-nested managed skills (and its helpers/tests). The pre-0.0.3 skills are obsolete and no longer auto-removed; the plugin now only registers the bundled skills. Upgrade note updated to point users to remove any stale ~/.config/opencode/skills dirs manually. Co-authored-by: Cursor <cursoragent@cursor.com>
Collaborator
Author
|
I have read the CLA Document and I hereby sign the CLA |
YoniMelki
reviewed
Jun 23, 2026
YoniMelki
left a comment
Collaborator
There was a problem hiding this comment.
Overall: solid simplification. Replacing the runtime download/unzip pipeline with a vendored, committed skills/ tree is the right call — it makes the plugin reproducible, offline-capable, and much easier to reason about. CI hardening (drift guard, tarball self-containment check) is a nice addition.
Three things worth addressing before merge:
Addresses PR review: - config hook can run multiple times per session -> show the `jf setup` nudge once via a closure flag (adds a regression test). - sync-skills: select the extracted tarball's top-level dir deterministically (filter to directories + sort) instead of relying on readdir order. Co-authored-by: Cursor <cursoragent@cursor.com>
YoniMelki
approved these changes
Jun 23, 2026
Merged
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
Stabilizes the OpenCode JFrog plugin and aligns it with the Cursor plugin model (AX-1704). The plugin is now thin and self-contained: it ships vendored JFrog skills and registers them via the OpenCode
confighook, with no runtime downloads. MCP/Agent Guard was explored on this branch and intentionally reverted — this PR is skills-only; MCP is a later phase.What changed
Skills (core)
jfrog/jfrog-skills@v0.14.0intoskills/(pinned viasync-skills-vendor.json+scripts/sync-skills.mjs); ship them in the npm package (files).setupPackageManagerswith a thinconfighook that pushes the bundledskills/dir intoconfig.skills.paths(idempotent, fail-loud).~/.config/opencode/skillsdirs manually (documented in the README upgrade notes).jf setupnudge is shown once per session.Distribution & CI
releases.jfrog.ioruntime dependency; deps resolve from public npm.@opencode-ai/pluginmoved to devDependencies (zero runtime deps).Cleanup
.opencode/, scrub stale refs, drop redundant publish workflow; align repo layout with the cursor/claude plugins.Breaking changes (pre-1.0)
jfrog,jfrog-package-safety-and-download); removed skills fold intojfrog.jf setup <pm>nudge).Verification
sync-skills:checkno drift;pack:checkOK.Before merge (environmental, not plugin defects — confirm on CI/normal-network machine)
~/.cache/opencode/node_modules/@jfrog/opencode-jfrog-pluginexercised (blocked locally by a corporate 403 on@opencode-ai/plugin).opencode run(local headless loop stalls even with--pure).