04Model · Catalog
The catalog is canonical.
A catalog is a directory with skill-suitcase.yaml and
skill directories under skills/. Runtime and agent homes
are targets; a live target never becomes source merely because it
contains a skill or a newer local edit.
Layout
/path/to/skills-catalog
├── skill-suitcase.yaml # the manifest
├── skills/
│ ├── office-hours/
│ │ └── SKILL.md
│ └── gnhf-postflight/
│ └── SKILL.md
├── variants/ # declared alternate source directories
│ ├── claude/office-hours/
│ └── codex/office-hours/
└── .skill-suitcase/
└── upstream-lock.json # pinned upstream declarations, if any
Git backing is the preferred operating model because it provides
reviewable provenance and recovery, and workflows with stronger
source-control requirements, such as upstream import, refuse a
catalog outside a Git worktree. Ordinary planning and target
materialization also accept a non-Git catalog directory. Support
directories marked with .support-directory are not
treated as installable skills.
What the manifest owns
Names and references must validate deterministically. Target
resolution precedence is: CLI path overrides, then manifest
assignmentPaths, then native adapter behavior, then the
vendored skills.sh compatibility snapshot.
Categorized Hermes roots
The writable hermes-external-skills-root adapter uses
explicit home and path fields and installs
each assigned skill at
<path>/<category>/<skill>.
Its assignment must declare one safe plain
categories segment for every selected skill.
assignments:
hermes:
suitcases:
- core
categories:
agent-swarm: autonomous-ai-agents
assignmentPaths:
hermes:
kind: hermes-external-skills-root
assignment: hermes
home: /path/to/hermes
path: /path/to/hermes/skill-suitcase/skills
Create the external root and register its exact path in
<home>/config.yaml under
skills.external_dirs before inspecting or mutating
live target state. Skill Suitcase never creates the root or edits
Hermes configuration.
Fail closed
The root must not overlap <home>/skills or an
earlier configured external root. Local or earlier external
skills must not shadow a planned SKILL.md identity,
and the plan itself must not contain duplicate identities.
Category and traversal symlinks are refused. One central receipt
remains at the owned external root.
Logical groups
Reporting only
Groups organize skills, suitcases, and assignments for operator reporting. They are catalog metadata only: they validate references deterministically but do not change planning, packing, installation, receipt, or target assignment semantics. Broken group references are catalog metadata problems, not implicit install targets.
Source policy
sourcePolicy.exclude omits approved generated or cache
paths from pack, plan-lock, diff, and copy-mode apply
materialization. sourcePolicy.deny, including built-in
secret-like path denials, blocks unsafe source paths before any
target write and reports path-level evidence.
-
Refused
Symlink apply cannot omit descendants, so it refuses every non-empty exclude policy with
symlink_source_policy_exclude, even when no path currently matches. -
Refused
Denied paths surface as
source_denied_pathordiff_source_denied_path, identifying the skill and relative path. -
Refused
For Git-backed catalogs, pack, plan-lock creation, and apply refuse selected skills containing untracked, non-ignored files (
source_untracked_files). Git-ignored regular files may still be materialized unless source policy excludes or denies them.
Variants and portability
The catalog is the authority for canonical bundles.
compatibility.<skill>.variant and
variants.<skill>.<variant> declare portable
source variants per agent, so one skill can ship agent-specific
source directories while planning stays deterministic. The
portability matrix
documents the variant and compatibility model in detail.
Strict validation
validate --strict --json applies the Skillify authoring
contract. Reviewed validationPolicy.skillify.skip
entries can exempt referenced external, legacy, or upstream-managed
skills from strict scoring when their provenance is valid:
external-managed entries need source,
owner, and reason;
legacy-local entries additionally require a
reviewAfter date and emit
legacy_skillify_skip so migration debt stays visible.
Boundary
A validation skip changes validation only. It does not change planning, installation, receipt, ownership, or target-drift semantics, and malformed skip policy is release-blocking rather than silently ignored.
The normative catalog contract lives in SPEC.md, with a working example in the catalog fixture.