Library format
A library is an independently maintained collection of rule groups. Libraries are useful because projects import them: you write rules once and reuse them in every codebase that needs them. A project is a codebase that uses rules to guide its agents. It can write its own rules, import them from libraries, or both.
Libraries live in Git repositories. This page covers what makes a repository a library. For the rule and group files inside it, see Rule and group format. For how each rule is versioned, see Rule versions.
Library layout
Section titled “Library layout”The tree below shows a library repository named engineering-rules/. The folder name is an example; you can name your library repository anything you like. These are the library’s source files. A consuming project stores imported copies under vendor/ in its Code Rules directory (.code-rules/vendor/); see Project files.
Directoryengineering-rules/
- rule-library.yaml
- LICENSE.md
Directorychanges/
- 2026-09-29-verify-retry-limits-7f3a9c.yaml
Directorytechs/
Directorytypescript/
- _group.yaml
- README.md
- prefer-type-aliases.md
Directorypractices/
Directorytesting/
- _group.yaml
- README.md
- verify-retry-limits.md
rule-library.yaml is the library’s manifest. It declares the library format and its license:
formatVersion: 1license: spdxExpression: MIT file: LICENSE.md notices: []Discover groups only under techs/ and practices/.
Within selected groups, Markdown files outside reserved asset directories are rules. The group-root README.md and declared license and notice files, which can’t use a rule’s path, are exempt. Group READMEs are authoring documentation, not generated rule guidance.
Change notes live in the library-root changes/ directory. Projects never import 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 group metadata must use valid paths; wildcard discovery also rejects rules whose group metadata is missing.
The builder does not inspect the contents of unselected groups.
rule-library.yaml, change notes, and group metadata use one YAML document per file. Duplicate keys, anchors, aliases, and explicit tags are rejected. Generated snapshot and provenance files remain JSON.
Shared assets
Section titled “Shared assets”Files that several rules use, such as a shared diagram, live in the library-root assets/ directory. 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 version, need no change note when they change, and reach projects with the next library release, when each project runs code-rules project update. See What a version covers.
License metadata
Section titled “License metadata”The optional license object declares the library-wide terms. Authors should use root-level LICENSE.md and optional NOTICE.md; the manifest can identify other source locations:
| Field | Meaning |
|---|---|
license.spdxExpression | Declared SPDX expression, such as MIT or MIT OR Apache-2.0, or a LicenseRef-… for custom terms. Optional for compatibility with existing manifests. |
license.file | Path to the actual license text, relative to the library root. |
license.notices | Paths to accompanying notices, relative to the library root; use an empty array when none apply. |
When license is present, file and notices are required and all declared files must exist within the library.
Declared license and notice files are library-wide files, so they can’t be part of a rule’s version: a declared path can’t be a rule’s Markdown file or lie in an asset directory inside a technology or practice group, such as practices/testing/assets/verify-retry-limits/LICENSE. Otherwise a later library release could replace a file that a project’s pinned rule version covers. code-rules library check rejects such a declaration, and projects refuse to import a library release whose manifest has one.
Unknown fields in the license declaration are rejected so misspellings cannot silently discard intended metadata.
Code Rules 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. A legacy declaration with files but no expression records spdxExpression: null; that differs from no declared terms. Code Rules 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. The former license.expression field is rejected with a rename instruction; use license.spdxExpression.
Every imported library has a generated libraries/<source-name>/README.md with its repository, imported library release, requested ref or pins, each rule’s version and whether the project excludes or replaces it, or still imports it after the library retired it, a notice when it was imported 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, Code Rules 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 configured library alias. 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. Vendored 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 group and rule. Rule- and group-level license or licenses fields are rejected.
Keep original attribution with each rule and include required notices in the library 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.
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, group metadata, and the canonical group list with the github.com/fabricahq/code-rules/coderules package, whose Go documentation describes its API. Code Rules 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 Code Rules’ version, and its API may change before Code Rules 1.0.0.
Related guides
Section titled “Related guides”- Create your first library walks through organizing and sharing a library.
- Version your rules explains change notes and publishing library releases.
- License rules explains how to choose and declare terms.
- Configuration explains how a project selects libraries and rules to import.