Command-line tool for inspecting, validating, and packaging AI Catalog documents.
| Resource | Link |
|---|---|
| Specification | https://agent-card.github.io/ai-catalog/ |
| Upstream repository | https://github.com/Agent-Card/ai-catalog |
| Rust libraries | https://github.com/Agent-Card/ai-catalog-rust |
The crate is named ai-catalog-cli; the installed binary is ai-catalog.
On macOS and Linux, install from the tap in this repository:
brew tap Agent-Card/ai-catalog-cli https://github.com/Agent-Card/ai-catalog-cli
brew trust Agent-Card/ai-catalog-cli
brew install ai-catalogOn Windows, install with WinGet:
winget install --id AgentCard.AICatalog --exactOpen a new terminal afterwards so the ai-catalog command is on your PATH.
Upgrade later with winget upgrade --id AgentCard.AICatalog --exact.
Prebuilt binaries for Linux, macOS, and Windows are attached to each
release. Download the
archive for your platform, verify it against the accompanying .sha256 file,
and place ai-catalog on your PATH:
VERSION=v0.1.0
NAME=ai-catalog-darwin-arm64 # see the release page for other platforms
BASE=https://github.com/Agent-Card/ai-catalog-cli/releases/download/$VERSION
curl -fsSLO "$BASE/$NAME.tar.gz" -O "$BASE/$NAME.sha256"
shasum -a 256 -c "$NAME.sha256"
tar -xzf "$NAME.tar.gz"
install -m 0755 ai-catalog /usr/local/bin/Linux archives come in gnu (glibc 2.28 or newer) and musl (statically
linked) flavours; pick musl for Alpine or other non-glibc distributions.
With a Rust toolchain installed:
cargo install ai-catalog-cliFrom a checkout of this repository:
cargo install --path .Or run without installing, replacing ai-catalog with cargo run -- in any
example below:
cargo run -- --helpSKILL.md follows the Agent Skills standard
and teaches an AI agent to use this CLI to discover, inspect, and install AI
artifacts from a catalog. It requires the ai-catalog binary on PATH.
Each skill is loaded from a directory named after it, so install it as:
mkdir -p ~/.agents/skills/ai-catalog-cli
cp SKILL.md ~/.agents/skills/ai-catalog-cli/~/.agents/skills/ is read by Cursor, Copilot, VS Code, Codex, and Gemini CLI.
For Claude Code, use ~/.claude/skills/ instead.
just build # cargo build
just lint # fmt --check + clippy -D warnings
just test # cargo test
just coverage # llvm-cov summaryThis CLI builds on the four AI Catalog library crates, released separately from
Agent-Card/ai-catalog-rust:
ai-catalog,
ai-catalog-validate,
ai-catalog-trust, and
ai-catalog-oci.
ai-catalog validate [--json] <path|->
ai-catalog format <path|->
ai-catalog oci pack <path|->
ai-catalog oci unpack <path|->
ai-catalog oci export-layout [--tag <tag>] [--cosign-key <path>] [--cosign-public-key <path>] <path|-> <layout-dir>
ai-catalog oci unpack-layout [--ref-name <name>] <layout-dir>
ai-catalog oci push [--tag <tag>] [--plain-http] [--insecure] [--to-oci-layout-path <layout-dir>] [--cosign-key <path>] [--cosign-public-key <path>] <path|-> <target>
ai-catalog oci add <name> <layout-dir> [--ref-name <tag>]
ai-catalog oci search [--regex] [-n <limit>] [--json] <keyword>
ai-catalog oci show [--json] [--media-type <type>] <identifier>
ai-catalog oci pull [--output <path>] [--media-type <type>] <identifier>
ai-catalog catalog add <name> <url>
ai-catalog catalog list [--json]
ai-catalog catalog remove <name-or-url>
ai-catalog catalog update <name>
ai-catalog search [--regex] [-n <limit>] [--json] <keyword>
ai-catalog show [--scope <catalog-name-or-url>] [--json] [--media-type <type>] <identifier>
ai-catalog pull [--output <path>] [--scope <catalog-name-or-url>] [--media-type <type>] <identifier>
ai-catalog --version
Use - as <path> to read from stdin. Every command accepts --help.
Validates a catalog document against the AI Catalog specification and reports the conformance level (Minimal / Discoverable / Trusted).
ai-catalog validate catalog.json # text report
ai-catalog validate --json catalog.json # JSON report
cat catalog.json | ai-catalog validate - # from stdinExits with code 0 on success, 1 on validation errors.
With --json, each error and warning has a stable code (for example
entry-duplicate) next to its path and message. Match on the code rather
than the message. code is null when the input could not be parsed.
Pretty-prints a catalog document to stdout without modifying the source file.
ai-catalog format catalog.json
cat catalog.json | ai-catalog format -Fetches a catalog from a URL, a domain or a local file, stores all catalog blobs in the local content-addressed cache, and registers the catalog in the local registry. Nested catalogs are fetched recursively (up to depth 4).
ai-catalog catalog add my-registry https://example.com/ai-catalog.json
ai-catalog catalog add example https://example.com # or just: example.com
ai-catalog catalog add local-demo file:///path/to/catalog.jsonMakes network requests. All other consumer commands operate on the local cache.
A domain or an https:// URL does not have to be the catalog itself. If it
isn't one, the CLI follows the specification's
discovery procedure: a Link header
with rel="ai-catalog", then an HTML <link rel="ai-catalog"> element, then
/.well-known/ai-catalog.json. The catalog that is found is the one that gets
registered, under its own URL, which is what catalog update fetches again. If
nothing is found, the error lists every URL that was tried. Files and http://
URLs are used as they are, without discovery.
References inside a catalog must be https (or relative to the catalog). A local
file:// path is followed only from a local catalog, so a remote catalog can't
read your disk. Cycles, http:// references and nesting beyond depth 4 are
skipped with a warning, and catalogs are limited to 10 MiB.
Lists all catalogs registered in the local registry.
ai-catalog catalog list
ai-catalog catalog list --jsonRe-fetches a registered catalog from its source URL and refreshes the local cache. Accepts a catalog name.
ai-catalog catalog update my-registryRemoves a catalog from the local registry by name or source URL. Also removes the cached object blob if no other registered catalog references it.
ai-catalog catalog remove my-registry
ai-catalog catalog remove https://example.com/ai-catalog.jsonSearches entries across all registered catalogs (all sources).
ai-catalog search "finance agent" # substring match
ai-catalog search --regex "urn:example:(agent|data).*"
ai-catalog search --json dataset # JSON output
ai-catalog search -n 5 embeddings # limit to 5 resultsMatches against identifier, displayName, description, and tags.
Default limit is 50.
Shows full details of a single catalog entry by identifier.
ai-catalog show urn:example:agent:v1
ai-catalog show --json urn:example:agent:v1
ai-catalog show --scope my-registry urn:example:agent:v1 # restrict to one catalog
ai-catalog show --scope https://example.com/ai-catalog.json urn:example:agent:v1
ai-catalog show --media-type application/json urn:example:catalog:nested--scope accepts a registered catalog name or source, or a catalog URL, which
is fetched and cached on the fly without registering it.
For an entry that is itself a nested catalog, --media-type resolves its
children and shows the single child of that type. Omitting it, or passing
application/ai-catalog+json, shows the catalog entry itself.
Downloads an entry's content to disk. For nested-catalog entries the full
catalog JSON is written; for other types the raw bytes from entry.url are
fetched. An http(s) URL given as the identifier is fetched as a catalog if it
is not registered.
ai-catalog pull urn:example:data:dataset-v1
ai-catalog pull --output ./downloads urn:example:data:dataset-v1
ai-catalog pull --output ./report.json urn:example:data:dataset-v1
ai-catalog pull --output - urn:example:data:dataset-v1 # stream to stdout
ai-catalog pull --scope https://example.com/ai-catalog.json urn:example:agent:v1If --output is a directory, a filename is derived from the identifier. If it
is a file path, that path is used directly. - streams the artifact bytes to
stdout. Omitting --output writes to the current directory.
--scope follows the same name-or-URI rules as show.
If the entry's trust manifest has a subject, the content is checked against
subject.digest first, and a mismatch fails the pull. Signatures are not verified.
When the identifier resolves to a nested catalog entry
(application/ai-catalog+json), --media-type is required:
--media-type |
Result |
|---|---|
application/ai-catalog+json |
Writes the catalog JSON document itself |
| any other type | Pulls the single child entry of that type; errors on 0 or more than 1 match |
| omitted | Errors, suggesting --media-type |
Packs a catalog into the internal JSON artifact-set envelope used by the Rust library. Useful for debugging or pipeline integration when you need to inspect how the CLI represents a catalog before pushing it to an OCI registry.
ai-catalog oci pack catalog.json
cat catalog.json | ai-catalog oci pack -Output is JSON written to stdout.
Unpacks an internal JSON artifact-set envelope back into AI Catalog JSON.
ai-catalog oci unpack artifacts.jsonOutput is JSON written to stdout.
Exports a catalog as a standard OCI image layout
directory. Each catalog entry is stored as a separate OCI manifest; the catalog
itself becomes an OCI image index tagged with --tag.
ai-catalog oci export-layout catalog.json /path/to/layout
ai-catalog oci export-layout --tag v1.0 catalog.json /path/to/layoutWith Cosign signing (see Trust manifest signing):
ai-catalog oci export-layout \
--cosign-key cosign.key \
--cosign-public-key cosign.pub \
catalog.json /path/to/layout| Flag | Description |
|---|---|
--tag <tag> |
OCI tag to apply (default: latest) |
--cosign-key <path> |
Path to Cosign private key; triggers signing of trust manifests |
--cosign-public-key <path> |
Path to PEM public key (derived from --cosign-key if omitted) |
Reads from stdin when <path> is -.
Imports a standard OCI image layout back into AI Catalog JSON. Prints the reconstructed catalog to stdout.
ai-catalog oci unpack-layout /path/to/layout
ai-catalog oci unpack-layout --ref-name v1.0 /path/to/layout| Flag | Description |
|---|---|
--ref-name <name> |
Tag to import (default: first entry in index.json) |
Pushes a catalog to an OCI registry. Internally calls oci export-layout into
a temporary directory, then delegates distribution to oras cp -r.
ai-catalog oci push catalog.json ghcr.io/example/ai-catalog:latest
ai-catalog oci push --tag v1.0 catalog.json ghcr.io/example/ai-catalog:v1.0With signing and registry options:
ai-catalog oci push \
--cosign-key cosign.key \
--cosign-public-key cosign.pub \
catalog.json ghcr.io/example/ai-catalog:latest| Flag | Description |
|---|---|
--tag <tag> |
OCI tag (default: latest) |
--plain-http |
Use plain HTTP instead of HTTPS |
--insecure |
Skip TLS certificate verification |
--to-oci-layout-path <dir> |
Also write the exported layout to this directory |
--cosign-key <path> |
Path to Cosign private key |
--cosign-public-key <path> |
Path to PEM public key |
Reads from stdin when <path> is -. Requires oras on PATH.
Imports a local OCI image layout into the local registry. Unpacks all catalog
entries from the layout and registers the catalog with a urn:ai-catalog:oci:
identifier prefix.
ai-catalog oci add my-layout /path/to/layout
ai-catalog oci add my-layout /path/to/layout --ref-name v1.0| Flag | Description |
|---|---|
--ref-name <tag> |
Tag to import from the layout (default: first entry) |
Searches entries across OCI-sourced catalogs only (those added via oci add).
Accepts the same flags as search.
ai-catalog oci search embeddings
ai-catalog oci search --regex "^urn:ai-catalog:oci:"
ai-catalog oci search --json nlp
ai-catalog oci search -n 10 agentShows full details of an entry from OCI-sourced catalogs only. Accepts the same
--media-type flag as show.
ai-catalog oci show urn:ai-catalog:oci:abc12345
ai-catalog oci show --json urn:ai-catalog:oci:abc12345
ai-catalog oci show --media-type application/json urn:ai-catalog:oci:abc12345Pulls an entry from OCI-sourced catalogs to disk. Accepts the same --output
and --media-type flags as pull.
ai-catalog oci pull urn:ai-catalog:oci:abc12345
ai-catalog oci pull --output ./artifact.json urn:ai-catalog:oci:abc12345
ai-catalog oci pull --media-type application/json urn:ai-catalog:oci:abc12345The local registry lives at ~/.ai-catalog/ by default. Override with the
AI_CATALOG_CACHE_DIR environment variable.
~/.ai-catalog/
├── catalog.json # registry index (AiCatalog document)
├── refs.json # source URL → SHA-256 hash map
└── objects/
└── <sha256>.json # cached catalog blobs
Entries added via catalog add are stored under their source URL and use the
urn:ai-catalog:local: convention. Entries added via oci add use the
urn:ai-catalog:oci: prefix and are scoped separately. The plain search,
show, and pull commands span all sources; the oci search / show / pull
variants are restricted to OCI-sourced entries. See
docs/storage.md for details.
When --cosign-key is supplied to oci export-layout or oci push, the CLI:
- Canonicalizes each entry trust manifest (key-sorted JSON,
signaturefield stripped) - Signs the canonical blob with
cosign sign-blob - Attaches three OCI referrer artifacts to each signed entry:
- the canonical trust manifest (
application/vnd.ai-catalog.trust-manifest.v1+json) - the detached Cosign signature (
application/vnd.ai-catalog.cosign.signature.v1) - the public key (
application/vnd.ai-catalog.cosign.public-key.v1)
- the canonical trust manifest (
Signatures live in the OCI layout as referrers, not embedded in the AI Catalog
JSON. Use oras discover to inspect the referrer tree and cosign verify-blob
to verify. See demo/trust-walkthrough.sh for a
complete end-to-end example.
| Variable | Description |
|---|---|
AI_CATALOG_CACHE_DIR |
Override the default cache directory (~/.ai-catalog/) |
AI_CATALOG_COSIGN_BIN |
Path to the cosign binary (default: cosign) |
AI_CATALOG_ORAS_BIN |
Path to the oras binary (default: oras) |
COSIGN_PASSWORD |
Password for an encrypted Cosign private key |
All demos create a temporary workspace and clean up on exit.
| Demo | Command | Prerequisites |
|---|---|---|
| OCI image layout | just demo-oci-layout |
cargo, cosign, oras |
| Consumer workflow | just demo-consumer |
cargo |
| Trust sign & verify | just demo-trust |
cargo, cosign, oras |
Exercises the full OCI publish/verify flow: validate → generate Cosign key pair
→ oci export-layout --cosign-key → oras discover referrers → print
signature and public key → oci unpack-layout round-trip → oci push to a
second layout. Script: demo/oci-layout-walkthrough.sh.
Exercises every author and consumer command without external tools or network
calls: validate, format, catalog add/list/update/remove, search
(keyword, regex, JSON, limit), show (text, JSON, scoped), pull (inline-data
and file-URL entries), and the full OCI consumer path (oci add, oci search,
oci show, oci pull). Script: demo/consumer-walkthrough.sh.
Demonstrates the complete trust manifest lifecycle: validate → generate
Cosign key pair → sign via oci export-layout --cosign-key → oras discover
referrer tree → extract canonical trust manifest and detached signature →
cosign verify-blob → tamper detection → oci unpack-layout round-trip. Script: demo/trust-walkthrough.sh.
This walkthrough is POSIX only; there is no PowerShell port yet.
| File | Purpose |
|---|---|
LICENSE |
Apache License 2.0 |
CONTRIBUTING.md |
Contribution workflow and local checks |
CODE_OF_CONDUCT.md |
Collaboration expectations |
SECURITY.md |
Vulnerability reporting guidance |
GOVERNANCE.md |
Project decision-making and branch policy |