From 2af75a470887cc1fe24be39f26e604921a392709 Mon Sep 17 00:00:00 2001 From: Yoni Melki Date: Tue, 25 Aug 2026 13:25:31 +0300 Subject: [PATCH 1/7] AX-2162 - Add shared install verify recovery guide and README alignment Co-authored-by: Cursor --- CONTRIBUTING.md | 1 + README.md | 19 +++++++ docs/shared-install-and-verify.md | 85 +++++++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 docs/shared-install-and-verify.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e1fea83..0e95dfb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,6 +47,7 @@ This downloads the pinned upstream tarball and replaces the contents of `skills/ - [ ] No secrets, credentials, or files under `**/local-cache/` committed. - [ ] If the skill tree changed: `pin` in `.github/scripts/sync-skills-vendor.json` matches the upstream tag the new tree was generated from. - [ ] Smoke-test: `claude --plugin-dir .` from the repo root. +- [ ] Install/recovery docs: README links [docs/shared-install-and-verify.md](docs/shared-install-and-verify.md), includes a **Verify** section, and does not contradict it on init/env/restart/recovery. ### Submitting to the Claude plugin directory diff --git a/README.md b/README.md index 0971f5c..5f22506 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ JFrog plugin for [Claude Code](https://claude.com/product/claude-code): artifact management, security scanning, and supply-chain best practices, and Agent Guard. +> **Install flow:** [Shared install, verify, and recovery guide](docs/shared-install-and-verify.md) — canonical cross-harness rules. This README covers **Claude Code-only** steps. + ## Features The JFrog plugin provides the following capabilities, grouped by component: @@ -54,6 +56,8 @@ claude plugin marketplace update claude-plugins-official claude plugin install jfrog@claude-plugins-official ``` +Then run **`/jfrog-init`** to complete the shared readiness walk, **restart Claude Code**, and verify below. + ### Local development From a clone of this repository (repository root **is** the plugin root): @@ -84,6 +88,21 @@ If you have never configured the JFrog CLI on this machine: ``` 3. Follow the interactive prompts to enter the same JFrog platform URL and access token. +Setting `JFROG_URL` / `JFROG_ACCESS_TOKEN` alone does **not** replace a successful `/jfrog-init` walk or repair a failed one — see [shared env-var rules](docs/shared-install-and-verify.md#environment-variables--what-actually-helps). + +--- + +## Verify + +Verification is a required install step, not a troubleshooting fallback: + +1. `/plugins` → **Installed** — the JFrog plugin is listed. +2. Run **`/jfrog-init`** — it completes without blocking errors. Restart Claude Code if it changed the MCP config. +3. `jf rt ping` — succeeds against your configured server. + +If a check fails, fix the step `/jfrog-init` reports and re-run it, then restart. See the +[shared recovery playbook](docs/shared-install-and-verify.md#recovery-playbook). + --- ## Plugin MCP rewrite (Agent Guard) diff --git a/docs/shared-install-and-verify.md b/docs/shared-install-and-verify.md new file mode 100644 index 0000000..6df34bc --- /dev/null +++ b/docs/shared-install-and-verify.md @@ -0,0 +1,85 @@ +# Shared JFrog plugin install, verify, and recovery flow + +Canonical cross-harness guidance for the JFrog agent plugins. Each harness README and web doc links here for the common flow and documents **only verified harness differences**. + +**Web overview:** [JFrog Agent Plugins](https://docs.jfrog.com/ai-ml/docs/jfrog-plugins) + +## Common prerequisites (all harnesses) + +| Requirement | Notes | +| --- | --- | +| JFrog Platform instance | You can authenticate against it (URL + token or browser login). | +| Node.js ≥ 18 | With `npx` on `PATH` where Agent Guard or `/jfrog-init` auto-install is used. VS Code Copilot hooks may require Node ≥ 20 — see the VS Code plugin README. | +| `jf`, `jq`, `curl` on `PATH` | Required for JFrog skills at runtime. Install and configure the CLI with [`jf config add`](https://docs.jfrog.com/integrations/docs/jf-config-add) or `jf login`. | +| JFrog AI Catalog (optional) | Required only for Agent Guard MCP catalog features. | + +## Shared flow (every harness) + +Follow these steps in order. Harness READMEs describe **how** to perform step 1 for that IDE/agent only. + +1. **Install the plugin** using the harness-specific marketplace or config mechanism. +2. **Configure the JFrog CLI** (`jf config add` or `jf login`) so skills and detectors can reach your platform. This is the primary credential path for skills. +3. **Run `/jfrog-init` where the harness ships the skill** (Claude Code, Cursor, VS Code, Devin, and others with the vendored `jfrog-init` skill). It walks Node → CLI → server reachability → plugin MCP file → project → AI Catalog entitlement. Stop at the first failure and follow the skill's fix prompts. +4. **Restart the harness** after plugin install and after any MCP config change. A new chat session alone is **not** enough on OpenCode, Codex, Devin CLI, Claude Code, or VS Code when MCP entries changed. +5. **Verify** using the harness checklist below — verification is a required install step, not an FAQ footnote. + +## Environment variables — what actually helps + +| Variable | Typical form | Used for | +| --- | --- | --- | +| `JFROG_PLATFORM_URL` | Host only (`mycompany.jfrog.io`, no `https://`) | Plugin MCP placeholders (Cursor, VS Code, Devin, OpenCode). Must be set **before** the harness starts where the MCP entry resolves it at launch (Devin, OpenCode). Codex is the exception: its bundled `.mcp.json` is edited directly rather than read from the environment. | +| `JFROG_URL` | Full platform URL (`https://mycompany.jfrog.io`, no trailing `/`) | Legacy skill paths and some Agent Guard resolution. Prefer `jf config` for skills. | +| `JFROG_ACCESS_TOKEN` | JWT access token | OpenCode MCP registration, some headless flows. Not a substitute for `jf config` in skills. | + +**Important — do not treat env vars as a recovery shortcut after a failed `/jfrog-init`:** + +- When `/jfrog-init` **succeeds**, Step 5 **writes the resolved platform URL into the plugin-owned `mcp.json`**, replacing `${JFROG_PLATFORM_URL}` / `${JFROG_URL}` placeholders from your live `jf config`. Env vars you set afterward do not re-run that substitution. +- When `/jfrog-init` **fails or stops early**, there is **no guaranteed recovery path** from "set env vars and retry." Fix the reported step (CLI install, auth, MCP file, project, catalog entitlement) and **re-run `/jfrog-init`**, then restart the harness. +- Setting env vars without a successful init walk may appear to help in one harness and silently fail in another — always prefer completing `/jfrog-init` (or the harness-specific MCP login flow documented in that README). + +## Verify (required after install) + +Complete **all** rows that apply to your harness before considering the install done. + +| Check | Pass criteria | +| --- | --- | +| Plugin present | Harness-specific list/install command shows the JFrog plugin enabled. | +| Skills loaded | JFrog skills appear in the harness skill picker (`/skills`, `@jfrog`, or `/jfrog:…` invocations). | +| JFrog CLI | `jf rt ping` succeeds for your configured server. | +| Platform MCP (if bundled) | Harness MCP list shows `jfrog` connected after OAuth/login where required. | +| Agent Guard (optional) | Asking the agent to list installable MCPs returns catalog rows for your project. | + +## Recovery playbook + +| Symptom | Do this | Do **not** do this | +| --- | --- | --- | +| MCP missing after install | Run `/jfrog-init` (if available), complete OAuth/login steps, **restart harness**, re-verify MCP list. | Assume `JFROG_URL` alone will register MCP on every harness. | +| `/jfrog-init` stopped at CLI/auth | Follow the skill prompt (`jf config add`, web login, or token path), then **re-run `/jfrog-init`**. | Skip init and only export env vars. | +| Plugin MCP file missing | Reinstall/update the JFrog plugin, restart, re-run `/jfrog-init`. | Hand-edit unrelated MCP configs. | +| Placeholder URL still in plugin `mcp.json` | Fix `jf config` for the intended server, re-run `/jfrog-init` Step 5 substitution. | Reinstall the plugin when the detector says auth/URL resolution failed. | +| Stale plugin version | Upgrade via the harness marketplace/npm/update command, restart, verify version column. | Trust a new chat session without restart after upgrade. | +| Install fails with marketplace schema errors | Refresh the marketplace catalog (for Claude Code, `claude plugin marketplace update claude-plugins-official`) and retry the install — a stale or invalid *aggregate* catalog rejects every plugin in it, including this one. See [AX-2176](https://jfrog-int.atlassian.net/browse/AX-2176). | Read the indexed error (`plugins.0.source`) as a diagnosis of the JFrog plugin. | + +## Harness-specific install docs + +Document **only differences** from this page in each harness guide: + +| Harness | Install doc | +| --- | --- | +| Claude Code | [README](../README.md) · [Web](https://docs.jfrog.com/ai-ml/docs/claude-code) | +| VS Code (Copilot) | [README](https://github.com/jfrog/vscode-plugin/blob/main/README.md) · [Web](https://docs.jfrog.com/ai-ml/docs/vs-code) | +| Cursor | [README](https://github.com/jfrog/cursor-plugin/blob/main/README.md) · [Web](https://docs.jfrog.com/ai-ml/docs/cursor) | +| OpenCode | [README](https://github.com/jfrog/opencode-jfrog-plugin/blob/main/README.md) · [Web](https://docs.jfrog.com/ai-ml/docs/opencode) — see also [AX-1780](https://jfrog-int.atlassian.net/browse/AX-1780), [AX-2122](https://jfrog-int.atlassian.net/browse/AX-2122), [AX-2124](https://jfrog-int.atlassian.net/browse/AX-2124) for OpenCode-specific init/MCP work | +| Codex | [README](https://github.com/jfrog/codex-plugin/blob/main/README.md) · [Web source](https://github.com/jfrog/codex-plugin/blob/main/docs/install-jfrog-plugin-for-codex.md) | +| Devin | [README](https://github.com/jfrog/devin-plugin/blob/main/README.md) · [Web source](https://github.com/jfrog/devin-plugin/blob/main/docs/install-jfrog-plugin-for-devin.md) | +| Kiro | [README](https://github.com/jfrog/jfrog-kiro-power/blob/main/README.md) — MCP/Kiro adapter gaps tracked separately | + +## Maintainer checklist (release review) + +Before merging documentation or cutting a plugin release: + +- [ ] Harness README links to this shared guide and does not contradict it on init, env vars, restart, or recovery. +- [ ] Verification steps appear in the install section (not only FAQ/troubleshooting). +- [ ] OpenCode cross-links [AX-1780](https://jfrog-int.atlassian.net/browse/AX-1780), [AX-2122](https://jfrog-int.atlassian.net/browse/AX-2122), [AX-2124](https://jfrog-int.atlassian.net/browse/AX-2124) when describing OpenCode-only behavior. +- [ ] Codex and Devin web-doc sources under `docs/install-jfrog-plugin-for-*.md` stay aligned with the harness README. +- [ ] `node scripts/validate-install-docs.mjs` passes in repos that ship the checker. From e63c4526cbc5a59cde3206850e42fc896bd7b5e9 Mon Sep 17 00:00:00 2001 From: Yoni Melki Date: Tue, 25 Aug 2026 18:33:22 +0300 Subject: [PATCH 2/7] AX-2162 - Keep Claude install docs self-contained Stop treating this repo as the shared source for other harnesses. Install, verify, and recovery live in this plugin only. Co-authored-by: Cursor --- CONTRIBUTING.md | 2 +- README.md | 6 +-- docs/install-and-verify.md | 75 +++++++++++++++++++++++++++ docs/shared-install-and-verify.md | 85 ------------------------------- 4 files changed, 79 insertions(+), 89 deletions(-) create mode 100644 docs/install-and-verify.md delete mode 100644 docs/shared-install-and-verify.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0e95dfb..1a7dae6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,7 +47,7 @@ This downloads the pinned upstream tarball and replaces the contents of `skills/ - [ ] No secrets, credentials, or files under `**/local-cache/` committed. - [ ] If the skill tree changed: `pin` in `.github/scripts/sync-skills-vendor.json` matches the upstream tag the new tree was generated from. - [ ] Smoke-test: `claude --plugin-dir .` from the repo root. -- [ ] Install/recovery docs: README links [docs/shared-install-and-verify.md](docs/shared-install-and-verify.md), includes a **Verify** section, and does not contradict it on init/env/restart/recovery. +- [ ] Install/recovery docs: README links [docs/install-and-verify.md](docs/install-and-verify.md), includes a **Verify** section, and does not contradict it on init/env/restart/recovery. Do not send readers to another plugin repository for those steps. ### Submitting to the Claude plugin directory diff --git a/README.md b/README.md index 5f22506..fb893d1 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ JFrog plugin for [Claude Code](https://claude.com/product/claude-code): artifact management, security scanning, and supply-chain best practices, and Agent Guard. -> **Install flow:** [Shared install, verify, and recovery guide](docs/shared-install-and-verify.md) — canonical cross-harness rules. This README covers **Claude Code-only** steps. +> **Install, verify, and recovery:** [docs/install-and-verify.md](docs/install-and-verify.md). ## Features @@ -88,7 +88,7 @@ If you have never configured the JFrog CLI on this machine: ``` 3. Follow the interactive prompts to enter the same JFrog platform URL and access token. -Setting `JFROG_URL` / `JFROG_ACCESS_TOKEN` alone does **not** replace a successful `/jfrog-init` walk or repair a failed one — see [shared env-var rules](docs/shared-install-and-verify.md#environment-variables--what-actually-helps). +Setting `JFROG_URL` / `JFROG_ACCESS_TOKEN` alone does **not** replace a successful `/jfrog-init` walk or repair a failed one — see [environment variables](docs/install-and-verify.md#environment-variables). --- @@ -101,7 +101,7 @@ Verification is a required install step, not a troubleshooting fallback: 3. `jf rt ping` — succeeds against your configured server. If a check fails, fix the step `/jfrog-init` reports and re-run it, then restart. See the -[shared recovery playbook](docs/shared-install-and-verify.md#recovery-playbook). +[recovery playbook](docs/install-and-verify.md#recovery-playbook). --- diff --git a/docs/install-and-verify.md b/docs/install-and-verify.md new file mode 100644 index 0000000..1ba68e1 --- /dev/null +++ b/docs/install-and-verify.md @@ -0,0 +1,75 @@ +# Claude Code install, verify, and recovery + +How to install, verify, and recover the JFrog plugin for Claude Code. This document covers Claude Code only. + +**Web overview:** [Install JFrog Agent Plugin for Claude Code](https://docs.jfrog.com/ai-ml/docs/claude-code) + +## Prerequisites + +| Requirement | Notes | +| --- | --- | +| JFrog Platform instance | You can authenticate against it (URL + token or browser login). | +| Claude Code CLI (≥ 1.0) | Plugin commands (`claude plugin …`) must be available. | +| Node.js ≥ 18 | With `npx` on `PATH` (used by Agent Guard and `/jfrog-init`). | +| `jf`, `jq`, `curl` on `PATH` | Required for JFrog skills at runtime. Install and configure the CLI with [`jf config add`](https://docs.jfrog.com/integrations/docs/jf-config-add) or `jf login`. | +| JFrog AI Catalog (optional) | Required only for Agent Guard MCP catalog features. | + +## Install flow + +1. **Install the plugin** from Claude's official marketplace: + + ```bash + claude plugin marketplace update claude-plugins-official + claude plugin install jfrog@claude-plugins-official + ``` + +2. **Configure the JFrog CLI** (`jf config add` or `jf login`) so skills and detectors can reach your platform. This is the primary credential path for skills. + +3. **Run `/jfrog-init`.** It walks Node → CLI → server reachability → plugin MCP file → project → AI Catalog entitlement. Stop at the first failure and follow the skill's fix prompts. + +4. **Restart Claude Code** after plugin install and after any MCP config change. A new chat session alone is not enough when MCP entries changed. + +5. **Verify** using the checklist below — verification is a required install step, not an FAQ footnote. + +## Environment variables + +| Variable | Typical form | Used for | +| --- | --- | --- | +| `JFROG_URL` | Full platform URL (`https://mycompany.jfrog.io`, no trailing `/`) | Plugin MCP and some skill paths. Prefer `jf config` for skills. | +| `JFROG_ACCESS_TOKEN` | JWT access token | Some headless flows. Not a substitute for `jf config` in skills. | + +**Do not treat env vars as a recovery shortcut after a failed `/jfrog-init`:** + +- When `/jfrog-init` **succeeds**, it writes the resolved platform URL into the plugin-owned `mcp.json`, replacing placeholders from your live `jf config`. Env vars you set afterward do not re-run that substitution. +- When `/jfrog-init` **fails or stops early**, there is no guaranteed recovery path from "set env vars and retry." Fix the reported step (CLI install, auth, MCP file, project, catalog entitlement) and **re-run `/jfrog-init`**, then restart Claude Code. + +## Verify (required after install) + +Complete all rows before considering the install done. + +| Check | Pass criteria | +| --- | --- | +| Plugin present | `/plugins` → **Installed** lists the JFrog plugin. | +| Initialization | `/jfrog-init` completes without blocking errors. Restart Claude Code if it changed MCP config. | +| JFrog CLI | `jf rt ping` succeeds for your configured server. | +| Platform MCP | JFrog MCP tools are available in the session after OAuth if prompted. | +| Agent Guard (optional) | Asking the agent to list installable MCPs returns catalog rows for your project. | + +## Recovery playbook + +| Symptom | Do this | Do **not** do this | +| --- | --- | --- | +| MCP missing after install | Run `/jfrog-init`, complete OAuth if prompted, **restart Claude Code**, re-check MCP tools. | Assume `JFROG_URL` alone will register MCP. | +| `/jfrog-init` stopped at CLI/auth | Follow the skill prompt (`jf config add`, web login, or token path), then **re-run `/jfrog-init`**. | Skip init and only export env vars. | +| Plugin MCP file missing | Reinstall/update the JFrog plugin, restart, re-run `/jfrog-init`. | Hand-edit unrelated MCP configs. | +| Placeholder URL still in plugin `mcp.json` | Fix `jf config` for the intended server, re-run `/jfrog-init` so it can substitute the URL. | Reinstall the plugin when the detector says auth/URL resolution failed. | +| Stale plugin version | Upgrade via the marketplace, restart, confirm the installed version. | Trust a new chat session without restart after upgrade. | +| Install fails with marketplace schema errors | Run `claude plugin marketplace update claude-plugins-official` and retry the install — a stale or invalid *aggregate* catalog rejects every plugin in it, including this one. | Read the indexed error (`plugins.0.source`) as a diagnosis of the JFrog plugin. | + +## Maintainer checklist (release review) + +Before merging documentation or cutting a plugin release: + +- [ ] [`README.md`](../README.md) and this page agree on init, env vars, restart, verification, and recovery. +- [ ] Verification steps appear in the install section (not only FAQ/troubleshooting). +- [ ] This document does not send readers to another plugin repository for install or recovery steps. diff --git a/docs/shared-install-and-verify.md b/docs/shared-install-and-verify.md deleted file mode 100644 index 6df34bc..0000000 --- a/docs/shared-install-and-verify.md +++ /dev/null @@ -1,85 +0,0 @@ -# Shared JFrog plugin install, verify, and recovery flow - -Canonical cross-harness guidance for the JFrog agent plugins. Each harness README and web doc links here for the common flow and documents **only verified harness differences**. - -**Web overview:** [JFrog Agent Plugins](https://docs.jfrog.com/ai-ml/docs/jfrog-plugins) - -## Common prerequisites (all harnesses) - -| Requirement | Notes | -| --- | --- | -| JFrog Platform instance | You can authenticate against it (URL + token or browser login). | -| Node.js ≥ 18 | With `npx` on `PATH` where Agent Guard or `/jfrog-init` auto-install is used. VS Code Copilot hooks may require Node ≥ 20 — see the VS Code plugin README. | -| `jf`, `jq`, `curl` on `PATH` | Required for JFrog skills at runtime. Install and configure the CLI with [`jf config add`](https://docs.jfrog.com/integrations/docs/jf-config-add) or `jf login`. | -| JFrog AI Catalog (optional) | Required only for Agent Guard MCP catalog features. | - -## Shared flow (every harness) - -Follow these steps in order. Harness READMEs describe **how** to perform step 1 for that IDE/agent only. - -1. **Install the plugin** using the harness-specific marketplace or config mechanism. -2. **Configure the JFrog CLI** (`jf config add` or `jf login`) so skills and detectors can reach your platform. This is the primary credential path for skills. -3. **Run `/jfrog-init` where the harness ships the skill** (Claude Code, Cursor, VS Code, Devin, and others with the vendored `jfrog-init` skill). It walks Node → CLI → server reachability → plugin MCP file → project → AI Catalog entitlement. Stop at the first failure and follow the skill's fix prompts. -4. **Restart the harness** after plugin install and after any MCP config change. A new chat session alone is **not** enough on OpenCode, Codex, Devin CLI, Claude Code, or VS Code when MCP entries changed. -5. **Verify** using the harness checklist below — verification is a required install step, not an FAQ footnote. - -## Environment variables — what actually helps - -| Variable | Typical form | Used for | -| --- | --- | --- | -| `JFROG_PLATFORM_URL` | Host only (`mycompany.jfrog.io`, no `https://`) | Plugin MCP placeholders (Cursor, VS Code, Devin, OpenCode). Must be set **before** the harness starts where the MCP entry resolves it at launch (Devin, OpenCode). Codex is the exception: its bundled `.mcp.json` is edited directly rather than read from the environment. | -| `JFROG_URL` | Full platform URL (`https://mycompany.jfrog.io`, no trailing `/`) | Legacy skill paths and some Agent Guard resolution. Prefer `jf config` for skills. | -| `JFROG_ACCESS_TOKEN` | JWT access token | OpenCode MCP registration, some headless flows. Not a substitute for `jf config` in skills. | - -**Important — do not treat env vars as a recovery shortcut after a failed `/jfrog-init`:** - -- When `/jfrog-init` **succeeds**, Step 5 **writes the resolved platform URL into the plugin-owned `mcp.json`**, replacing `${JFROG_PLATFORM_URL}` / `${JFROG_URL}` placeholders from your live `jf config`. Env vars you set afterward do not re-run that substitution. -- When `/jfrog-init` **fails or stops early**, there is **no guaranteed recovery path** from "set env vars and retry." Fix the reported step (CLI install, auth, MCP file, project, catalog entitlement) and **re-run `/jfrog-init`**, then restart the harness. -- Setting env vars without a successful init walk may appear to help in one harness and silently fail in another — always prefer completing `/jfrog-init` (or the harness-specific MCP login flow documented in that README). - -## Verify (required after install) - -Complete **all** rows that apply to your harness before considering the install done. - -| Check | Pass criteria | -| --- | --- | -| Plugin present | Harness-specific list/install command shows the JFrog plugin enabled. | -| Skills loaded | JFrog skills appear in the harness skill picker (`/skills`, `@jfrog`, or `/jfrog:…` invocations). | -| JFrog CLI | `jf rt ping` succeeds for your configured server. | -| Platform MCP (if bundled) | Harness MCP list shows `jfrog` connected after OAuth/login where required. | -| Agent Guard (optional) | Asking the agent to list installable MCPs returns catalog rows for your project. | - -## Recovery playbook - -| Symptom | Do this | Do **not** do this | -| --- | --- | --- | -| MCP missing after install | Run `/jfrog-init` (if available), complete OAuth/login steps, **restart harness**, re-verify MCP list. | Assume `JFROG_URL` alone will register MCP on every harness. | -| `/jfrog-init` stopped at CLI/auth | Follow the skill prompt (`jf config add`, web login, or token path), then **re-run `/jfrog-init`**. | Skip init and only export env vars. | -| Plugin MCP file missing | Reinstall/update the JFrog plugin, restart, re-run `/jfrog-init`. | Hand-edit unrelated MCP configs. | -| Placeholder URL still in plugin `mcp.json` | Fix `jf config` for the intended server, re-run `/jfrog-init` Step 5 substitution. | Reinstall the plugin when the detector says auth/URL resolution failed. | -| Stale plugin version | Upgrade via the harness marketplace/npm/update command, restart, verify version column. | Trust a new chat session without restart after upgrade. | -| Install fails with marketplace schema errors | Refresh the marketplace catalog (for Claude Code, `claude plugin marketplace update claude-plugins-official`) and retry the install — a stale or invalid *aggregate* catalog rejects every plugin in it, including this one. See [AX-2176](https://jfrog-int.atlassian.net/browse/AX-2176). | Read the indexed error (`plugins.0.source`) as a diagnosis of the JFrog plugin. | - -## Harness-specific install docs - -Document **only differences** from this page in each harness guide: - -| Harness | Install doc | -| --- | --- | -| Claude Code | [README](../README.md) · [Web](https://docs.jfrog.com/ai-ml/docs/claude-code) | -| VS Code (Copilot) | [README](https://github.com/jfrog/vscode-plugin/blob/main/README.md) · [Web](https://docs.jfrog.com/ai-ml/docs/vs-code) | -| Cursor | [README](https://github.com/jfrog/cursor-plugin/blob/main/README.md) · [Web](https://docs.jfrog.com/ai-ml/docs/cursor) | -| OpenCode | [README](https://github.com/jfrog/opencode-jfrog-plugin/blob/main/README.md) · [Web](https://docs.jfrog.com/ai-ml/docs/opencode) — see also [AX-1780](https://jfrog-int.atlassian.net/browse/AX-1780), [AX-2122](https://jfrog-int.atlassian.net/browse/AX-2122), [AX-2124](https://jfrog-int.atlassian.net/browse/AX-2124) for OpenCode-specific init/MCP work | -| Codex | [README](https://github.com/jfrog/codex-plugin/blob/main/README.md) · [Web source](https://github.com/jfrog/codex-plugin/blob/main/docs/install-jfrog-plugin-for-codex.md) | -| Devin | [README](https://github.com/jfrog/devin-plugin/blob/main/README.md) · [Web source](https://github.com/jfrog/devin-plugin/blob/main/docs/install-jfrog-plugin-for-devin.md) | -| Kiro | [README](https://github.com/jfrog/jfrog-kiro-power/blob/main/README.md) — MCP/Kiro adapter gaps tracked separately | - -## Maintainer checklist (release review) - -Before merging documentation or cutting a plugin release: - -- [ ] Harness README links to this shared guide and does not contradict it on init, env vars, restart, or recovery. -- [ ] Verification steps appear in the install section (not only FAQ/troubleshooting). -- [ ] OpenCode cross-links [AX-1780](https://jfrog-int.atlassian.net/browse/AX-1780), [AX-2122](https://jfrog-int.atlassian.net/browse/AX-2122), [AX-2124](https://jfrog-int.atlassian.net/browse/AX-2124) when describing OpenCode-only behavior. -- [ ] Codex and Devin web-doc sources under `docs/install-jfrog-plugin-for-*.md` stay aligned with the harness README. -- [ ] `node scripts/validate-install-docs.mjs` passes in repos that ship the checker. From efc01688351af0adeb55227f2d4f5b2102abb936 Mon Sep 17 00:00:00 2001 From: Yoni Melki Date: Tue, 25 Aug 2026 19:01:40 +0300 Subject: [PATCH 3/7] AX-2162 - Document JFROG_PLATFORM_URL instead of JFROG_URL The host-only env var is the documented name. https://${JFROG_PLATFORM_URL} is the platform URL; do not show the legacy JFROG_URL name. Co-authored-by: Cursor --- README.md | 8 ++++---- docs/install-and-verify.md | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index fb893d1..1a7208b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The JFrog plugin provides the following capabilities, grouped by component: | Component | Feature | Description | | --- | --- | --- | -| **MCP** | JFrog MCP server | Remote JFrog MCP server auto-attached to every session via `.mcp.json` at `${JFROG_URL}/mcp` (OAuth, no API keys). | +| **MCP** | JFrog MCP server | Remote JFrog MCP server auto-attached to every session via `.mcp.json` at `https://${JFROG_PLATFORM_URL}/mcp` (OAuth, no API keys). | | **Skill** | JFrog Platform | Interact with Artifactory repositories, builds, permissions, users, access tokens, projects, release bundles, and platform administration via the JFrog CLI and REST/GraphQL APIs. Also covers security audits, CVE lookups, and Advanced Security exposure queries. | | **Skill** | Package safety & download | Check whether npm, Maven, PyPI, Go, and other packages are safe, curated, or allowed, then download them through Artifactory remote caches or curation-aware package managers. | | **Hook + Skill** | Agent Package Resolution (Preview) | Automatically route packages installed by the AI agent through your organization's JFrog Artifactory, keeping agent-driven installs inside your Curation, Xray, and governance perimeter. | @@ -28,7 +28,7 @@ Before installing, make sure you have: - **Node.js** (≥ 18) — with `npx` on your `PATH` (used by the Agent Guard). - **Skill runtime requirements** — `jf` CLI, `jq`, and `curl` on `PATH`, plus a configured JFrog instance. For the minimum versions, see the upstream skills [`Requirements`](https://github.com/jfrog/jfrog-skills/blob/v0.11.0/README.md#requirements). Configure the CLI with `jf config add` — see [Authentication](#authentication). - **JFrog AI Catalog** (optional) — If you want to use the Agent Guard feature, your JFrog subscription needs to include the AI Catalog entitlement. Contact your JFrog account team if you're unsure whether it's enabled. -- **JFrog CLI ≥ 2.105.0** (optional) — If you want the Agent Guard to auto-resolve credentials/server ID from the JFrog CLI instead of `JFROG_URL`/`JFROG_ACCESS_TOKEN` env vars. Older CLIs don't support the `--format` flag used by `jf config show` for this. +- **JFrog CLI ≥ 2.105.0** (optional) — If you want the Agent Guard to auto-resolve credentials/server ID from the JFrog CLI instead of `JFROG_PLATFORM_URL`/`JFROG_ACCESS_TOKEN` env vars. Older CLIs don't support the `--format` flag used by `jf config show` for this. - **JFrog project** (optional) — If you want to use the Agent Guard feature. --- @@ -74,7 +74,7 @@ claude --plugin-dir /path/to/claude-plugin | Variable | Description | | --- | --- | -| `JFROG_URL` | Your JFrog platform URL, e.g. `https://mycompany.jfrog.io` (no trailing `/`) | +| `JFROG_PLATFORM_URL` | Your JFrog platform host, e.g. `mycompany.jfrog.io` (no `https://`, no trailing `/`). The MCP URL is `https://${JFROG_PLATFORM_URL}/mcp`. | | `JFROG_ACCESS_TOKEN` | Your JFrog access token | ### 2. Configure the JFrog CLI @@ -88,7 +88,7 @@ If you have never configured the JFrog CLI on this machine: ``` 3. Follow the interactive prompts to enter the same JFrog platform URL and access token. -Setting `JFROG_URL` / `JFROG_ACCESS_TOKEN` alone does **not** replace a successful `/jfrog-init` walk or repair a failed one — see [environment variables](docs/install-and-verify.md#environment-variables). +Setting `JFROG_PLATFORM_URL` / `JFROG_ACCESS_TOKEN` alone does **not** replace a successful `/jfrog-init` walk or repair a failed one — see [environment variables](docs/install-and-verify.md#environment-variables). --- diff --git a/docs/install-and-verify.md b/docs/install-and-verify.md index 1ba68e1..3c6ac3e 100644 --- a/docs/install-and-verify.md +++ b/docs/install-and-verify.md @@ -35,7 +35,7 @@ How to install, verify, and recover the JFrog plugin for Claude Code. This docum | Variable | Typical form | Used for | | --- | --- | --- | -| `JFROG_URL` | Full platform URL (`https://mycompany.jfrog.io`, no trailing `/`) | Plugin MCP and some skill paths. Prefer `jf config` for skills. | +| `JFROG_PLATFORM_URL` | Host only (`mycompany.jfrog.io`, no `https://`, no trailing `/`) | Plugin MCP (`https://${JFROG_PLATFORM_URL}/mcp`) and related resolution. Prefer `jf config` for skills. | | `JFROG_ACCESS_TOKEN` | JWT access token | Some headless flows. Not a substitute for `jf config` in skills. | **Do not treat env vars as a recovery shortcut after a failed `/jfrog-init`:** @@ -59,7 +59,7 @@ Complete all rows before considering the install done. | Symptom | Do this | Do **not** do this | | --- | --- | --- | -| MCP missing after install | Run `/jfrog-init`, complete OAuth if prompted, **restart Claude Code**, re-check MCP tools. | Assume `JFROG_URL` alone will register MCP. | +| MCP missing after install | Run `/jfrog-init`, complete OAuth if prompted, **restart Claude Code**, re-check MCP tools. | Assume `JFROG_PLATFORM_URL` alone will register MCP. | | `/jfrog-init` stopped at CLI/auth | Follow the skill prompt (`jf config add`, web login, or token path), then **re-run `/jfrog-init`**. | Skip init and only export env vars. | | Plugin MCP file missing | Reinstall/update the JFrog plugin, restart, re-run `/jfrog-init`. | Hand-edit unrelated MCP configs. | | Placeholder URL still in plugin `mcp.json` | Fix `jf config` for the intended server, re-run `/jfrog-init` so it can substitute the URL. | Reinstall the plugin when the detector says auth/URL resolution failed. | From 9fb0449f83d56470e2c1a7da4cd6eca606615cfe Mon Sep 17 00:00:00 2001 From: Yoni Melki Date: Wed, 26 Aug 2026 14:53:51 +0300 Subject: [PATCH 4/7] Drop the extra install markdown file Keep install, verify, and recovery in the README so the repo is not a second copy of the public JFrog docs. Co-authored-by: Cursor --- CONTRIBUTING.md | 2 +- README.md | 13 ++++--- docs/install-and-verify.md | 75 -------------------------------------- 3 files changed, 9 insertions(+), 81 deletions(-) delete mode 100644 docs/install-and-verify.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1a7dae6..9823348 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,7 +47,7 @@ This downloads the pinned upstream tarball and replaces the contents of `skills/ - [ ] No secrets, credentials, or files under `**/local-cache/` committed. - [ ] If the skill tree changed: `pin` in `.github/scripts/sync-skills-vendor.json` matches the upstream tag the new tree was generated from. - [ ] Smoke-test: `claude --plugin-dir .` from the repo root. -- [ ] Install/recovery docs: README links [docs/install-and-verify.md](docs/install-and-verify.md), includes a **Verify** section, and does not contradict it on init/env/restart/recovery. Do not send readers to another plugin repository for those steps. +- [ ] README includes a **Verify** section and does not send readers to another plugin repository for install or recovery. ### Submitting to the Claude plugin directory diff --git a/README.md b/README.md index 1a7208b..3aca5c8 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,6 @@ JFrog plugin for [Claude Code](https://claude.com/product/claude-code): artifact management, security scanning, and supply-chain best practices, and Agent Guard. -> **Install, verify, and recovery:** [docs/install-and-verify.md](docs/install-and-verify.md). - ## Features The JFrog plugin provides the following capabilities, grouped by component: @@ -88,7 +86,7 @@ If you have never configured the JFrog CLI on this machine: ``` 3. Follow the interactive prompts to enter the same JFrog platform URL and access token. -Setting `JFROG_PLATFORM_URL` / `JFROG_ACCESS_TOKEN` alone does **not** replace a successful `/jfrog-init` walk or repair a failed one — see [environment variables](docs/install-and-verify.md#environment-variables). +Setting `JFROG_PLATFORM_URL` / `JFROG_ACCESS_TOKEN` alone does **not** replace a successful `/jfrog-init` walk or repair a failed one. Fix the step `/jfrog-init` reports, re-run it, then restart Claude Code. --- @@ -100,8 +98,13 @@ Verification is a required install step, not a troubleshooting fallback: 2. Run **`/jfrog-init`** — it completes without blocking errors. Restart Claude Code if it changed the MCP config. 3. `jf rt ping` — succeeds against your configured server. -If a check fails, fix the step `/jfrog-init` reports and re-run it, then restart. See the -[recovery playbook](docs/install-and-verify.md#recovery-playbook). +If a check fails, fix the step `/jfrog-init` reports, re-run it, then restart Claude Code. + +| Symptom | Do this | Do **not** do this | +| --- | --- | --- | +| MCP missing after install | Run `/jfrog-init`, complete OAuth if prompted, **restart Claude Code**, re-check MCP tools. | Assume `JFROG_PLATFORM_URL` alone will register MCP. | +| `/jfrog-init` stopped at CLI/auth | Follow the skill prompt, then **re-run `/jfrog-init`**. | Skip init and only export env vars. | +| Install fails with marketplace schema errors | Run `claude plugin marketplace update claude-plugins-official` and retry. | Treat `plugins.0.source` as a diagnosis of this plugin. | --- diff --git a/docs/install-and-verify.md b/docs/install-and-verify.md deleted file mode 100644 index 3c6ac3e..0000000 --- a/docs/install-and-verify.md +++ /dev/null @@ -1,75 +0,0 @@ -# Claude Code install, verify, and recovery - -How to install, verify, and recover the JFrog plugin for Claude Code. This document covers Claude Code only. - -**Web overview:** [Install JFrog Agent Plugin for Claude Code](https://docs.jfrog.com/ai-ml/docs/claude-code) - -## Prerequisites - -| Requirement | Notes | -| --- | --- | -| JFrog Platform instance | You can authenticate against it (URL + token or browser login). | -| Claude Code CLI (≥ 1.0) | Plugin commands (`claude plugin …`) must be available. | -| Node.js ≥ 18 | With `npx` on `PATH` (used by Agent Guard and `/jfrog-init`). | -| `jf`, `jq`, `curl` on `PATH` | Required for JFrog skills at runtime. Install and configure the CLI with [`jf config add`](https://docs.jfrog.com/integrations/docs/jf-config-add) or `jf login`. | -| JFrog AI Catalog (optional) | Required only for Agent Guard MCP catalog features. | - -## Install flow - -1. **Install the plugin** from Claude's official marketplace: - - ```bash - claude plugin marketplace update claude-plugins-official - claude plugin install jfrog@claude-plugins-official - ``` - -2. **Configure the JFrog CLI** (`jf config add` or `jf login`) so skills and detectors can reach your platform. This is the primary credential path for skills. - -3. **Run `/jfrog-init`.** It walks Node → CLI → server reachability → plugin MCP file → project → AI Catalog entitlement. Stop at the first failure and follow the skill's fix prompts. - -4. **Restart Claude Code** after plugin install and after any MCP config change. A new chat session alone is not enough when MCP entries changed. - -5. **Verify** using the checklist below — verification is a required install step, not an FAQ footnote. - -## Environment variables - -| Variable | Typical form | Used for | -| --- | --- | --- | -| `JFROG_PLATFORM_URL` | Host only (`mycompany.jfrog.io`, no `https://`, no trailing `/`) | Plugin MCP (`https://${JFROG_PLATFORM_URL}/mcp`) and related resolution. Prefer `jf config` for skills. | -| `JFROG_ACCESS_TOKEN` | JWT access token | Some headless flows. Not a substitute for `jf config` in skills. | - -**Do not treat env vars as a recovery shortcut after a failed `/jfrog-init`:** - -- When `/jfrog-init` **succeeds**, it writes the resolved platform URL into the plugin-owned `mcp.json`, replacing placeholders from your live `jf config`. Env vars you set afterward do not re-run that substitution. -- When `/jfrog-init` **fails or stops early**, there is no guaranteed recovery path from "set env vars and retry." Fix the reported step (CLI install, auth, MCP file, project, catalog entitlement) and **re-run `/jfrog-init`**, then restart Claude Code. - -## Verify (required after install) - -Complete all rows before considering the install done. - -| Check | Pass criteria | -| --- | --- | -| Plugin present | `/plugins` → **Installed** lists the JFrog plugin. | -| Initialization | `/jfrog-init` completes without blocking errors. Restart Claude Code if it changed MCP config. | -| JFrog CLI | `jf rt ping` succeeds for your configured server. | -| Platform MCP | JFrog MCP tools are available in the session after OAuth if prompted. | -| Agent Guard (optional) | Asking the agent to list installable MCPs returns catalog rows for your project. | - -## Recovery playbook - -| Symptom | Do this | Do **not** do this | -| --- | --- | --- | -| MCP missing after install | Run `/jfrog-init`, complete OAuth if prompted, **restart Claude Code**, re-check MCP tools. | Assume `JFROG_PLATFORM_URL` alone will register MCP. | -| `/jfrog-init` stopped at CLI/auth | Follow the skill prompt (`jf config add`, web login, or token path), then **re-run `/jfrog-init`**. | Skip init and only export env vars. | -| Plugin MCP file missing | Reinstall/update the JFrog plugin, restart, re-run `/jfrog-init`. | Hand-edit unrelated MCP configs. | -| Placeholder URL still in plugin `mcp.json` | Fix `jf config` for the intended server, re-run `/jfrog-init` so it can substitute the URL. | Reinstall the plugin when the detector says auth/URL resolution failed. | -| Stale plugin version | Upgrade via the marketplace, restart, confirm the installed version. | Trust a new chat session without restart after upgrade. | -| Install fails with marketplace schema errors | Run `claude plugin marketplace update claude-plugins-official` and retry the install — a stale or invalid *aggregate* catalog rejects every plugin in it, including this one. | Read the indexed error (`plugins.0.source`) as a diagnosis of the JFrog plugin. | - -## Maintainer checklist (release review) - -Before merging documentation or cutting a plugin release: - -- [ ] [`README.md`](../README.md) and this page agree on init, env vars, restart, verification, and recovery. -- [ ] Verification steps appear in the install section (not only FAQ/troubleshooting). -- [ ] This document does not send readers to another plugin repository for install or recovery steps. From fa3df31dbcf66516cf1de2846c48d14de1503ceb Mon Sep 17 00:00:00 2001 From: Yoni Melki Date: Thu, 27 Aug 2026 15:40:20 +0300 Subject: [PATCH 5/7] Match the MCP placeholder to JFROG_PLATFORM_URL and add the install-docs CI guard. --- .github/workflows/validate.yml | 5 ++ .mcp.json | 2 +- README.md | 6 +- scripts/validate-install-docs.mjs | 97 ++++++++++++++++++++++++++ scripts/validate-install-docs.test.mjs | 68 ++++++++++++++++++ 5 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 scripts/validate-install-docs.mjs create mode 100644 scripts/validate-install-docs.test.mjs diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index acc7252..2292c04 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -25,3 +25,8 @@ jobs: - name: Run MCP rewrite hook unit tests run: node --test scripts/claude-mcp-json-discover.test.mjs scripts/claude-align-mcp-json.test.mjs scripts/rewrite-mcp-json.test.mjs scripts/agent-guard-check.test.mjs + + - name: Validate install/recovery docs + run: | + node --test scripts/validate-install-docs.test.mjs + JFROG_PLUGIN_HARNESS=claude node scripts/validate-install-docs.mjs diff --git a/.mcp.json b/.mcp.json index d7b7ef3..6b02ac5 100644 --- a/.mcp.json +++ b/.mcp.json @@ -2,7 +2,7 @@ "mcpServers": { "jfrog": { "type": "http", - "url": "${JFROG_URL}/mcp" + "url": "https://${JFROG_PLATFORM_URL}/mcp" } } } diff --git a/README.md b/README.md index 3aca5c8..daff87e 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Before installing, make sure you have: - **Node.js** (≥ 18) — with `npx` on your `PATH` (used by the Agent Guard). - **Skill runtime requirements** — `jf` CLI, `jq`, and `curl` on `PATH`, plus a configured JFrog instance. For the minimum versions, see the upstream skills [`Requirements`](https://github.com/jfrog/jfrog-skills/blob/v0.11.0/README.md#requirements). Configure the CLI with `jf config add` — see [Authentication](#authentication). - **JFrog AI Catalog** (optional) — If you want to use the Agent Guard feature, your JFrog subscription needs to include the AI Catalog entitlement. Contact your JFrog account team if you're unsure whether it's enabled. -- **JFrog CLI ≥ 2.105.0** (optional) — If you want the Agent Guard to auto-resolve credentials/server ID from the JFrog CLI instead of `JFROG_PLATFORM_URL`/`JFROG_ACCESS_TOKEN` env vars. Older CLIs don't support the `--format` flag used by `jf config show` for this. +- **JFrog CLI ≥ 2.105.0** (optional) — If you want the Agent Guard to auto-resolve the credentials/server ID from the JFrog CLI configuration. Older CLIs don't support the `--format` flag used by `jf config show` for this. - **JFrog project** (optional) — If you want to use the Agent Guard feature. --- @@ -98,7 +98,9 @@ Verification is a required install step, not a troubleshooting fallback: 2. Run **`/jfrog-init`** — it completes without blocking errors. Restart Claude Code if it changed the MCP config. 3. `jf rt ping` — succeeds against your configured server. -If a check fails, fix the step `/jfrog-init` reports, re-run it, then restart Claude Code. +If a check fails, see [Recovery](#recovery). Fix the step `/jfrog-init` reports, re-run it, then restart Claude Code. + +## Recovery | Symptom | Do this | Do **not** do this | | --- | --- | --- | diff --git a/scripts/validate-install-docs.mjs b/scripts/validate-install-docs.mjs new file mode 100644 index 0000000..33f5268 --- /dev/null +++ b/scripts/validate-install-docs.mjs @@ -0,0 +1,97 @@ +#!/usr/bin/env node +// Copyright (c) JFrog Ltd. 2026 +// Licensed under the Apache License, Version 2.0 +// Validates install/recovery documentation invariants. + +import { readFileSync, existsSync } from 'node:fs'; +import { join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const repoRoot = process.cwd(); + +const HARNESS_OWN_REPO = { + claude: 'claude-plugin', + codex: 'codex-plugin', + cursor: 'cursor-plugin', + devin: 'devin-plugin', + opencode: 'opencode-jfrog-plugin', + vscode: 'vscode-plugin', +}; + +const ALL_PLUGIN_REPOS = Object.values(HARNESS_OWN_REPO); + +const REQUIRED_README_MARKERS = ['## Verify', '## Recovery']; + +const FORBIDDEN_PATTERNS = [ + { + re: /setting\s+(?:the\s+)?environment\s+variables?\s+after\s+a\s+failed\s+init\s+may\s+repair/i, + message: 'must not claim env vars repair failed init', + }, + { + re: /JFROG_URL/, + message: 'must not document the legacy JFROG_URL env var; use JFROG_PLATFORM_URL', + }, + { + re: /atlassian\.net/i, + message: 'must not reference JFrog Jira (atlassian.net) in repo files', + }, + { + re: /\b(?:AX|MLD)-\d+\b/, + message: 'must not include Jira ticket keys in repo files', + }, +]; + +export function validateInstallDocs({ repoRoot: root, harness }) { + const errors = []; + const readmePath = join(root, 'README.md'); + if (!existsSync(readmePath)) { + return [`${harness}: missing README.md`]; + } + const files = [{ label: 'README.md', text: readFileSync(readmePath, 'utf8') }]; + + const readme = files[0].text; + for (const marker of REQUIRED_README_MARKERS) { + if (!readme.includes(marker)) { + errors.push(`${harness}: README.md missing required marker: ${marker}`); + } + } + + const ownRepo = HARNESS_OWN_REPO[harness]; + const otherRepos = ALL_PLUGIN_REPOS.filter((name) => name !== ownRepo); + + for (const { label, text } of files) { + for (const { re, message } of FORBIDDEN_PATTERNS) { + if (re.test(text)) errors.push(`${harness}: ${label} ${message}`); + } + for (const other of otherRepos) { + if (text.includes(`github.com/jfrog/${other}`)) { + errors.push(`${harness}: ${label} must not link to github.com/jfrog/${other}`); + } + } + } + + return errors; +} + +function main() { + const harness = process.env.JFROG_PLUGIN_HARNESS ?? inferHarness(repoRoot); + const errors = validateInstallDocs({ repoRoot, harness }); + if (errors.length) { + console.error('install-docs validation failed:'); + for (const e of errors) console.error(` - ${e}`); + process.exit(1); + } + console.log('install-docs validation passed'); +} + +function inferHarness(root) { + if (existsSync(join(root, '.codex-plugin'))) return 'codex'; + if (existsSync(join(root, '.devin-plugin'))) return 'devin'; + if (existsSync(join(root, '.claude-plugin'))) return 'claude'; + if (existsSync(join(root, 'plugins', 'jfrog', '.cursor-plugin'))) return 'cursor'; + if (existsSync(join(root, 'plugin', '.claude-plugin'))) return 'vscode'; + if (existsSync(join(root, 'package.json')) && root.endsWith('opencode-jfrog-plugin')) return 'opencode'; + return 'unknown'; +} + +if (process.argv[1] === fileURLToPath(import.meta.url)) main(); diff --git a/scripts/validate-install-docs.test.mjs b/scripts/validate-install-docs.test.mjs new file mode 100644 index 0000000..25965d5 --- /dev/null +++ b/scripts/validate-install-docs.test.mjs @@ -0,0 +1,68 @@ +// Copyright (c) JFrog Ltd. 2026 +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { mkdtempSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { validateInstallDocs } from './validate-install-docs.mjs'; + +function writeReadme(root, body) { + writeFileSync(join(root, 'README.md'), body); +} + +test('validateInstallDocs passes when README has Verify, Recovery, and no other-plugin links', () => { + const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); + writeReadme(root, '# Claude\n\n## Verify\n\n1. list plugins\n\n## Recovery\n\n'); + assert.deepEqual(validateInstallDocs({ repoRoot: root, harness: 'claude' }), []); +}); + +test('validateInstallDocs flags missing Verify section', () => { + const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); + writeReadme(root, '# Claude\n\nInstall the plugin.\n'); + const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); + assert.ok(errors.some((e) => e.includes('## Verify'))); +}); + +test('validateInstallDocs flags missing Recovery section', () => { + const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); + writeReadme(root, '# Claude\n\n## Verify\n\n1. list plugins\n'); + const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); + assert.ok(errors.some((e) => e.includes('## Recovery'))); +}); + +test('validateInstallDocs rejects contradictory failed-init env-var recovery claims', () => { + const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); + writeReadme( + root, + '# x\n## Verify\n## Recovery\nSetting environment variables after a failed init may repair MCP registration.' + ); + const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); + assert.ok(errors.some((e) => e.includes('env vars repair failed init'))); +}); + +test('validateInstallDocs rejects the legacy JFROG_URL env var', () => { + const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); + writeReadme(root, '# Claude\n## Verify\n## Recovery\nSet `JFROG_URL` to your platform.\n'); + const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); + assert.ok(errors.some((e) => e.includes('JFROG_URL'))); +}); + +test('validateInstallDocs rejects links to other plugin GitHub repos', () => { + const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); + writeReadme( + root, + '# Claude\n## Verify\n## Recovery\nSee https://github.com/jfrog/codex-plugin/blob/main/README.md\n' + ); + const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); + assert.ok(errors.some((e) => e.includes('codex-plugin'))); +}); + +test('validateInstallDocs rejects Jira URLs and ticket keys', () => { + const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); + const host = ['jfrog-int', 'atlassian', 'net'].join('.'); + const key = ['AX', '1780'].join('-'); + writeReadme(root, `# Claude\n## Verify\n## Recovery\nSee [${key}](https://${host}/browse/${key}).\n`); + const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); + assert.ok(errors.some((e) => e.includes('atlassian.net'))); + assert.ok(errors.some((e) => e.includes('Jira ticket keys'))); +}); From c98609f31b5388e678fc03ab4b147e03c8ac30ec Mon Sep 17 00:00:00 2001 From: Yoni Melki Date: Thu, 27 Aug 2026 16:22:34 +0300 Subject: [PATCH 6/7] Drop the install-docs README checker and keep this repo self-contained. --- .github/workflows/validate.yml | 5 - docs/package-resolution-user-guide.md | 7 +- modules/copilot-session-start.mjs | 4 +- .../package-resolution/scripts/onboarding.mjs | 16 +-- scripts/validate-install-docs.mjs | 97 ------------------- scripts/validate-install-docs.test.mjs | 68 ------------- 6 files changed, 7 insertions(+), 190 deletions(-) delete mode 100644 scripts/validate-install-docs.mjs delete mode 100644 scripts/validate-install-docs.test.mjs diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 2292c04..acc7252 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -25,8 +25,3 @@ jobs: - name: Run MCP rewrite hook unit tests run: node --test scripts/claude-mcp-json-discover.test.mjs scripts/claude-align-mcp-json.test.mjs scripts/rewrite-mcp-json.test.mjs scripts/agent-guard-check.test.mjs - - - name: Validate install/recovery docs - run: | - node --test scripts/validate-install-docs.test.mjs - JFROG_PLUGIN_HARNESS=claude node scripts/validate-install-docs.mjs diff --git a/docs/package-resolution-user-guide.md b/docs/package-resolution-user-guide.md index 297800d..a56826f 100644 --- a/docs/package-resolution-user-guide.md +++ b/docs/package-resolution-user-guide.md @@ -101,12 +101,9 @@ To turn it off in the config file itself, set `"enabled": false`. If your file i This is a preview, and your feedback directly shapes what ships next. Please tell us about anything that felt confusing, broken, or surprising, good or bad. -File an issue on GitHub, in whichever plugin repo you use: +File an issue on GitHub: [github.com/jfrog/claude-plugin/issues](https://github.com/jfrog/claude-plugin/issues) -- Cursor: [github.com/jfrog/cursor-plugin/issues](https://github.com/jfrog/cursor-plugin/issues) -- Claude Code: [github.com/jfrog/claude-plugin/issues](https://github.com/jfrog/claude-plugin/issues) -- VS Code: [github.com/jfrog/vscode-plugin/issues](https://github.com/jfrog/vscode-plugin/issues) -- Email: plugins-feedback@jfrog.com +Email: plugins-feedback@jfrog.com --- diff --git a/modules/copilot-session-start.mjs b/modules/copilot-session-start.mjs index 9d0c275..cfa1bf2 100644 --- a/modules/copilot-session-start.mjs +++ b/modules/copilot-session-start.mjs @@ -1,6 +1,6 @@ #!/usr/bin/env node -// GitHub Copilot Chat SessionStart hook runner (installed via the VS Code -// Copilot plugin — see jfrog/vscode-plugin). +// GitHub Copilot Chat SessionStart hook runner. + // // Usage: node copilot-session-start.mjs // Example: node copilot-session-start.mjs package-resolution diff --git a/modules/package-resolution/scripts/onboarding.mjs b/modules/package-resolution/scripts/onboarding.mjs index 8c5ce6a..52024bd 100644 --- a/modules/package-resolution/scripts/onboarding.mjs +++ b/modules/package-resolution/scripts/onboarding.mjs @@ -34,26 +34,16 @@ const log = createLogger("onboarding"); const here = path.dirname(fileURLToPath(import.meta.url)); const NUDGE_TEMPLATE = path.join(here, "../onboarding/session-start-nudge.md"); -export const CURSOR_ADMIN_GUIDE_URL = - "https://github.com/jfrog/cursor-plugin/blob/main/docs/package-resolution-admin-guide.md"; -export const CLAUDE_ADMIN_GUIDE_URL = +export const ADMIN_GUIDE_URL = "https://github.com/jfrog/claude-plugin/blob/main/docs/package-resolution-admin-guide.md"; -export const COPILOT_ADMIN_GUIDE_URL = - "https://github.com/jfrog/vscode-plugin/blob/main/docs/package-resolution-admin-guide.md"; - -const ADMIN_GUIDE_URL_BY_IDE = { - claude_code: CLAUDE_ADMIN_GUIDE_URL, - cursor: CURSOR_ADMIN_GUIDE_URL, - copilot: COPILOT_ADMIN_GUIDE_URL, -}; /** Human-readable list of APR package types (keeps nudge copy in sync with code). */ export function supportedTypesPhrase() { return PACKAGE_TYPES.join(", "); } -function adminGuideUrlForIde(ide) { - return ADMIN_GUIDE_URL_BY_IDE[ide] ?? CLAUDE_ADMIN_GUIDE_URL; +function adminGuideUrlForIde(_ide) { + return ADMIN_GUIDE_URL; } function configureCommandPath() { diff --git a/scripts/validate-install-docs.mjs b/scripts/validate-install-docs.mjs deleted file mode 100644 index 33f5268..0000000 --- a/scripts/validate-install-docs.mjs +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env node -// Copyright (c) JFrog Ltd. 2026 -// Licensed under the Apache License, Version 2.0 -// Validates install/recovery documentation invariants. - -import { readFileSync, existsSync } from 'node:fs'; -import { join } from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const repoRoot = process.cwd(); - -const HARNESS_OWN_REPO = { - claude: 'claude-plugin', - codex: 'codex-plugin', - cursor: 'cursor-plugin', - devin: 'devin-plugin', - opencode: 'opencode-jfrog-plugin', - vscode: 'vscode-plugin', -}; - -const ALL_PLUGIN_REPOS = Object.values(HARNESS_OWN_REPO); - -const REQUIRED_README_MARKERS = ['## Verify', '## Recovery']; - -const FORBIDDEN_PATTERNS = [ - { - re: /setting\s+(?:the\s+)?environment\s+variables?\s+after\s+a\s+failed\s+init\s+may\s+repair/i, - message: 'must not claim env vars repair failed init', - }, - { - re: /JFROG_URL/, - message: 'must not document the legacy JFROG_URL env var; use JFROG_PLATFORM_URL', - }, - { - re: /atlassian\.net/i, - message: 'must not reference JFrog Jira (atlassian.net) in repo files', - }, - { - re: /\b(?:AX|MLD)-\d+\b/, - message: 'must not include Jira ticket keys in repo files', - }, -]; - -export function validateInstallDocs({ repoRoot: root, harness }) { - const errors = []; - const readmePath = join(root, 'README.md'); - if (!existsSync(readmePath)) { - return [`${harness}: missing README.md`]; - } - const files = [{ label: 'README.md', text: readFileSync(readmePath, 'utf8') }]; - - const readme = files[0].text; - for (const marker of REQUIRED_README_MARKERS) { - if (!readme.includes(marker)) { - errors.push(`${harness}: README.md missing required marker: ${marker}`); - } - } - - const ownRepo = HARNESS_OWN_REPO[harness]; - const otherRepos = ALL_PLUGIN_REPOS.filter((name) => name !== ownRepo); - - for (const { label, text } of files) { - for (const { re, message } of FORBIDDEN_PATTERNS) { - if (re.test(text)) errors.push(`${harness}: ${label} ${message}`); - } - for (const other of otherRepos) { - if (text.includes(`github.com/jfrog/${other}`)) { - errors.push(`${harness}: ${label} must not link to github.com/jfrog/${other}`); - } - } - } - - return errors; -} - -function main() { - const harness = process.env.JFROG_PLUGIN_HARNESS ?? inferHarness(repoRoot); - const errors = validateInstallDocs({ repoRoot, harness }); - if (errors.length) { - console.error('install-docs validation failed:'); - for (const e of errors) console.error(` - ${e}`); - process.exit(1); - } - console.log('install-docs validation passed'); -} - -function inferHarness(root) { - if (existsSync(join(root, '.codex-plugin'))) return 'codex'; - if (existsSync(join(root, '.devin-plugin'))) return 'devin'; - if (existsSync(join(root, '.claude-plugin'))) return 'claude'; - if (existsSync(join(root, 'plugins', 'jfrog', '.cursor-plugin'))) return 'cursor'; - if (existsSync(join(root, 'plugin', '.claude-plugin'))) return 'vscode'; - if (existsSync(join(root, 'package.json')) && root.endsWith('opencode-jfrog-plugin')) return 'opencode'; - return 'unknown'; -} - -if (process.argv[1] === fileURLToPath(import.meta.url)) main(); diff --git a/scripts/validate-install-docs.test.mjs b/scripts/validate-install-docs.test.mjs deleted file mode 100644 index 25965d5..0000000 --- a/scripts/validate-install-docs.test.mjs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) JFrog Ltd. 2026 -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import { mkdtempSync, writeFileSync } from 'node:fs'; -import { tmpdir } from 'node:os'; -import { join } from 'node:path'; -import { validateInstallDocs } from './validate-install-docs.mjs'; - -function writeReadme(root, body) { - writeFileSync(join(root, 'README.md'), body); -} - -test('validateInstallDocs passes when README has Verify, Recovery, and no other-plugin links', () => { - const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); - writeReadme(root, '# Claude\n\n## Verify\n\n1. list plugins\n\n## Recovery\n\n'); - assert.deepEqual(validateInstallDocs({ repoRoot: root, harness: 'claude' }), []); -}); - -test('validateInstallDocs flags missing Verify section', () => { - const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); - writeReadme(root, '# Claude\n\nInstall the plugin.\n'); - const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); - assert.ok(errors.some((e) => e.includes('## Verify'))); -}); - -test('validateInstallDocs flags missing Recovery section', () => { - const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); - writeReadme(root, '# Claude\n\n## Verify\n\n1. list plugins\n'); - const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); - assert.ok(errors.some((e) => e.includes('## Recovery'))); -}); - -test('validateInstallDocs rejects contradictory failed-init env-var recovery claims', () => { - const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); - writeReadme( - root, - '# x\n## Verify\n## Recovery\nSetting environment variables after a failed init may repair MCP registration.' - ); - const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); - assert.ok(errors.some((e) => e.includes('env vars repair failed init'))); -}); - -test('validateInstallDocs rejects the legacy JFROG_URL env var', () => { - const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); - writeReadme(root, '# Claude\n## Verify\n## Recovery\nSet `JFROG_URL` to your platform.\n'); - const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); - assert.ok(errors.some((e) => e.includes('JFROG_URL'))); -}); - -test('validateInstallDocs rejects links to other plugin GitHub repos', () => { - const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); - writeReadme( - root, - '# Claude\n## Verify\n## Recovery\nSee https://github.com/jfrog/codex-plugin/blob/main/README.md\n' - ); - const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); - assert.ok(errors.some((e) => e.includes('codex-plugin'))); -}); - -test('validateInstallDocs rejects Jira URLs and ticket keys', () => { - const root = mkdtempSync(join(tmpdir(), 'claude-docs-')); - const host = ['jfrog-int', 'atlassian', 'net'].join('.'); - const key = ['AX', '1780'].join('-'); - writeReadme(root, `# Claude\n## Verify\n## Recovery\nSee [${key}](https://${host}/browse/${key}).\n`); - const errors = validateInstallDocs({ repoRoot: root, harness: 'claude' }); - assert.ok(errors.some((e) => e.includes('atlassian.net'))); - assert.ok(errors.some((e) => e.includes('Jira ticket keys'))); -}); From 40396b3c4214466a7c3f2385d69bd822df9f79f6 Mon Sep 17 00:00:00 2001 From: Yoni Melki Date: Thu, 27 Aug 2026 16:40:01 +0300 Subject: [PATCH 7/7] Restore vendored modules to the jfrog-agent-hooks copy. --- modules/copilot-session-start.mjs | 4 ++-- .../package-resolution/scripts/onboarding.mjs | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/modules/copilot-session-start.mjs b/modules/copilot-session-start.mjs index cfa1bf2..9d0c275 100644 --- a/modules/copilot-session-start.mjs +++ b/modules/copilot-session-start.mjs @@ -1,6 +1,6 @@ #!/usr/bin/env node -// GitHub Copilot Chat SessionStart hook runner. - +// GitHub Copilot Chat SessionStart hook runner (installed via the VS Code +// Copilot plugin — see jfrog/vscode-plugin). // // Usage: node copilot-session-start.mjs // Example: node copilot-session-start.mjs package-resolution diff --git a/modules/package-resolution/scripts/onboarding.mjs b/modules/package-resolution/scripts/onboarding.mjs index 52024bd..8c5ce6a 100644 --- a/modules/package-resolution/scripts/onboarding.mjs +++ b/modules/package-resolution/scripts/onboarding.mjs @@ -34,16 +34,26 @@ const log = createLogger("onboarding"); const here = path.dirname(fileURLToPath(import.meta.url)); const NUDGE_TEMPLATE = path.join(here, "../onboarding/session-start-nudge.md"); -export const ADMIN_GUIDE_URL = +export const CURSOR_ADMIN_GUIDE_URL = + "https://github.com/jfrog/cursor-plugin/blob/main/docs/package-resolution-admin-guide.md"; +export const CLAUDE_ADMIN_GUIDE_URL = "https://github.com/jfrog/claude-plugin/blob/main/docs/package-resolution-admin-guide.md"; +export const COPILOT_ADMIN_GUIDE_URL = + "https://github.com/jfrog/vscode-plugin/blob/main/docs/package-resolution-admin-guide.md"; + +const ADMIN_GUIDE_URL_BY_IDE = { + claude_code: CLAUDE_ADMIN_GUIDE_URL, + cursor: CURSOR_ADMIN_GUIDE_URL, + copilot: COPILOT_ADMIN_GUIDE_URL, +}; /** Human-readable list of APR package types (keeps nudge copy in sync with code). */ export function supportedTypesPhrase() { return PACKAGE_TYPES.join(", "); } -function adminGuideUrlForIde(_ide) { - return ADMIN_GUIDE_URL; +function adminGuideUrlForIde(ide) { + return ADMIN_GUIDE_URL_BY_IDE[ide] ?? CLAUDE_ADMIN_GUIDE_URL; } function configureCommandPath() {