Reference documents
A reference is a named Markdown document an agent reads on demand, such as a checklist or a set of
weights a skill applies. A skill asks for it by name, such as project-tracker.capabilities.github,
and gets exactly that. Whoever places a contribution for the name decides what it says: a plugin
ships one, a skill ships its default, and a repository, a user, or a machine-wide policy can each
add their own without forking the plugin.
import { loadReference } from 'cyber-agentkit'
const resolved = await loadReference('agent-readiness-weights', { root: process.cwd(), plugin: { name: 'my-plugin', root: pluginRoot }, defaultSkill: skillFolder,})if (resolved.status === 'found') console.log(resolved.content)From a shell, or from an agent:
npx -y cyber-agentkit reference show agent-readiness-weightsThe reference command
Section titled “The reference command”| Subcommand | Does |
|---|---|
show <name>... |
Prints each reference, composed from its contributions; --trace says how it was built |
list [pattern] |
One row per name, with its description, and its status when not found; --trace adds a row per layer holding it |
search <query> |
References matching a query by name, description, tags, heading, or body |
where <name> |
The project and user files a customization is written to, and the heading paths below each |
create <name> |
Starts a contribution, with merge: patch unless --merge says otherwise |
select <name> <option>... |
Writes the extends that picks what a name builds on |
delete <name> |
Deletes a project or user contribution, and reports what answers the name afterwards |
implementations <id> |
The implementations of an interface a consumer can load |
check [name]... |
Checks references against their interface; exits 1 on any failure |
create, select, and delete act on the project tier by default (.agents/references/ at the
root) or the user tier with --scope user (~/.agents/references/). create and delete also
take --plugin <plugin folder> or --default <skill folder>, for a plugin’s or a skill’s source in
the repository. They never write to a managed folder or an installed copy of a plugin or skill.
--dry-run prints what create or delete would do. The read-only subcommands change no file.
The reference skill
Section titled “The reference skill”The package is also an agent plugin, cyber-agentkit, that ships a reference skill. Type
/reference to run it. Installed as a Claude Code plugin, it is /cyber-agentkit:reference. The
skill page lists every kind of request it handles.
The skill shows each file and its path, and writes or deletes it only on your approval. It never
edits a contribution a plugin ships; it writes one above it instead. Load runs only the skill’s
bundled scripts/reference.mjs, never a package runner.
A skill loads references by naming them in one line:
Load `agent-readiness-weights` and `release-checklist` with the `reference` skill of `cyber-agentkit`.Where contributions are read from
Section titled “Where contributions are read from”A name may have a contribution in several layers. The tiers, listed from highest to lowest:
| Tier | Folders |
|---|---|
| managed | references/ beside each detected harness’s managed-policy files |
| project | .agents/references/ in the root and each folder above it, up to the repository root; the nearer folder is higher |
| user | ~/.agents/references/ |
| plugin | The calling plugin’s references/, each plugin the harness has enabled, then each declared dependency of the nearest package.json that has a plugin manifest |
| default | <skill folder>/references/<name>.default.md of the skill loading the name, given by --default <skill folder> |
Within a folder, only <name>.md and <name>/README.md answer a name, in that order. A
<name>.default.md in a tier folder is ignored with a warning: a default goes in a skill’s
references/ folder.
A plugin is named by the name in its plugin manifest, never by its npm package name. A plugin
layer is read only for a plugin the harness has enabled, or a package the project declares that has
a plugin manifest. Installing a plugin never adds a layer, because a reference is instruction text
an agent follows.
list, search, and check also find skills’ defaults in the skill folders the detected harness
reads: its project and user skill folders, its machine-wide admin skill folders, and each enabled
plugin’s skills. This covers Claude Code, Cursor, Codex, GitHub Copilot CLI, OpenCode, and Gemini
CLI. A skill is known by the name in its SKILL.md, not by its folder’s name, and a symlinked
skill folder is followed, so skills that pnpm or npx skills linked are found. On another harness,
the answer says why no default is listed.
How contributions compose
Section titled “How contributions compose”Contributions apply bottom first, each over the result of everything below it:
- The stack: the plugins and the default, in the order
extendsgives them. - The user contribution.
- The project contributions, from the repository root down to the root.
- The managed contributions.
A higher contribution wins where they conflict.
Operations
Section titled “Operations”Frontmatter merge says how a contribution applies over what is below it.
merge |
Effect |
|---|---|
patch (default) |
Keeps what is below, and puts each section’s text in place of the text it matches by heading path |
combine |
Keeps what is below, and adds each section’s text after the text it matches |
replace |
Drops everything below |
remove |
Drops everything below; its body is ignored with a warning |
A heading path is read from each document’s own top heading level, so # Review and ## Review
match. Under patch, a section with empty text keeps the text below, and a section that matches
nothing is added at the end. Its subsections replace the ones they match, and the others are kept.
Under combine, the lower text comes first, subsections combine too, and the document says once
that where combined text conflicts, the later text wins.
A contribution with no body changes nothing, except with remove. When a remove is the last
contribution with an effect, the name is missing, and the trace names the remove.
A marker under a heading applies one operation to that section alone; a section with no marker takes its document’s operation:
## Weights<!-- merge: combine -->
- Tests: 30An unknown merge value or marker is read as patch, with a warning. A marker that matches no
section below warns, and its text goes at the end.
What a contribution builds on
Section titled “What a contribution builds on”Frontmatter extends lists what a contribution builds on, bottom first: plugins by their manifest
name, and default for the loading skill’s default.
---extends: [default, repobuddy, house-style]---- The highest
extendswritten in the managed, project, or user tier builds the stack. A plugin or the default it leaves out is not used. - Each step brings its own
extendsbeneath it. A step can carry its own keys:- house-style: {merge: combine, extends: []}, orhouse-style: combinefor just the operation. - With no written
extends, the plugins’ ownextendsorder them, and the default is lowest. Plugins that nothing orders make the nameambiguous, with each<plugin>/<name>and the default as options. - A step not installed, or not holding the name, is skipped with a warning. When every step is
missing, the
extendscounts as not written. - When a plugin answers over the loading skill’s default and no
extendsnames either, the name still answers, with a warning that namesreference select.
A contribution with extends and no body is a selection: it picks the stack and changes nothing
else. reference select <name> <option>... writes one, and --clear removes it:
npx -y cyber-agentkit reference select project-tracker.capabilities.github repobuddy house-styleA qualified name, <plugin>/<name>, builds that plugin’s own stack. A written extends is not used
for it, and managed, project, and user contributions still apply over it.
Names and statuses
Section titled “Names and statuses”A name is letters, digits, -, and ., optionally after <plugin>/. A name that ends .md or
.default, is a path, or has another character is invalid. Nothing is read for it, and the other
names still resolve.
| Status | Code | Means |
|---|---|---|
found |
The composed document | |
missing |
reference-missing |
No contribution answers, a qualified name’s plugin is not installed, or a remove turned it off |
ambiguous |
reference-ambiguous |
The contributions cannot be put in one order; options lists the choices |
invalid |
reference-invalid |
It is not a reference name |
Output
Section titled “Output”Output is agent-first: a command prints only the fields that answer it.
show --format jsongives each found name’s content as a string. A name not found, or one with warnings, is a record.--metadatamakes every entry a record, with itsstatusandmetadata: the composed frontmatter, the higher contribution winning each key, withoutmergeandextends.--traceadds the trace. It shows the stack and what built it, the contributions behind each section, and every layer checked with its frontmatter as written, its operation, and its outcome. The trace also names the detected harnesses.
Every warning is {code, message}; the code is stable and the wording is not. In text, a failure
prints on stderr as error: <code>: <message> and a warning as warning: <code>: <message>.
Several names print as <reference name="..."> blocks, in the order asked.
The command exits 0 when every name is found, 1 when one is not or a write is refused, and 2 on a usage error.
Frontmatter
Section titled “Frontmatter”Frontmatter is read as YAML. The resolver reads merge and extends; list and search show
description, and search also matches tags. check and implementations read interface and
implements. Frontmatter that is not a YAML mapping is ignored with a warning.