Kai Ase Siren
Skip to content

Skill catalogues

The catalogue export surface and the local catalogues it reads.

Catalogues and bundle export

Agent Compose exposes the effective selected profile through deterministic text and JSON catalogues. Inspection is read-only. It does not select a role, activate a personality, change authority, or fetch a source.

Catalogue commands

Every person-dependent command accepts --person-source and repeatable --personality-library roots:

agent-compose catalog personalities [--query ] [--json]
agent-compose catalog roles [--json]
agent-compose catalog seats [--role ] [--json]
agent-compose catalog expressions [--json]

Text output is unpaged and follows effective catalogue order. Exact normalized personality slugs win over aliases. An ambiguous alias returns every candidate in catalogue order.

Every JSON command emits:

{
  "format": "agent-compose.catalog.v1",
  "items": []
}

Each item carries the whole stable object for its kind, so the emitted JSON is the field list rather than a copy of it here. Personality items add role affinities, role items role-skill provenance and background, seat items role, and expression items are plain strings.

Deterministic export

agent-compose bundle export <bundle-dir> --out <file>.tar.gz verifies the bundle before opening the output. The exporter sorts safe relative paths, rejects links and non-regular entries, normalizes gzip and tar metadata, and includes manifest.json, so identical verified trees export byte-identical.

Content-aware diff

agent-compose diff <left-bundle> <right-bundle> reports resolver-decision changes, logical content changes, and changed bundle artifacts. Logical content uses the manifest's stable IDs and SHA-256 digests, so a content change stays visible even when it alters no resolver decision.

Local skill catalogues

Agent Compose accepts an AOS-emitted local catalogue manifest:

skill_catalog_manifest: ~/.config/aos/catalogues.json

This is the Agent Compose v2 ownership boundary. AOS owns remote selection, Git access, locking, cache freshness, offline fallback and host paths, and must complete them before convergence runs. Agent Compose opens only the resulting local JSON: it never fetches a source, and never mutates MCP or approval config.

Manifest contract

The document must use aos.catalogues.v1:

{
  "format": "aos.catalogues.v1",
  "forge": "https://git.example.com",
  "catalogues": [
    {
      "source": "owner/repo/.agents/skills@main",
      "path": "/absolute/local/catalogue",
      "commit": "0123456789abcdef0123456789abcdef01234567"
    }
  ]
}

Every entry needs a source that resolves to a forge, an absolute existing directory, and a full 40- or 64-character Git object ID. Unknown fields, trailing JSON, unsupported formats, missing paths, relative paths, and regular files all fail before roster or load-point writes.

Every source names its forge

A source carrying a scheme names its own forge, as https://github.com/acme/handbook/.agents/skills@main does. A bare owner/repo/path takes the document's forge, which an entry may override with its own. Both keys take the URL form config is written in or the bare host a record carries. A bare source with no forge to take is an error rather than one that picks a side: acme/tools can exist on both git.example.com and github.com, one canonical and one a mirror whose content may lag, and only you know which one you meant.

A record names the host, as git.example.com/acme-games/server/.agents/skills@main, and a skill in it drops the catalogue path. Source travels with the path rather than being checked and dropped, so a warning names the repository to fix.

Entries retain declaration order, and one catalogue listed twice is refused as a malformed manifest rather than ruled on as a duplicate. Two different catalogues offering one name dedupe on equal content and are fatal on divergent content, naming both. Unowned files at a load point still win.

An entry marked "private": true keeps its content and loses its identity: its skills project as any other catalogue's, and its source renders as private catalogue <n> everywhere agent-compose writes. Source.Reveal() returns the real string for a message staying on the host that holds the catalogue, and is the one call that must never reach shipped output. That is what lets a private focus reach a public lane without the public image learning it exists.