Consumer guide

Reading & using

After you pull an artifact, this page covers what the bundle contains, how to read it without writing files, how it renders on the web, and how to use it in scripts and CI.

What unpack writes

grcli unpack writes the bundle's contents into --output (default ./grcli-unpacked):

  • The original Gemara file(s) — the YAML exactly as the publisher authored it, ready to read or feed to any Gemara-aware tool.
  • bundle.json — the OCI manifest plus the artifact's SLSA-shaped provenance: what was built, from where, and by whom.

The digest shown on a release page and in bundle.json is the artifact's identity. Because tags are immutable, that digest never moves — re-pulling a version always yields the same bytes.

Stream content with cat

grcli cat streams the artifact file(s) to stdout and nothing else — no bundle.json, no manifest. Diagnostics go to stderr, so a pipe stays clean:

$grcli cat --repository finos-ccc/ccc.objstor.cn --version 1.0.0 | yq '.metadata.title'

A single-file bundle prints verbatim; a multi-file bundle prints as a --- separated YAML stream. Pull one file out of a multi-file bundle with --file:

$grcli cat --repository <namespace>/<catalog_id> --version <version> --file controls.yaml

Read on the web

Most artifacts render on their release page — control, guidance, capability, principle, threat, and vector catalogs each have a built-in view. A control catalog also offers Markdown and OSCAL tabs, both derived server-side, so you can read a human-readable version or hand the OSCAL to another tool without pulling anything.

Pulling references and imports

Artifacts cite each other — a control catalog may import a lexicon or map onto a framework. grcli unpack can resolve those links and pull them alongside the primary artifact:

  • --with-imports — also pull the artifact's imports.
  • --with-references — pull all mapping references (a superset of --with-imports).
$grcli unpack --repository <namespace>/<catalog_id> --version <version> --with-references

Each referenced artifact lands in its own directory — references/<category>/<ns>/<id>@<version>/ holding its original YAML plus bundle.json — and references/index.json maps every reference to its path.

The local cache

A remote unpack or cat stores the whole decoded bundle on disk, keyed by (host, namespace, id, version). Because tags are immutable, a cache hit is always fresh — repeat fetches, and references to the same coordinate, are served without touching the network (discovery is skipped entirely on a hit).

  • Location$GRCLI_CACHE if set, otherwise your OS cache dir (~/Library/Caches/grcli on macOS, ~/.cache/grcli on Linux).
  • Skip once--no-cache forces a fresh pull for a single run and stores nothing.
  • Disable durablycache-enabled: false in config (or GRCLI_CACHE_ENABLED=false).

Config and pointing at a hub

Every command defaults to https://hub.grc.store. To target a private or self-hosted hub, set the URL once. Settings resolve in this order, highest first:

  1. a command-line flag (--url, --no-cache, …);
  2. a GRCLI_* environment variable (GRCLI_URL);
  3. the user-global ~/.config/grcli/config.yaml;
  4. the built-in default.

The user-global file is just a couple of keys — point grcli at your own hub with url: https://hub.example.internal, and turn the cache off with cache-enabled: false. The same keys work as GRCLI_URL and GRCLI_CACHE_ENABLED in the environment.

In scripts and CI

The read commands compose in a pipeline: resolve the latest version, stream a field, and gate on the signature — without writing files or signing in:

$grcli versions <namespace>/<catalog_id> --latest
$grcli cat --repository <namespace>/<catalog_id> --version <version> | yq '.metadata'
$grcli verify --repository <namespace>/<catalog_id> --version <version>

versions --latest prints one line (or nothing, exit 0, when there are no releases); cat keeps stdout pipe-clean; verify in its zero-flag form checks the signature against the identity the hub recorded at publish and exits non-zero when it doesn't check — enough to fail a pipeline on an artifact you don't trust. Pin the expected identity with --certificate-identity or --cosign-key to verify independently of the hub.