Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
---
name: jfrog-ai-catalog-skills
name: jfrog-ai-catalog
description: >-
Discover, install, manage, and publish agent skills hosted in the JFrog AI
Catalog (Artifactory skills repositories) using the JFrog CLI (`jf skills`)
and the JFrog Agent Guard. Lists and searches available skills (catalog-wide
or scoped to a project), shows a skill's versions and which repos host it,
installs the latest or a pinned version, verifies the install, lists
installed skills, updates and removes them, and publishes (uploads) a local
skill bundle and releases new versions.
Use when the user asks what skills are available or installed, to
search/browse the catalog, to install/update/uninstall a skill, to see a
skill's versions, or to publish/upload/release a skill to JFrog /
Artifactory / the AI Catalog.
Discover, install, manage, and publish agent skills and agent plugins hosted
in the JFrog AI Catalog (Artifactory skills and plugins repositories) using
the JFrog CLI (`jf skills`, `jf agent plugins`) and the JFrog Agent Guard.
Lists and searches available skills and plugins (catalog-wide or scoped to a
project), shows versions and which repos host them, installs the latest or a
pinned version, verifies the install, lists installed skills and plugins,
updates and removes them, and publishes a local skill or plugin bundle and
releases new versions. Use when the user asks what skills or plugins are
available or installed, to search/browse the catalog, to
install/update/uninstall/delete a skill or plugin, to see versions, or to
publish/upload/release a skill or plugin to JFrog / Artifactory / the AI
Catalog.
metadata:
role: workflow
---

# JFrog AI Catalog Skills
# JFrog AI Catalog

Discover, install, and manage agent skills from the JFrog AI Catalog
(Artifactory skills repositories), and publish your own skills back to it, all
through the JFrog CLI (`jf skills`) and the JFrog Agent Guard.
Discover, install, and manage agent skills and agent plugins from the JFrog AI
Catalog (Artifactory skills/plugins repositories), and publish your own back to
it, all through the JFrog CLI (`jf skills`, `jf agent plugins`) and the JFrog
Agent Guard.

## Choose a reference file

Expand All @@ -32,6 +34,10 @@ Pick the row matching the user's intent and read that reference file.
| Install or update a skill (latest or a pinned version), or a download is blocked | [references/installing-skills.md](references/installing-skills.md) |
| "What's installed?" / remove an installed skill | [references/managing-installed-skills.md](references/managing-installed-skills.md) |
| Publish / upload / release a skill to the catalog | [references/publishing-skills.md](references/publishing-skills.md) |
| "What plugins are available?" / browse the plugin catalog / list plugin versions / search plugins | [references/discovering-plugins.md](references/discovering-plugins.md) |
| Install or update a plugin (latest or a pinned version) | [references/installing-plugins.md](references/installing-plugins.md) |
| "What plugins are installed?" / remove an installed plugin | [references/managing-installed-plugins.md](references/managing-installed-plugins.md) |
| Publish / upload / release a plugin to the catalog | [references/publishing-plugins.md](references/publishing-plugins.md) |

## Prerequisites

Expand All @@ -43,6 +49,12 @@ Pick the row matching the user's intent and read that reference file.
- The [server selection rules](../jfrog/SKILL.md#server-selection-rules-mandatory)
— resolve the default `<SID>` once and reuse it, pass `--server-id <SID>`
after the subcommand on every `jf` call, and use one server per request.
**Resolve it now, before any `jf` call:**
```bash
jf config show 2>/dev/null \
| awk '/^Server ID:/{id=$NF} /^Default:[[:space:]]*true/{print id; exit}'
# stdout: the default server-id; if empty, stop and ask which server to use
```
- The stop-on-error rule — on any `jf` failure, stop and never switch servers.

One addition specific to this skill: never `cat` or parse
Expand All @@ -57,16 +69,21 @@ Pick the row matching the user's intent and read that reference file.
as your `jf` calls. Agent Guard also reads `JFROG_URL` / `JF_URL` directly when
set, so make sure the `<SID>` you resolved points at that same host.
- **Resolve the project (`<PROJECT>`) only when needed.**
It is required for `--list-skills`, `--list-skill-versions`, and
`--provision-skills-repository`. Take it from `JF_PROJECT` or the user.
It is required for `--list-skills`, `--list-skill-versions`,
`--provision-skills-repository`, `--list-agent-plugins`,
`--list-agent-plugin-versions`, and `--provision-agent-plugins-repository`.
Take it from `JF_PROJECT` or the user.
There is no non-admin way to look up or validate project keys (the
`/access/api/v1/projects` list endpoint needs admin), so you cannot
silently correct a display name to a key. If the value looks like a
display name (spaces, mixed case) rather than a short slug, ask the
user to confirm the project **key** specifically. Never assume
`default`, never invent one. Install, update, remove, and publishing to
an explicit `--repo` are keyed by skill **name** and/or **repo**, not a
project.
an explicit `--repo` are keyed by skill/plugin **name** and/or **repo**,
not a project.
- **Bundle manifests differ by type.** Skill bundles require `SKILL.md`
in the bundle root; plugin bundles require `plugin.json`. Validate the
correct file before installing or publishing.

## Workflow overview

Expand All @@ -76,10 +93,14 @@ flowchart TD
B -->|No| C[Ask user to install jf CLI, then continue]
B -->|Yes| D{Intent}
C --> D
D -->|List all / versions| E[npx @jfrog/agent-guard --list-skills]
D -->|Install / update| F[Resolve slug + version, then jf skills install/update]
D -->|List installed / remove| G[jf skills list / rm -rf install dir]
D -->|Publish| H[Resolve/provision repo, validate bundle, jf skills publish]
D -->|List all skills / versions| E[npx @jfrog/agent-guard --list-skills]
D -->|Install / update skill| F[Resolve slug + version, then jf skills install/update]
D -->|List installed skills / remove| G[jf skills list / rm -rf install dir]
D -->|Publish skill| H[Resolve/provision repo, validate bundle, jf skills publish]
D -->|List all plugins / versions| I[npx @jfrog/agent-guard --list-agent-plugins]
D -->|Install / update plugin| J[Resolve slug + version, then jf agent plugins install/update]
D -->|List installed plugins / remove| K[jf agent plugins list / rm -rf install dir]
D -->|Publish plugin| L[Resolve/provision repo, validate bundle, jf agent plugins publish]
```

## Gotchas
Expand All @@ -100,3 +121,6 @@ the reference files above.
- **Use the response templates verbatim**: where a reference file gives a "reply
using this exact template" block, fill the placeholders and send exactly that,
with the same wording every time and no extra preamble or commentary.
- **Plugins have no Xray support**: skip all Xray-related handling (no 403
gating on download, no inline scan on publish, no `--skip-scan` flag) when
performing any `jf agent plugins` operation.
83 changes: 83 additions & 0 deletions skills/jfrog-ai-catalog/references/discovering-plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Discovering plugins

List-all and versions go through the **Agent Guard**.

## List plugins (page through the catalog)

```bash
npx --yes --registry <REGISTRY_URL> @jfrog/agent-guard \
--list-agent-plugins --project "<PROJECT>" [--name <PATTERN>] [--server "<SID>"] [--page-size <N>] [--cursor <C>] [--format json]
```

| Flag | Required | Purpose |
|------|----------|---------|
| `--project <PROJECT>` | **Yes** | AI Catalog project to list. |
| `--name <PATTERN>` | No | Find plugins by name: server-side, case-insensitive substring, scoped to the project. |
| `--server <SID>` | No | jf CLI config entry to authenticate with (defaults to the resolved single server). |
| `--page-size <N>` | No | Results per page. Pass `50` to stay bounded. The Agent Guard defaults to 500 if omitted. |
| `--cursor <C>` | No | Continuation cursor from a previous page's JSON, to fetch the next page. |
| `--format json` | No | Raw page JSON instead of the default compact TSV (name + last-updated). |

Request a bounded page with `--page-size 50 --format json`, present those plugins,
then read `exhausted` and `cursor` from the response. If `exhausted` is `false`
there are more. Tell the user and offer to fetch the next page with
`--cursor <cursor>`. Do not silently page through the whole catalog.

**Presenting results (use this exact format).** Render the plugins as this table,
sorted by name, and nothing else (no commands, URLs, flags, or cursors):

| Plugin | Last updated |
|--------|-------------|
| `<name>` | `<lastUpdated>` |

For a `--name` search with no matches, reply with one line instead:

> No plugins match "`<query>`".

To offer a follow-up (a plugin's versions or repos), ask in plain language
("want the versions for one of these?") and run the command yourself.

## List a repo's plugins

To see what is published in one specific plugins repository (for example, to check
a repo before or after publishing to it), list it directly with the CLI. This is
repo-scoped (Artifactory registry contents), unlike `--list-agent-plugins`, which is
project-scoped:

```bash
jf agent plugins list --repo "<repo>" --server-id "<SID>" --format json
```

Never run a bare `jf agent plugins list` (it errors): always pass `--repo <key>` here, or
`--harness <h>` for installed plugins (see `managing-installed-plugins.md`).

**Presenting results (use this exact format).** Render the plugins as this table,
sorted by name, and nothing else (no commands, URLs, or flags):

Plugins in `<repo>`:

| Plugin | Version | Description |
|--------|---------|-------------|
| `<name>` | `<version>` | `<description>` |

Include the **Description** column only when the listing provides one (drop it if
every plugin's description is empty). If the repo holds no plugins, reply with one
line instead:

> No plugins published in `<repo>`.

## A plugin's versions and hosting repos

```bash
npx --yes --registry <REGISTRY_URL> @jfrog/agent-guard \
--list-agent-plugin-versions --project "<PROJECT>" --agent-plugin "<slug>" [--server "<SID>"] [--page-size <N>] [--cursor <C>] [--format json]
# JSON: versions[].version, versions[].locations[].repoKey (page through with cursor like above)
```

**Presenting versions (use this exact format).** Newest version first:

Versions of `<slug>`:

| Version | Hosted in |
|---------|-----------|
| `<version>` | `<repoKey>`[, `<repoKey>`…] |
138 changes: 138 additions & 0 deletions skills/jfrog-ai-catalog/references/installing-plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# Installing and updating plugins

Install and update both download from the registry, so they share the same
`--repo`/`--quiet` rules and verify-landed check.

## Contents

- When evidence verification fails
- Verify the install landed
- Update an installed plugin

Install by **slug** (the registry `slug`/`name`, never a display name). Latest
version is used by default, and the user may pass an explicit version.
**The `jf agent plugins install` command takes no project.** Resolving which repo hosts
the slug uses `--list-agent-plugin-versions` (below), which does require `--project`, so
resolve it (from `JF_PROJECT`, else ask the user) before that lookup.

```bash
jf agent plugins install "<slug>" \
--server-id "<SID>" \
--version "latest" \
--repo "<repo>" \
--harness "<harness>" \
--quiet
```

**Always pass `--quiet`.** `jf agent plugins install`/`update` opens an interactive
prompt by default, and an agent's shell has no TTY, so without `--quiet` the
prompt fails. `--quiet` also defaults to `$CI`, so exporting `CI=true` has the
same effect if the flag is ever unavailable. Run non-interactively and resolve
every choice (`--repo`, target) up front.

**Resolve `<harness>` from the environment check script — never from your model
name.** If `<UA>` is not already known from this session, run
`bash <skill_path>/scripts/check-environment.sh <model-slug>` now and capture
its stdout as `<UA>`. Parse the `tool=<h>` field from `<UA>` and map it to a
`jf` harness name:

| `tool=` value in `<UA>` | `--harness` for `jf agent plugins` |
|-------------------------|------------------------------------|
| `claude` | `claude-code` |
| `cursor` | `cursor` |
| `unknown`, empty, or any other | Ask the user |

If `tool` is `unknown`, empty, or not in the table — do **not** guess. Ask
the user for the desired install path and use `--path <dir>` instead. VS Code
and similar hosts that lack a recognised `tool=` value are not in the supported
agents table for plugins; passing a guessed harness will cause the CLI to error
with `unknown agent`.

Choose exactly one install target (these are mutually exclusive):

| Flag | Installs into |
|------|---------------|
| `--harness <name>` | The current agent's resolved plugins dir (resolve per above, e.g. `cursor`, `claude-code`). |
| `--global` | Each agent's global directory from config. |
| `--project-dir <dir>` | Project root combined with the agent's project path. |
| `--path <dir>` | Direct: files go under `<dir>/<slug>`. |

**Always resolve and pass `--repo`.** When the platform has more than one plugins
repository (the common case), `jf agent plugins install` errors with
`multiple plugins repositories found … specify --repo` if you omit it, even when
the plugin lives in only one repo. So **the first install step is always** to look
up where the slug is hosted with the Agent Guard:

```bash
npx --yes --registry <REGISTRY_URL> @jfrog/agent-guard \
--list-agent-plugin-versions --project "<PROJECT>" --agent-plugin "<slug>" [--server "<SID>"] --format json
# read versions[].version and versions[].locations[].repoKey
```

**Resolve the repo and version only via `--list-agent-plugin-versions`.** The catalog
listing (`--list-agent-plugins`, even with `--name`) returns just names, not repos or
versions, so use the versions call above to pick the repo, never a name listing.

- **One repo hosts the slug.** Use it as `--repo <repoKey>` directly. Don't ask.
- **Multiple repos host the slug.** Do not pick silently. List the repos (and
the version each holds), ask the user which to install from, then pass
`--repo <chosen>`. The newest version may only exist in one of them, so
surface that to avoid giving the user a stale version.

## When evidence verification fails

If install fails with `evidence verification failed … no evidence found`, the
plugin has **no signed evidence/attestation** (proof it's genuine and scanned).
This is a security control. **Do not silently bypass it.** Stop and ask using
**this exact template**:

> `<slug>@<version>` has no signed evidence (proof it is genuine and scanned).
> Installing it skips that security check. Do you want to install it anyway?

Only if the user explicitly agrees, re-run with
`JFROG_SKILLS_DISABLE_QUIET_FAILURE=true`. Never set that flag on your own.

## Verify the install landed

After install, confirm the `plugin.json` exists at the resolved install location
before reporting success:

```bash
test -f "<install-dir>/<repo-key>/<slug>/plugin.json" && echo "installed" || echo "MISSING plugin.json"
```

If the file is missing, report the failure. Do not claim success.

On success, reply using **this exact template**:

> Installed `<slug>@<version>` from `<repo>` into `<harness>`.
> Restart your agent session to load it.

## Update an installed plugin

To upgrade an installed plugin to a newer version, use the CLI (it re-downloads
and reinstalls in place):

```bash
jf agent plugins update --slug "<slug>" --server-id "<SID>" --harness "<harness>" --version "latest" --quiet
# Preview without touching Artifactory:
jf agent plugins update --slug "<slug>" --server-id "<SID>" --harness "<harness>" --dry-run
# Reinstall even if already at the target version:
jf agent plugins update --slug "<slug>" --server-id "<SID>" --harness "<harness>" --force --quiet
# Update all installed plugins at once:
jf agent plugins update --all --server-id "<SID>" --harness "<harness>" --quiet
```

Note: unlike `jf skills update`, the slug is passed as `--slug <slug>` (a named
flag), not as a positional argument. Use the same install-target flag
(`--harness`/`--global`/`--project-dir`/`--path`) the plugin was installed with.
After updating, re-verify the `plugin.json` (see *Verify the install landed* above).

On success, reply using **this exact template**:

> Updated `<slug>` to `<version>` (`<harness>`).
> Restart your agent session to load it.

If the plugin was already current:

> `<slug>` is already at the latest version (`<version>`). Nothing to update.
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,21 @@ defaults to `$CI`, so exporting `CI=true` has the same effect if the flag is eve
unavailable. Run non-interactively and resolve every choice (`--repo`, target)
up front.

**Resolve `<harness>` from the host you are running in. Never take it from your
model name, and never hardcode it.** Get the valid names from the CLI: run
`jf skills list --harness '?'` to print the
`Supported agents:` table, then install into the row for your host. Identify the
host from its environment. For example, `CURSOR_*` → `cursor`,
`CLAUDECODE` → `claude-code`, VS Code / GitHub Copilot → `github-copilot`. If
nothing identifies the host, ask the user. Never assume.
**Resolve `<harness>` from the environment check script — never from your model
name.** If `<UA>` is not already known from this session, run
`bash <skill_path>/scripts/check-environment.sh <model-slug>` now and capture
its stdout as `<UA>`. Parse the `tool=<h>` field from `<UA>` and map it to a
`jf` harness name:

| `tool=` value in `<UA>` | `--harness` for `jf skills` |
|-------------------------|------------------------------|
| `claude` | `claude-code` |
| `cursor` | `cursor` |
| `copilot` | `github-copilot` |
| `unknown`, empty, or any other | Ask the user |

If `tool` is `unknown`, empty, or not in the table — do **not** guess. Ask
the user for the desired install path and use `--path <dir>` instead.

Choose exactly one install target (these are mutually exclusive):

Expand Down
Loading
Loading