Commit de03bef
feat: align OpenCode plugin with Cursor model (vendored skills, thin config-hook, CI hardening) (#16)
* feat(skills): vendor jfrog-skills@v0.11.0 + add sync-skills script
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>
* build(skills): ship vendored skills/ in the npm package (files + sync-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>
* build: drop stale src/version.ts from files
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>
* feat(skills): thin plugin - register vendored skills via config.skills.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>
* build: use mise task for sync-skills (drop package.json scripts)
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>
* chore: remove internal registry (ctoa/carmit) refs; resolve from public 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>
* fix(skills): fire-and-forget tui toasts in config hook
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>
* test(skills): add migration-safety (V5) and vendored-content (V9) tests
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>
* docs: rewrite README for thin/vendored skills model; add VENDOR.md; document 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>
* docs: use @<version> placeholder in README install example
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(deps): move @opencode-ai/plugin to devDependencies
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>
* feat(skills): bump vendored jfrog-skills pin v0.11.0 -> v0.14.0
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(mcp): inject JFrog Platform remote MCP server via the config hook
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>
* feat(mcp): token-based Agent Guard (Claude model); drop OAuth direct MCP
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>
* revert(mcp): drop MCP / Agent Guard injection; return to skills-only plugin
Reverts the token-based Agent Guard template injection (632025f) and the
direct MCP injection (23cac6c). The plugin again only registers the vendored
skills via the config hook. MCP support is deferred to a later phase.
Co-authored-by: Cursor <cursoragent@cursor.com>
* ci: add vendored-skills drift guard, typecheck/pkgjsonlint, and tarball-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>
* docs: document npm + ecosystem distribution; mark plugin self-contained
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>
* chore: repo hygiene — drop scratch docs, ignore .opencode, remove templates 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>
* docs: tidy repo root — move RELEASE/VENDOR to docs/, CONTRIBUTING to .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>
* chore: remove AGENTS.md (bun-template boilerplate, not in peer plugins)
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>
* chore: align repo layout with cursor/claude plugins
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>
* feat!: remove legacy-skill migration from the plugin
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>
* fix(review): dedupe jf-setup nudge; deterministic tarball top-dir
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>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>1 parent 2146d7f commit de03bef
46 files changed
Lines changed: 7576 additions & 998 deletions
File tree
- .github/workflows
- .mise/tasks
- scripts
- skills
- jfrog-package-safety-and-download
- jfrog
- assets
- references
- scripts
- src
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
15 | 14 | | |
16 | 15 | | |
17 | 16 | | |
| |||
21 | 20 | | |
22 | 21 | | |
23 | 22 | | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
43 | | - | |
44 | | - | |
45 | | - | |
46 | 23 | | |
47 | 24 | | |
48 | 25 | | |
| |||
54 | 31 | | |
55 | 32 | | |
56 | 33 | | |
| 34 | + | |
57 | 35 | | |
| 36 | + | |
58 | 37 | | |
59 | 38 | | |
| 39 | + | |
| 40 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | 20 | | |
43 | 21 | | |
44 | 22 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
| 13 | + | |
| 14 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
40 | | - | |
41 | | - | |
| 40 | + | |
This file was deleted.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | | - | |
4 | | - | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
5 | 6 | | |
6 | | - | |
7 | | - | |
8 | | - | |
9 | | - | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
10 | 11 | | |
11 | | - | |
12 | | - | |
13 | | - | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
14 | 16 | | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
| 17 | + | |
| 18 | + | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
20 | 25 | | |
21 | | - | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
22 | 32 | | |
23 | 33 | | |
24 | | - | |
25 | | - | |
26 | 34 | | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
31 | | - | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
32 | 46 | | |
33 | 47 | | |
34 | | - | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
39 | 54 | | |
40 | | - | |
41 | | - | |
| 55 | + | |
42 | 56 | | |
43 | | - | |
| 57 | + | |
44 | 58 | | |
45 | | - | |
46 | | - | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
47 | 62 | | |
48 | | - | |
49 | | - | |
50 | | - | |
51 | | - | |
52 | | - | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
53 | 66 | | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
58 | 72 | | |
59 | 73 | | |
60 | | - | |
61 | | - | |
62 | | - | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
63 | 107 | | |
64 | 108 | | |
65 | 109 | | |
66 | | - | |
67 | | - | |
68 | | - | |
69 | | - | |
70 | | - | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
71 | 119 | | |
72 | 120 | | |
73 | 121 | | |
74 | | - | |
| 122 | + | |
75 | 123 | | |
76 | 124 | | |
77 | 125 | | |
78 | | - | |
| 126 | + | |
| 127 | + | |
79 | 128 | | |
80 | 129 | | |
81 | 130 | | |
82 | | - | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
0 commit comments