shelf Docs
On this page

Library and skills

The library is the directory ~/.shelf/library (or $SHELF_HOME/library). Each subdirectory with a SKILL.md is a skill, in the Agent Skills format: YAML frontmatter with a name that matches the directory and a description, followed by instructions, plus any reference files or scripts.

You edit the library with any tool. There is no daemon: every shelf command that reads skills first reconciles the library with the database, recording a new revision for anything that changed. A library directory that isn't a valid skill is skipped with a warning (see shelf doctor).

Skill names are 1 to 64 characters of lowercase letters, digits and single hyphens, with no leading or trailing hyphen: pdf-tools, react-best-practices.

Revisions

A revision is an immutable snapshot of a skill directory, named by its content hash: SHA-256 over every file's relative path and the SHA-256 of its bytes, written sha256:9f86d0…. Commands show the first 10 hex characters (ddad27dd34) and accept any unique prefix of at least 6.

Snapshots live in ~/.shelf/objects/<hash>/ and are never deleted. Each revision records its parent and its source:

SourceRecorded when
libraryThe library copy was edited (or created with shelf new, or restored).
promoteA project's edits were published with shelf promote.
importshelf add imported the skill, or shelf pull updated it.
adoptshelf adopt --unedited recorded an older copy found in a project.

The library's latest revision (its head) is what new loans get. shelf log <name> lists every revision and which projects hold it; shelf restore makes an earlier one the latest again.

Projects

A project is a directory that uses shelf, marked by .agents/shelf.lock.json. shelf finds the project root by walking up from the working directory: the nearest directory with a lockfile, else the nearest git root, else the working directory itself. Run commands from anywhere inside the project.

shelf init registers a project. A clone of a project that already has a lockfile is recognised and registered the first time any shelf command runs in it, because the lockfile carries the project's id. A moved directory is followed the same way. The project's name is its directory name.

Loans

A loan is a project borrowing one revision of one skill until a due date. Loans live in the database (~/.shelf/shelf.db) on your machine. Each loan has:

FieldMeaning
revisionThe revision the project holds (its base).
targetsThe directories the skill is copied into.
due dateWhen the loan expires unless renewed.
last usedThe last time an agent was seen using the skill in this project.
keptKept loans never come due.
policypinned or follow.
modecopy or link.

Borrow creates a loan and writes the copies. Return removes the copies and closes the loan. Detach closes the loan but leaves the files, which then belong to the project.

Targets and harnesses

A harness is a coding agent that reads skills: Claude Code, Codex, Cursor and so on. A target is a project-relative directory that skills are copied into, such as .claude/skills.

The default targets are .agents/skills (the cross-harness convention, read by Codex, Cursor, Gemini CLI, Copilot, OpenCode, Amp, Goose, Cline and others) and .claude/skills (Claude Code). A project can add directories for harnesses that read neither, such as Kiro, with shelf targets --add kiro. See Harnesses.

ModeWhat is written
copy (default)A full copy of the skill in every target.
linkOne real copy in the first target; the others are relative symlinks to it (junctions on Windows).

Copies are the default because symlinked skills are unreliable in some harnesses and across the WSL/Windows boundary. Choose link mode per loan with shelf borrow --link, or for every new loan with "mode": "link" in the config. Hashes follow symlinks, so content states work the same in both modes.

Due dates and loan length

Every loan that isn't kept has a due date. A skill's loan length decides how far out it is set:

  • the skill's own loan length, set with shelf loan-days <name> <days> (a setting of your library on this machine), else
  • loanDays from the config (30 by default),
  • never more than maxLoanDays (90 by default).
EventNew due date
shelf borrowNow plus --days, or the loan length.
An agent uses the skillNow plus the loan length, if that is later than the current due date.
shelf renewNow plus --days, or the loan length, if that is later than the current due date.
shelf due <name> +14dThe current due date shifted by the amount.
shelf due <name> 2026-12-01The end of that day, UTC.

No command sets a due date more than maxLoanDays from now; trying fails with LOAN_LIMIT.

Due states

StateMeaning
activeMore than dueSoonDays (7 by default) days left, or kept.
due-soonDue within dueSoonDays days. With hooks installed, this means the skill has gone unused for a while.
overdueThe due date has passed.

Renew on use

Loans renew when they are used, so a due date really means "unused for a loan period". Hooks installed by shelf setup recognise a borrowed skill being used in Claude Code and Codex (the Skill tool naming it, a tool reading a file inside its copy, or a prompt invoking /name) and record the use. In harnesses without hooks, agents run shelf used <name> after using a skill.

A use is written at most once an hour per loan, and appears in the activity log at most once a day.

Expiry

An overdue loan is returned automatically by the next shelf status, shelf sync or shelf sweep in its project, or the next session start (the session-start hook runs a sync). The copies are deleted and the loan is closed.

shelf never deletes local edits. An overdue loan whose copy is modified or diverged stays, and the next steps tell you to promote or detach it.

Keep

A kept loan never comes due. Its due state is always active, nothing expires it, and uses are still recorded. Keep a skill with shelf keep <name> or borrow it with shelf borrow <name> --keep; stop with shelf keep <name> --off. A loan that stops being kept gets at least a fresh loan period.

Keeping is a project decision, so it is written to the lockfile ("keep": true) and every clone keeps the same skills. Kept skills load into every session forever, so keep only what the project is built on: Convex skills in a Convex app, the API design skill in an API service. Agents follow the same rule.

Policy: pinned or follow

PolicyWhen the library has a newer revision
pinned (default)The loan is behind until someone runs shelf update (or shelf propagate from the library side).
followshelf sync, shelf sweep and the session-start hook update it automatically, as long as the copy has no local edits.

Choose follow with shelf borrow <name> --follow.

Content states

Each loan's content state compares three hashes: the revision the project borrowed (base), the library's latest revision (head) and each copy on disk (working).

StateMeaningWhat to do
currentEvery copy matches the borrowed revision, which is the latest.Nothing.
behindThe copies are unedited, but the library has a newer revision.shelf update <name>
modifiedA copy was edited in the project; the library hasn't changed.shelf promote <name> to publish, shelf detach <name> to keep the edits unmanaged, or shelf update <name> --force to discard them.
divergedA copy was edited, and the library has changed too.Review with shelf diff, then shelf promote <name> --force or shelf update <name> --force.
missingSome copies were deleted and the remaining ones are unedited.shelf sync restores them.

Edits take precedence over missing copies: a loan with one edited copy and one deleted copy is modified, so restoring can never overwrite edits. Every operation that would discard edits (return, update, promote over a newer library revision, expiry, removing a target) refuses unless forced.

The lockfile

.agents/shelf.lock.json records which skills shelf manages in the project, at which revision, in which directories, and whether they are kept. It has no timestamps, so renewing a loan never changes it and committing it causes no merge churn. Commit it; never edit it by hand. See Lockfile.

Sets

A set is a named group of library skills, such as frontend for react-best-practices, playwright-testing and accessibility-audit. shelf borrow @frontend borrows every skill in it. Each skill still gets its own loan, due date and lockfile entry; nothing about the set reaches the project. Sets live in your database, per machine. See Sets.

Actors and the activity log

Every change is recorded in the activity log with its actor: who did it.

ActorWhen
userYou, at a terminal.
user:dashboardYou, in shelf ui.
agent:claude-code, agent:codexCommands run inside those harnesses, and their hooks.
agent:<name>Other harnesses that set AI_AGENT.
anythingSet with --actor or SHELF_ACTOR.
unknownNot a terminal and no harness detected (for example a cron job).

The dashboard's Activity page shows the log as a timeline. Agents are restricted in one place: they may not import skills from remote sources unless you allow it. See Environment for how the actor is detected and Importing skills for the rule.