---
title: "Get a single library entry"
method: GET
path: "/api/v1/library/{owner}/{name}"
tags: ["Library"]
---

# Get a single library entry

`GET /api/v1/library/{owner}/{name}`

## Request

- Base URL: `https://skillrepo.dev`
- URL: `https://skillrepo.dev/api/v1/library/{owner}/{name}`
- Auth: HTTP bearer

Returns one skill from the authenticated account's library. Includes own private skills and skills added from the catalog via `POST /api/v1/library/refs`.

**Status codes:**
- `200` — skill is past safety analysis and ready to consume.
- `202` — caller owns a skill whose safety analysis is still running (RFC 9110 §15.3.3). Retry after the interval in `Retry-After`. Non-owners do not get this response.
- `404` — skill not in the caller's library and not owned by the caller, OR a moderation/visibility filter applied. Single message across all 404 paths to avoid leaking skill existence to other accounts.

**Cache-Control:**
- `no-store` on 202.
- `private, no-store` on 200 when `skill.filesIncomplete` is true.
- `private, max-age=0, must-revalidate` on complete 200 — limits storage to the caller's own browser cache and forces revalidation on every request.

Rate-limit bucket: `cli-crud` (60/min per key).

## Path parameters

- `owner` string, required
- `name` string, required

## Response `200`

Skill found and past safety analysis.

- LibraryEntryGetResponse: Single library entry. `skill` is the SAME SyncSkill shape returned inside the `skills` array of `GET /api/v1/library` — clients can reuse their sync-parsing code.
  - `skill` SyncSkill, required: Per-skill shape shared by bulk library sync and single-skill GET. Content is byte-identical across endpoints; the optional `governance` field rides only the manifest/scoped read paths.
    - `owner` string, required
    - `ownerName` string, required
    - `name` string, required
    - `version` string, nullable, required
    - `description` string, required
    - `keywords` string[], required: Single-word keywords extracted from the skill's `triggers` (stop-words removed, lowercased) for client-side indexing.
    - `updatedAt` string, date-time, required
    - `etag` string, required: Per-skill ETag of the form `"owner/name@<timestamp>"`. Used by clients for conditional re-fetching; the bulk sync response also sets an HTTP-level `ETag` covering the whole response.
    - `contextSignals` ContextSignals, nullable, required: Context-signals object attached to a skill by the analysis pipeline. Open-shaped — clients should pass through to UI without strict validation. Null when analysis has not yet run.
    - `files` SyncFile[], required
      - `path` string, required: File path relative to the skill root.
      - `content` string, required: Inlined file contents. UTF-8 when `encoding: utf-8`; base64 of the raw bytes when `encoding: base64`.
      - `sha256` string, required: Hex-encoded SHA-256 of the raw file bytes. Empty string for the synthesized SKILL.md entry (clients use the version-level `etag` for freshness there).
      - `contentType` string, required: MIME type. Text content types are inlined as UTF-8; everything else as base64.
      - `size` integer, required: File size in bytes (pre-base64-encoding).
      - `encoding` 'utf-8' | 'base64', required: How `content` is encoded. `utf-8` for text types, `base64` for binary.
    - `filesIncomplete` boolean, required: True when one or more blob-backed files failed to inline and were dropped from `files`. When true, the route SUPPRESSES the response-level HTTP `ETag` header and sets `Cache-Control: private, no-store` so clients re-fetch on the next sync instead of caching an incomplete response. On the push (POST) response this field is almost always `false` — files were just uploaded successfully, so the inline-fetch rarely fails. A `true` value here indicates a transient blob store hiccup between upload and response build; the next GET will return the complete state.
    - `governance` SyncSkillGovernance: Per-skill delivery governance carried ONLY on the non-recording read paths — the `?manifest=1` whole-library and skillset-scoped reads (`skillrepo list`). Absent on the byte-identical whole-library sync wire (D2) and the skillset-scoped sync wire, and absent entirely when the recall feature is disabled.
      - `status` 'latest' | 'serving' | 'pinned', required: Delivery status in the shared version-status vocabulary: `latest` — the served version is the publisher's head (healthy); `serving` — a recall rolled the account back to an earlier version (the served version is below head and diverted); `pinned` — a deliberate hold behind head (not a recall).
      - `head` string, nullable, required: The publisher's current head version label, for context (e.g. "vX available"). Null when the skill has no published head.
      - `recalledVersion` string, nullable: Present only when `status` is `serving`: the version that WOULD serve absent the recall — the one recalled and rolled back FROM. The version actually served is this skill's own `version`.

## Other responses

- `202`: Skill exists and is owned by the caller, but safety analysis has not yet completed. Poll this URL using `Retry-After`.
- `401`: Missing or invalid authentication. For routes that require `bearerAccessKey` or `bearerCatalogKey`.
- `403`: Authenticated, but the key lacks the required scope or the account is suspended. Use `code` to distinguish: `insufficient_scope`, `account_suspended`, `plan_limit`.
- `404`: Resource does not exist, OR exists but the caller has no permission to see it. Private resources return 404 (never 403) to avoid leaking existence.
- `429`: Rate limit exceeded on the route's bucket. Includes `X-RateLimit-*` headers indicating the limit, remaining, and reset time.

---

[API](https://skmtc.dev/skillrepo/apis/skillrepo-api.md) · [All operations](https://skmtc.dev/skillrepo/apis/skillrepo-api/llms.txt) · [OpenAPI document](https://skmtc.dev/skillrepo/apis/skillrepo-api/revisions/b62bac246918?raw)
