catalog

command
v1.4.14 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 14 Imported by: 0

README

tools/catalog

One generator for registry.json, catalog.json and counts.json (contract:plugins.catalog v1, Epic P7-PLUG D3). It replaces the hand-edited registries, plugins-pro:scripts/build-registry.py and plugins:scripts/plugin-counts.sh. Every value derives from a manifest, releases.json or bundles.json; nothing is typed by hand.

Run it in a plugin repo, built from a checkout of a pinned CLI ref (a tag or a full commit sha):

ref=<cli tag or commit sha>
src="$(mktemp -d)"
git -C "$src" init --quiet
git -C "$src" fetch --quiet --depth 1 https://github.com/nself-org/cli "$ref"
git -C "$src" -c advice.detachedHead=false checkout --quiet FETCH_HEAD
(cd "$src" && go build -mod=vendor -o "$src/catalog" ./tools/catalog)
"$src/catalog" -mode free ...
rm -rf "$src"

go run github.com/nself-org/cli/tools/catalog@<cli tag> does not work: the cli go.mod holds replace directives (the sdk module comes from ./sdk/go), and Go refuses to run a package from a downloaded module that has them. The checkout builds offline from the tracked vendor/ tree (D-0516).

Mode Reads Writes
free -plugins free/, -releases, -bundles, optional -peer-registry (licensed registry) registry.json
licensed -plugins paid/, -releases, -bundles, optional -peer-registry (free registry) registry.json
catalog -free-registry, -licensed-registry, -bundles catalog.json, counts.json

Common flags: -out dir, -require-released (a manifest with no releases.json row is an error instead of a note), -check (write nothing, exit 1 when a file differs), -plugins-ref, -bundles-ref, -generated-at (RFC 3339; default SOURCE_DATE_EPOCH, else the Unix epoch, never a clock). Exit 0 ok, 1 -check found a difference, 2 bad input or a data problem (all problems are listed). -partial is a diagnostic: it writes what loads and still exits 2.

Inputs

  • Manifests are read only through internal/plugin/manifestv2, so v1 and v2 plugin.json files give the same entry. The directory name must equal the manifest name. Directories starting with _ or . are not plugins: they are skipped with a note: on stderr, so a manifest placed there is never read. A manifest carrying both minNselfVersion and min_nself_version with different values is refused. A manifest whose license does not match the tree (free in paid/, licensed in free/) is refused: a plugin never moves tier here. The public repo never reads licensed manifests; it reads the licensed registry.json this tool wrote.
  • releases.json (schemas/releases.v1.schema.json) is release data written by the release pipeline from published bytes: per slug version, sha256, release_signature ({key_id, alg: ed25519, sig} or null), tarball_url, and optional release_tag, tarball, platform_checksums, binaries. A manifest with no row is left out of the registry (no checksum yet) and named on stderr (-require-released makes it an error); a row with no plugin directory is an error. When the manifest and the row disagree on the version, the registry carries the release and a note names both.
  • Command binaries. v1.4.12 turns an entry's cliCommands, binaryName and pluginType into required nself-<command> binaries and fails the install when the archive lacks one. A manifest cannot say whether the archive ships them, so those three keys are emitted only for a release whose binaries list covers every binary they require (a shortfall is an error); a row without binaries emits none, and the entry requires nothing, as the committed registry does for source-only archives. The release pipeline writes binaries from the tarball listing.
  • bundles.json is the membership source of truth. A free bundle lists free entries, a paid bundle lists licensed entries (catalog tier licensed). A member missing from its tier's registry is an error.

Outputs

registry.json keeps the key names and types of the registry released CLIs decode (v1.4.12). It adds _generated, generated_from, release_signature (when signed) and a per-entry catalog block (the manifest-only columns, so the catalog is built from registries alone). Dropped: the hand-written note, the two timestamps generated_at and last_updated, the licensed version and checksum_provenance envelope keys, and the licensed security_always_free entry key (no manifest v2 home, read by no CLI). tier is free or pro on the wire. tier_pair is set when the slug is in the peer registry.

catalog.json has one row per slug and tier sorted by (slug, tier); a tier-pair slug has a row per tier and counts once. counts.json keeps the existing shape (free, pro, overlap, totals, advertised) with generated_from in place of generated_at and sources.

All files: sorted keys, 2-space indent, trailing newline, no HTML escaping, byte-identical for identical inputs. Timestamps appear only as generated_from.generated_at.

Tests

go test ./tools/catalog/... runs golden files over trimmed copies of real plugin manifests and the real bundles membership, the v1.4.12 decode test, the v1/v2 twin test and the schema checks. go test ./tools/catalog -update rewrites the goldens.

Documentation

Overview

Command catalog generates registry.json, catalog.json and counts.json from plugin manifests, releases.json and bundles.json (contract:plugins.catalog v1).

Purpose: the one generator of the plugin projections (Epic P7-PLUG D3). Run it in a plugin repo pinned to a CLI tag:

go run github.com/nself-org/cli/tools/catalog@<cli tag> -mode free ...

Inputs: see README.md; flags -mode free|licensed|catalog, -plugins, -releases, -bundles, -peer-registry, -free-registry, -licensed-registry, -out, -check. Outputs: free and licensed write registry.json; catalog writes catalog.json and counts.json. Exit 0 ok, 1 when -check finds a difference, 2 on bad input or failure. Output is deterministic: no clock, sorted keys, 2-space indent. Constraints: imports only internal/plugin/manifestv2, the model package and the standard library, so it runs from a module download with no network.

Directories

Path Synopsis
Package model holds the wire types of the plugin catalog generator (contract:plugins.catalog v1, contract:plugins.registry, contract:plugins.counts).
Package model holds the wire types of the plugin catalog generator (contract:plugins.catalog v1, contract:plugins.registry, contract:plugins.counts).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL