JFrog Skill
The foundational skill for all JFrog agent interactions. Covers JFrog Platform concepts,
CLI setup and authentication, and intent routing to workflow skills.
Interact with the JFrog Platform through the JFrog CLI (
) and, where the
CLI falls short, through REST APIs and GraphQL. In code examples below,
refers to this skill's directory and is resolved automatically
by the agent. If the agent does not resolve it, determine the path by locating
this SKILL.md file and using its parent directory.
Prerequisites
The following tools must be available on
:
| Tool | Purpose |
|---|
| JSON parsing of CLI and API output |
All HTTP traffic to JFrog Platform APIs goes through the
CLI itself
(
, see
Invoking platform APIs with below) —
no standalone
is required for any JFrog interaction.
Runtime permission for JFrog calls. All
calls that touch the network
need an outbound-HTTPS escalation from the agent runtime. The
credential save (
during login) additionally needs a
filesystem-write escalation.
| Runtime | Network | Network + write |
|---|
| Cursor | required_permissions: ["full_network"]
| required_permissions: ["all"]
|
| Claude Code | allowed-tools: Bash(jf:*)
+ host allowlist | same + filesystem allowlist |
| Other | Configure at the runtime/sandbox layer | same |
If
exits 1 with empty output, the runtime's network gate is the first
thing to check — re-run with the appropriate escalation above.
Environment check
Before your first JFrog operation in a session, run the environment check
and
remember its stdout as
for the rest of the session:
bash
bash <skill_path>/scripts/check-environment.sh <model-slug>
# stdout (one line): model/<model-slug> jfrog-skills/<version> jfrog-cli-go/<cli-version>
# stderr: JSON state (cached 24h at ${JFROG_CLI_HOME_DIR:-$HOME/.jfrog}/skills-cache/jfrog-skill-state.json)
Pass the precise underlying-model slug with version:
,
,
,
,
. Cursor's
Composer product slug
is the canonical id — use it as-is. Do
not
pass harness/role names (
,
,
) or bare family
names (
,
); subagents inherit the parent's slug. If genuinely
unknown, pass
.
Export once per bash invocation
At the top of every bash invocation that runs
, export
once;
all
calls in that invocation pick it up:
bash
export JFROG_CLI_USER_AGENT='<UA>'
jf config show
jf api /artifactory/api/system/version
Do
not repeat the assignment per
call (
JFROG_CLI_USER_AGENT='<UA>' jf …
on every line). Examples elsewhere in this skill and in
omit the export for readability — the rule is global. When launching a
subagent, pass
in its prompt; subagents do not re-run the script.
| Exit | Meaning |
|---|
| 0 | Cache fresh — proceed |
| 1 | Cache refreshed — proceed |
| 2 | not installed — STOP, ask the user to install |
| 3 | below minimum version — STOP, ask the user to upgrade |
On exit 2 or 3, do not fall back to
, raw
, or other
workarounds — see
references/jfrog-cli-install-upgrade.md
. Re-run with
only when the user explicitly asks to refresh or install/upgrade.
JSON parsing ()
Use
for all JSON parsing of CLI and API output (pipes,
, filters).
— allowed files only
${JFROG_CLI_HOME_DIR:-$HOME/.jfrog}/skills-cache/
is
not a general scratch
or temp directory. Use it
only for these two artifacts:
- — written by
scripts/check-environment.sh
(24-hour CLI check cache).
onemodel-schema-${JFROG_SERVER_ID}.graphql
— cached OneModel supergraph
schema (see references/onemodel-graphql.md
).
Do not save HTTP response bodies, GraphQL query results, ad-hoc JSON, reports,
or any other temporary files under
. Write those to a host temp
path instead (for example
or
), echo the path
when a follow-up Shell step must read the file — same pattern as
Preserving
command output below.
Cautious execution
Do not run commands speculatively. Before executing any JFrog CLI command or
API call:
- Confirm the operation is needed to fulfill the user's request.
If the request is ambiguous or could refer to multiple systems (e.g.
"builds" could mean Artifactory build-info or CI/CD pipeline runs),
ask the user for clarification instead of guessing. Never fetch data
from the wrong system — a wrong answer is worse than asking a question.
- Resolve the target server using the Server selection rules below —
there must be no ambiguity about which server is used
- For mutating operations (create, update, delete, upload), confirm with the
user unless the intent is clearly implied
- Prefer read operations first to understand current state before making changes
- Never invent preparatory mutations. If the requested operation fails
because a precondition is not met (artifact missing from the specified repo,
repository does not exist, package not at the expected location, build not
found), stop and report the gap to the user. Do not perform copy, move,
upload, create-repo, or any other mutating operation to satisfy the
precondition unless the user explicitly asks for it. These "helper" mutations
can have cascading effects the user has not considered — virtual repository
resolution changes, storage quota consumption, replication triggers, Xray
re-indexing, or permission propagation.
Server selection rules (mandatory)
Single-server invariant. Every
call MUST pass
(default resolved below); for one user request, all
calls use
exactly
one server-id. A wrong answer from the wrong server is worse than a stop-and-ask.
MUST NOT retry on a second configured server after 401/403/404, empty, or
partial results;
MUST NOT infer multi-server intent from "my"/"our" or
from seeing extra entries in
.
Override: only when the user
explicitly names another id ("on
, …", "use
", "compare
and
") — inferred intent is not an override.
Resolve the default once per session
Before your first
call, resolve the default server-id and
remember it
as
for the rest of the session — same pattern as
:
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 to use
Pass
to every subsequent
call. The flag goes
after the subcommand name, not after
itself:
- ✅
jf api --server-id <SID> /artifactory/api/system/version
- ✅
jf rt ping --server-id <SID>
- ❌
jf --server-id <SID> api /…
— fails with flag provided but not defined
When launching a subagent, pass
in its prompt — subagents do not
re-resolve. Examples elsewhere in this skill and in
omit
for readability; the rule is global, same as
.
On any error, stop — never switch
If a
call returns 401/403, 404, network error, timeout, or any other
failure,
stop with no further calls and respond:
returned
for
:
. Other
configured server(s):
— I won't query them without your explicit
instruction. How would you like to proceed?
When to read reference files
Load the most specific file for the task at hand. Avoid loading more than 2-3
reference files for a single operation — start with the most relevant one and
only load additional files if the first doesn't cover the need. File sizes
vary (~25–640 lines); larger files are noted with approximate line counts
below.
Cross-domain
- Disambiguating a JFrog entity, understanding entity types, or planning operations that span multiple products: read
references/jfrog-entity-index.md
, then follow pointers to the relevant domain file
- Looking up documentation URLs: read
references/jfrog-url-references.md
Artifactory
- Repository types, artifacts, builds, properties, or permission targets (concepts): read
references/artifactory-entities.md
(~220 lines)
- Stored packages, package versions, version locations, or the metadata layer over Artifactory (concepts): read
references/stored-packages-entities.md
(~165 lines)
- Repo, file, build, permission, user/group, or replication operations: read
references/artifactory-operations.md
(for listing builds use AQL with / — see § Listing build names; for full build detail use GET /api/build/<name>/<number>?project=
— see § Retrieving full build info)
- AQL queries: read
references/artifactory-aql-syntax.md
(~585 lines)
- Artifactory REST beyond the CLI, structured JSON templates (replacing interactive wizards), or any Artifactory API gap: read
references/artifactory-api-gaps.md
(~220 lines)
Xray & security
- Watches, policies, violations, components, or vulnerability scanning (concepts): read
references/xray-entities.md
(~290 lines)
- Exposures scanning results (secrets, IaC, service misconfigurations, application security risks): read
references/xray-entities.md
§ Exposures (Advanced Security)
- Curation audit events (approved/blocked packages, dry-run policy evaluations, curation export): read
references/xray-entities.md
§ Curation audit events
Release lifecycle & distribution
- Release bundles, lifecycle stages, distribution, or evidence (concepts): read
references/release-lifecycle-entities.md
(~180 lines)
- Applications, application versions, releasables, promotions, or AppTrust (concepts): read
references/apptrust-entities.md
(~155 lines)
Catalog
- Public or custom catalog, package metadata, vulnerability advisories, licenses, OpenSSF, or MCP services (concepts): read
references/catalog-entities.md
(~190 lines)
- CVE details, vulnerability lookup by CVE ID, or severity/affected-packages/fix-versions for a specific CVE: go directly to
references/onemodel-query-examples.md
§ Public security domain for the query shape — this is self-contained; do not load the jfrog-package-safety-and-download
skill for pure CVE lookups
OneModel (GraphQL)
- GraphQL queries (applications, packages, evidence, release bundles, catalog, cross-domain, or "list/search my" platform entities): read
references/onemodel-graphql.md
(~325 lines)
- Query templates and domain-specific examples: read
references/onemodel-query-examples.md
(~555 lines)
- Pagination, filtering, GraphQL variables, or date formatting: read
references/onemodel-common-patterns.md
(~280 lines)
Platform administration
- Platform structure, project/repo membership, or project roles vs environments (concepts): read
references/platform-access-entities.md
- Access tokens, stats, projects, or system health: read
references/platform-admin-operations.md
- Managing JFrog Projects, members, or environments: read
references/projects-api.md
(~260 lines)
- Platform REST beyond the CLI, or any platform-level API gap: read
references/platform-admin-api-gaps.md
(~180 lines)
CLI setup & authentication
- Adding a server or logging in: read
references/jfrog-login-flow.md
(~130 lines)
- CLI not installed, upgrade needed, or unavailable: read
references/jfrog-cli-install-upgrade.md
General patterns
- Batching, parallel Shell calls, or launching subagents: read
references/general-parallel-execution.md
(~135 lines)
- Large or parallel data gathering, list-vs-detail APIs, cache hygiene: read
references/general-bulk-operations-and-agent-patterns.md
- Standalone HTML report with JFrog-aligned styling: read
references/jfrog-brand-html-report.md
- Reusable gotchas from past tasks: read or extend
references/general-use-case-hints.md
Server management
Server configuration is always read live from
(never cached).
- List servers: (local operation, no network needed)
- Use a specific server: pass to any command
- Switch default:
jf config use <server-id>
- Add a new server: read
references/jfrog-login-flow.md
for the full
login procedure (web login or manual token setup)
Command discovery
Use the commands listed below as your primary reference. Run
to
verify options you are unsure about or to discover commands not listed here —
do not rely on memorized commands outside this skill, as they may be outdated.
- — list all namespaces and top-level commands
- — list subcommands in a namespace
- — show usage, arguments, and options
CLI namespaces
| Namespace | Alias | Product |
|---|
| | Artifactory |
| | Xray |
| | Distribution V1 |
| | AppTrust |
| | Evidence |
| | Mission Control |
| | Workers |
| | CLI server configuration |
| | CLI plugin management |
| | IDE integration |
Sunset notice: JFrog Pipelines has been sunset and is no longer supported.
Do not use the
CLI namespace or the Pipelines REST API
(
). If a user asks about Pipelines, inform them the
product has been sunset.
Top-level lifecycle commands (no namespace):
,
,
,
,
,
,
,
,
,
,
.
Top-level security commands:
,
,
,
,
.
Top-level other:
(
),
,
,
,
generate-summary-markdown
,
,
.
Invoking platform APIs with
When the CLI lacks a dedicated subcommand, use
— the unified entry
point for every JFrog Platform REST and GraphQL endpoint, auto-authenticated
against the resolved server.
Do not use or —
they are superseded by
.
Product-prefix table
requires the
full path including the product prefix; omitting it
returns 404.
| Product | Path prefix |
|---|
| Artifactory | |
| Xray | |
| Access (users, groups, tokens, permissions, projects) | |
| Evidence | |
| Release Lifecycle | |
| AppTrust | |
| Distribution | |
| OneModel (GraphQL) | , /onemodel/api/v1/supergraph/schema
|
| Mission Control | |
| Curation | /xray/api/v1/curation/...
(lives under Xray) |
Examples
bash
jf api /artifactory/api/repositories
jf api /artifactory/api/system/version --server-id <id>
# AQL (POST with text/plain body)
jf api /artifactory/api/search/aql \
-X POST -H "Content-Type: text/plain" -d '<aql-query>'
Common flags:
,
,
,
,
,
. Body on stdout, status on stderr — see
Gotchas.
GraphQL (OneModel)
OneModel is the unified GraphQL API.
Do not embed the query inside a JSON
literal (
) — escaping breaks requests. Build the payload
with
, pass it via
, and save the response to a file
before running
on it.
bash
QUERY='{ evidence { searchEvidence(first: 5, where: { hasSubjectWith: { repositoryKey: "my-repo-local" } }) { totalCount } } }'
PAYLOAD=/tmp/onemodel-payload-$$.json RESPONSE=/tmp/onemodel-$$.json
jq -n --arg q "$QUERY" '{query:$q}' > "$PAYLOAD"
jf api /onemodel/api/v1/graphql -X POST \
-H "Content-Type: application/json" --input "$PAYLOAD" > "$RESPONSE"
jq . "$RESPONSE"
Schema discovery:
jf api /onemodel/api/v1/supergraph/schema > "$SCHEMA_FILE"
(store only under
, never query responses). Read
references/onemodel-graphql.md
for the full workflow (schema fetch,
validation, pagination, errors), plus
references/onemodel-query-examples.md
and
references/onemodel-common-patterns.md
for query shapes, pagination,
variables, and dates.
Structured inputs
Several CLI commands require JSON template files. The templates are normally
created by interactive wizard commands (
,
,
)
which agents cannot use. Instead, retrieve an existing config via REST API as a
starting point and modify it:
bash
jf api /artifactory/api/repositories/<repo-key>
For other Artifactory or platform REST patterns, or when you need more than
this repo GET, see
Any API gap under
When to read reference files.
Gotchas
- requires the product prefix in the path (, , , ,
, , , ,
). Omitting the prefix returns 404. See the
product-prefix table above.
- writes the body (success or error JSON) to stdout and
to stderr on every call; non-2xx also exits
1 and adds
[Warn] jf api: <method> <url> returned NNN
. Pipe stdout to
directly; never — stderr corrupts the JSON. To keep
diagnostics: jf api <path> 2>/tmp/err-$$.log | jq .
.
- has no (follow redirects) and no (output file).
Save bodies with shell redirection
(
jf api ... > /tmp/out-$$.json
); for
binary downloads through the Artifactory remote proxy prefer ,
which handles the cache and redirect semantics natively.
- Remote repository content is stored in a suffixed repo. Properties
and AQL queries for remote repo artifacts must target the cache repo.
Conversely, only accepts the parent remote key
(without ) — strip the suffix for configuration lookups.
- Do not use — always use a direct AQL query via
jf api /artifactory/api/search/aql -X POST -H "Content-Type: text/plain" -d '<aql>'
.
See references/artifactory-aql-syntax.md
.
- Use flag for non-interactive execution (suppresses confirmation
prompts). Caution: is not a global flag — commands that do not
support it (e.g. , ) will fail with misleading errors
like "Wrong number of arguments" or "flag provided but not defined". Check
for a command before adding .
- Use when targeting a non-default server. If a command fails
with , do not retry without it — that silently targets the
default server instead. See Server selection rules.
- Never use interactive commands. All JFrog CLI operations must be performed
non-interactively. Known interactive commands to avoid: ,
, ,
jf rt permission-target-template
, and
jf rt replication-template
. For server setup, follow references/jfrog-login-flow.md
.
For templates, use JSON schemas or REST API. If a command prompts for input
unexpectedly, find the non-interactive alternative via or REST API.
- output is base64-encoded JSON. Decode with
to extract fields.
- Build info lookups require a scope ( or ) —
resolve it before calling the API. See
references/artifactory-operations.md
§Retrieving build info for the full workflow.
- If a call returns 401, the configured token may have expired or
been rotated — ask the user to re-run the login flow (see
references/jfrog-login-flow.md
) for the same server. If 403, the
token lacks required permissions. If 404, verify the endpoint path
(especially the product prefix) and target server version. On any of
these errors, do not try a different configured server as a workaround —
that targets a different environment. Report the error and ask the user.
- Xray contextual analysis: the summary artifact response has two
applicability fields — (top-level, often null) and
(always present with a string). Use
applicability_details[].result
for counts and summaries. Using the
top-level field for aggregation produces wrong counts because
it is null when no scanner exists. See references/xray-entities.md
§Contextual analysis for the eight possible result values and jq snippets.
- OneModel GraphQL: always fetch the supergraph schema from the same
server you query before building operations (schemas differ by deployment);
cache, validate, and execute per
references/onemodel-graphql.md
.
- Never duplicate a network-fetching command to retry parsing — save the
response to a temp file first (see Preserving command output).
- When collecting detail responses in a loop (e.g. per-repo GETs), validate
each body with before appending to a results file. One non-JSON
or empty response corrupts a downstream slurp. Write validated
lines to an NDJSON file, then to produce the final
array. See
references/general-bulk-operations-and-agent-patterns.md
.
- Accumulated edge cases from real tasks live in
references/general-use-case-hints.md
— read when debugging odd failures; append a short entry when you confirm
a new, reusable gotcha.
Batch and parallel execution
When a task requires multiple independent operations, use the lightest
parallelism mechanism that fits. Three tiers: (1) batch commands in a single
Shell call using loops or
, (2) issue parallel Shell tool calls, (3) launch
parallel subagents for large fan-out. Read
references/general-parallel-execution.md
(~135 lines) for tier selection, examples, and subagent prompt structuring.
Preserving command output
When a CLI command or API call returns data, redirect the output to a temporary
file so you can re-read it without re-executing the call:
bash
OUT=/tmp/jf-repos-$$.json
jf api /artifactory/api/repositories > "$OUT"
echo "$OUT"
Use
(the shell PID) in the filename to prevent collisions across
concurrent sessions or processes.
Cross-call gotcha: each Shell tool invocation runs in a new process with a
different PID, so
expands to a different value in each call. Always
echo the expanded filename so the agent can read it from the output and
reuse the literal path in subsequent calls. Three patterns, in priority order:
- + echo (preferred): use for collision safety, echo the path
as shown above. The agent reads from the output
and passes that literal value to the next Shell call.
- Session ID: when many files share a prefix across calls, generate an ID
once (), echo it, and reuse in later calls.
- Hardcoded names: last resort — risks collisions when parallel calls or
subagents write to the same path.
This protects against wasted round-trips when you need to retry parsing — for
example, if a
filter fails or you extract the wrong field on the first
attempt. Re-read the file instead of hitting the server again.
Do
not duplicate the same
network request in a shell pipeline (e.g. with
) only to re-run
or to reveal jq diagnostics—the duplicate call
adds load on JFrog without fetching new data. Run
jq '<filter>' /tmp/jf-*-$$.json
(or redirect stdin from the file) instead
of re-running the same
or other identical network-backed command.
Do not reuse saved output across unrelated steps or changed contexts (different
server, user, or intent). The file is only valid for the immediate sequence of
operations that motivated the original call.