Library format
A library is a repository whose manifest publishes its authored rule groups, skills, and shared assets for other repositories. Libraries are useful because projects take from them: you write rules and skills once and reuse them in every codebase that needs them. A project is a repository that takes rules and skills for its own work. A repository can be both.
Libraries live in Git repositories. This page covers what makes a repository a library. For the rule and rule group files inside it, see Rule and rule group format; for skill folders, see Skill format. For how each rule and skill is versioned, see Rule and skill versions.
Library layout
Section titled “Library layout”A library uses the same Syllabus directory as every other repository. The tree below shows a library repository named engineering-rules/; the name is an example. A project that uses it stores a vendor snapshot of this content under .syllabus/vendor/<source-name>/; see Project files.
Directoryengineering-rules/
- LICENSE.md
Directory.syllabus/
- config.yaml
Directoryassets/
- retry-lifecycle.svg
Directorychanges/
- 2026-09-29-verify-retry-limits-7f3a9c.yaml
Directoryrules/
Directorytechs/
Directorytypescript/
- _group.yaml
- README.md
- prefer-type-aliases.md
Directorypractices/
Directorytesting/
- _group.yaml
- README.md
- verify-retry-limits.md
Directoryskills/
Directorybuild-feature/
- SKILL.md
Directoryreferences/
- slicing.md
Directoryscripts/
- verify.sh
Directoryreview-tests/
- SKILL.md
Directoryvendor/
- …
Directorygenerated/
- …
A library publishes exactly its authored content:
- Rule groups under
rules/techs/andrules/practices/, each with its rule group metadata and rules. - Skills under
skills/, one folder per skill. - Library-wide files: the manifest in
config.yaml, rule group metadata, shared files inassets/, and the declared license and notice files.
vendor/ and generated/ are the library’s own project files, for the sources it takes from and the guidance its own agents read. Projects never take them from the library.
Syllabus discovers rule groups only under rules/techs/ and rules/practices/, and skills only as skills/<name>/SKILL.md. A rule’s ID is its path in rules/ without .md, such as practices/testing/verify-retry-limits, and a skill’s ID is skills/<name>.
Within a rule group, Markdown files outside reserved asset directories are rules. The README.md at the rule group’s root and declared license and notice files, which can’t use a rule’s path, are exempt. Rule group READMEs are authoring documentation, not generated rule guidance.
Change notes, which record how rules and skills changed, live in changes/. Projects never take them.
Library releases are Git tags, not files; see Library releases.
Other supporting files, including _README.md, must live in an asset directory.
Rules and rule group metadata must use valid paths; a prefix selector also rejects rules whose rule group metadata is missing.
The builder does not inspect the contents of rule groups a project doesn’t include.
config.yaml, change notes, and rule group metadata use one YAML document per file. Duplicate keys, anchors, aliases, and explicit tags are rejected. Generated snapshot and provenance files remain JSON.
The manifest
Section titled “The manifest”The library section of .syllabus/config.yaml is the library’s manifest. It makes the repository a library, declares its license, and sets the level of each skill it offers:
schemaVersion: 2sources: mattpocock: repository: https://github.com/mattpocock/skills.git ref: mainlibrary: license: spdxExpression: MIT file: LICENSE.md notices: [] skills: required: [skills/ship-service] recommended: - skills/build-feature - mattpocock:skills/engineering/to-spec offered: - mattpocock:skills/productivity/grillingThe rest of the file is an ordinary configuration: the library’s own sources and what it takes from them, and its skill targets. Run syllabus library init to add a manifest to a repository.
The manifest replaces rule-library.yaml, and the Syllabus directory replaces root-level techs/, practices/, skills/, assets/, and changes/ folders. A repository with a rule-library.yaml fails to load with a message that shows the new shape; see No backward compatibility. Rule IDs don’t change when you move a library’s rules into .syllabus/rules/.
Skills
Section titled “Skills”Each folder in skills/ is one skill, and its SKILL.md names it. skills/ holds only skill folders, each directly inside it. Skills don’t belong to rule groups, so a skill folder is never inside rules/, or inside another skill.
syllabus library check validates every skill, and a project installs only the skills it includes, its required skills, and the skills they call. A skill’s version covers its whole folder; see What a version covers. For the folder’s contents, the SKILL.md fields, and every check, see Skill format.
A skill can cite rules from any rule group in the library with syllabus-rules-used, and a project that installs it takes those rules too, for reference. Rules can’t link to skills, and skills can’t link to rules or other library files: a skill cites rules by ID, and its links stay inside its own folder.
Skill levels
Section titled “Skill levels”library.skills sets how strongly the library asks its projects to install each skill:
| Level | A project that uses the library installs the skill |
|---|---|
required | Always, whatever it includes. It can’t exclude or fork the skill, but it can rename it. |
recommended | When it includes recommended or "*", or names the skill. |
offered | When it includes "*", or names the skill. |
An authored skill that no level lists is offered, so list only the skills you have an opinion about. Each skill can appear in one level. Levels are library-wide settings: changing one needs no change note, and projects see the change, such as recommended -> required, in their update preview after the next library release.
A project sees only the levels of the libraries it names as sources. Levels don’t chain: when your library borrows a skill from another library, your projects see the level you set, not the other library’s.
Borrowed skills
Section titled “Borrowed skills”A level can list a skill from another repository as <source>:<skill-id>, where <source> is an entry in the library’s own sources, with the ref the library tracks, such as main or a tag. A library borrows skills only, and must list every skill it borrows: a borrowed source’s other skills don’t reach projects.
Projects fetch a borrowed skill’s files from the original repository, not from the library, and record which library required, recommended, or offered it. A library release doesn’t lock a borrowed source’s ref: each project resolves it when it runs syllabus project update, so moving a borrowed skill forward needs no new library release, and two projects on the same library release can hold different commits of it. A project overrides the ref by declaring the same repository as its own source. See Borrowed skills.
Your library repository is a project too, so it installs the required skills of the sources it borrows from, as your projects do.
Name clashes
Section titled “Name clashes”Agents find skills by name, so syllabus library check fails when two skills the manifest lists, authored or borrowed, have the same name. It reads each borrowed source at its ref to find the names. Fix the clash in the library, so your projects never have to rename a skill to install both.
Shared assets
Section titled “Shared assets”Files that several rules use, such as a shared diagram, live in .syllabus/assets/. A rule’s own supporting files live beside it instead. Supporting assets covers both locations and the rules for linking to them.
Shared files are library-wide files: they aren’t part of any rule or skill version, need no change note when they change, and reach projects with the next library release, when each project runs syllabus project update. See What a version covers.
License metadata
Section titled “License metadata”The optional library.license object declares the library-wide terms. Authors should use a LICENSE.md and optional NOTICE.md at the repository root; the manifest can identify other source locations:
| Field | Meaning |
|---|---|
library.license.spdxExpression | Declared SPDX expression, such as MIT or MIT OR Apache-2.0, or a LicenseRef-… for custom terms. |
library.license.file | Path to the actual license text, relative to the repository root. |
library.license.notices | Paths to accompanying notices, relative to the repository root; use an empty array when none apply. |
When license is present, all three fields are required and all declared files must exist within the repository.
Declared license and notice files are library-wide files, so they can’t be part of a rule’s or skill’s version: a declared path can’t be a rule’s Markdown file, lie in a rule’s asset directory, such as .syllabus/rules/practices/testing/assets/verify-retry-limits/LICENSE, or lie in a skill folder, such as .syllabus/skills/build-feature/LICENSE. Otherwise a later library release could replace a file that a project’s pinned rule version covers. syllabus library check rejects such a declaration, and projects refuse to take a library release whose manifest has one.
A project’s vendor snapshot of the library stores a declared file from outside .syllabus/ at its path from the repository root, beside the files from .syllabus/, so that path can’t start with a name the snapshot uses for those files or its records, in any letter case: _source.json, config.yaml, assets/, borrowed/, changes/, rules/, or skills/.
Unknown fields in the license declaration are rejected so misspellings cannot silently discard intended metadata.
Syllabus retains the declared files from the resolved source commit and links generated rules to unchanged copies. Offline builds require those files in the stored snapshot.
If the declaration is absent, provenance records license: null. Syllabus never infers an identifier from a filename. It validates supplied SPDX expressions and identifiers using its bundled license list, while allowing LicenseRef- identifiers for custom terms. This validates the declaration format, not ownership, permissions, or agreement between the declaration and the retained text.
Every library a project uses has a generated libraries/<source-name>/README.md with its repository, library release, requested ref or pins, each included rule’s and installed skill’s version and level and whether the project excludes or replaces it, or still includes it after the library retired it, a notice when it was taken from unreleased changes, declared SPDX expression when supplied, and links to retained terms and provenance. Libraries without a license declaration omit the licenses/ directory. Provenance documents the machine-readable records.
The manifest paths select source files, not output locations. For declared terms, Syllabus uses these fixed destinations:
generated/libraries/<source-name>/licenses/LICENSE.mdgenerated/libraries/<source-name>/licenses/notices/001.mdgenerated/libraries/<source-name>/licenses/notices/002.md<source-name> is the name the project gave the source. Unique notice files are numbered in declaration order; repeated paths and a notice path identical to the license path are copied only once. No notice files are generated when none are declared. Contents, including whitespace and line endings, are preserved. Output paths are not configurable. Vendor snapshots retain the original names for traceability. Declared terms are retained even when exclusions or replacements leave no active rules from that library.
One library-wide license declaration covers every rule group, rule, and skill the library authors. A license or licenses field on a rule or rule group is rejected. A skill’s SKILL.md can carry the Agent Skills license field, but it’s informational: syllabus library check warns when it differs from the library’s SPDX expression; see Skill format. A borrowed skill keeps its own repository’s terms, which Syllabus finds as it does for any non-library source.
Keep original attribution with each rule and include required notices in the manifest. Material requiring a different declaration belongs in a separate library.
See License rules for publisher guidance and the boundary with the consuming project’s license.
Libraries in the earlier layout
Section titled “Libraries in the earlier layout”Earlier versions of Syllabus read a library’s manifest from rule-library.yaml, and its groups, shared assets, and change notes from techs/, practices/, assets/, and changes/ at the repository root. This version doesn’t read that layout and doesn’t move it. Every library command fails, writing nothing, while rule-library.yaml, techs, or practices exists at the repository root, with a message that shows where each file moves:
| Earlier layout | This layout |
|---|---|
rule-library.yaml | The library section of .syllabus/config.yaml |
techs/<group>/, practices/<group>/ | .syllabus/rules/techs/<group>/, .syllabus/rules/practices/<group>/ |
assets/ | .syllabus/assets/ |
changes/ | .syllabus/changes/ |
Move the files with git mv, then delete rule-library.yaml and write its license fields, without formatVersion, in the library section of .syllabus/config.yaml, beside the sources the repository uses as a project, if any. License and notice paths stay relative to the repository root, so they don’t change.
Rule IDs and versions don’t change. A moved rule sits two folders deeper, so its relative links to shared assets need one more ../, such as ../../../assets/retry-lifecycle.svg, and its links to license files at the repository root need two more. Links that start with /assets/ still work, because a link that starts with / resolves from .syllabus/. Once the library has a library release, record each rule whose links changed with syllabus library change RULE_ID --bump patch, then run syllabus library check. A rule whose bytes didn’t change needs no note, and moving the manifest isn’t a library-wide change unless its license fields changed.
Projects can’t import a library release in the earlier layout; sync and update fail with unsupported-library-layout until the library publishes a library release from the new layout and the project selects it. Rule versions that a library release in the earlier layout published still import when a later library release keeps them, unless one of their links resolves to another file in the new layout. A project that imported the library before it moved keeps a vendor/<source-name>/rule-library.yaml, which this version can’t read either: once the library has published a library release from the new layout, delete .syllabus/vendor/<source-name>/ and run syllabus project sync.
Read libraries from other tools
Section titled “Read libraries from other tools”Tools written in Go, such as a catalog of libraries, can read library release tags, release records, rule files, rule group metadata, and the canonical rule group list with the github.com/fabricahq/syllabus/syllabus package, whose Go documentation describes its API. Syllabus reads libraries through the same package, so both read them the same way. The package only parses text the tool has already read, such as with a Git library; it has no Git, filesystem, or network access. It follows Syllabus’s version, and its API may change before Syllabus 1.0.0.
Related guides
Section titled “Related guides”- Create your first library walks through organizing and sharing a library.
- Write a skill walks through adding a skill to a library and setting its level.
- Version your rules explains change notes and publishing library releases.
- License rules explains how to choose and declare terms.
- Configuration explains how a project includes rules and skills from its sources.