shelf Docs
On this page
shelf borrow <skill>... [options]
ArgumentDescription
<skill>...One or more skill names, or @<set> for every skill in a set
OptionTypeDefaultDescription
--days <days>stringthe skill's loan length, else config loanDaysLoan length in days
--keepbooleanNever expire: for skills covering a direct dependency of the project (kept skills load in every session)
--followbooleanLet shelf sync apply library updates automatically
--linkbooleanOne copy per project; other harness directories symlink to it

Also takes the global options --json and --actor (CLI overview).

What it does

  1. Expands @set arguments into their skills and checks every name before touching the project, so one bad name changes nothing.
  2. For each skill not yet borrowed, copies its latest revision from the object store into every target directory of the project (.agents/skills and .claude/skills by default; see shelf targets).
  3. Records the loan: the revision, the targets, the policy, the mode, and a due date of --days or the skill's loan length from now.
  4. Rewrites the lockfile.
OptionEffect
--days NLoan length in days. Default: the skill's loan length (shelf loan-days), else loanDays (30). At most maxLoanDays (90).
--keepThe loan never expires. Also applies to skills that are already borrowed. Agents keep only skills covering a direct dependency of the project.
--followPolicy follow: shelf sync, shelf sweep and session starts apply library updates automatically.
--linkMode link: one real copy in the first target, symlinks (junctions on Windows) in the others. Default: the config's mode.

Existing directories

shelf never writes into a skill directory it doesn't manage. If a target already holds a directory with the skill's name and different content, borrow fails with CONFLICT and nothing is written. Adopt the existing copy instead (shelf adopt <path>), or move it away. A leftover copy identical to the revision being borrowed (from an interrupted borrow) is taken over.

Examples

terminal
shelf borrow pdf-tools api-design
Borrowed pdf-tools (due 2026-11-06) → .agents/skills, .claude/skills
Borrowed api-design (due 2026-11-06) → .agents/skills, .claude/skills

shelf borrow @frontend
Borrowed playwright-testing (due 2026-11-06) → .agents/skills, .claude/skills
Borrowed react-best-practices (due 2026-11-06) → .agents/skills, .claude/skills

shelf borrow pdf-tools
pdf-tools is already borrowed (due 2026-12-06)

Kept loans print kept, never expires instead of the due date.

JSON output

json
{"schemaVersion":1,"ok":true,"data":{"skills":[{"skill":"pdf-tools","status":"borrowed","revision":"sha256:dca5f929e749b602869f964b944ab1c8567353094f413d0f53dabe7dfa015b67","dueAt":"2026-11-06T05:51:38.125Z","targets":[".agents/skills",".claude/skills"],"mode":"copy","kept":false}]}}
FieldMeaning
skills[].statusborrowed, or already-borrowed (then the other fields describe the existing loan).
skills[].revisionThe revision the project holds.
skills[].dueAtThe due date.
skills[].targetsWhere the copies are.
skills[].modecopy or link.
skills[].keptWhether the loan never expires.

Errors

CodeWhen
NOT_INITIALIZEDNot inside a shelf project (run shelf init).
INVALID_ARGUMENTAn invalid skill name; --days not a positive integer; a set with no skills.
SKILL_NOT_FOUNDA skill isn't in the library, or a set doesn't exist.
LOAN_LIMIT--days is more than maxLoanDays.
CONFLICTA target already has an unmanaged directory with the skill's name.
terminal
shelf borrow pdf-tools
error: No shelf project at /home/me/code/storefront
hint: Run `shelf init` in the project root