the format

The docspack package format

A documentation package is an ordinary npm package whose payload is Markdown. Everything a publisher writes and a consumer reads is on this page; the machine-readable form is /schema/v1.json, which is what $schema in every generated manifest points at.

docspack build writes all of this for you. The format is documented because a package is publishable without the CLI, and because a consumer other than docspack should be able to read one.

Naming

Two name shapes are discoverable, and discovery is a pure name check against package.json — no registry call, no manifest fetch, nothing that can fail while offline.

  • @vendor/docspack — published by whoever owns the scope. Trusted: its content is presented to an agent as documentation.
  • @docspack-community/<name> — published by anyone. Every answer drawn from one is labelled (community) and marked untrusted data.

One pack per npm scope is deliberate, and it is the constraint to design a package layout around. It is what makes @vendor/docspack derivable from a dependency's own name, so a project's documentation set is a function of its package.json alone. A vendor shipping two unrelated products under one scope documents both in one pack, or publishes the second under a scope of its own.

Layout

.llms/ is the payload and must be listed in the package's files. Omitting it publishes a package that installs cleanly and indexes nothing — docspack doctor treats that as an error.

@vendor/docspack/
├── package.json      name, version, and the docspack build settings
├── llms.txt          human-readable table of contents
└── .llms/
    ├── manifest.json every chunk, its file, size, tags and entities
    └── chunks/
        ├── overview.md
        └── webhooks-signing.md

manifest.json

The one file a consumer must read. It is the whole index of the package: a reader budgets a response from tokens before opening a single chunk file.

FieldTypeMeaning
name string required npm package name, e.g. @stripe/docspack.
version string required Must match the version in package.json.
chunks array required Every retrievable unit of documentation in the package.

Each entry in chunks

FieldTypeMeaning
id string required Unique within the package; used to build the chunk_id in the index.
file string required Path relative to .llms/. Must not escape that directory.
tokens integer Approximate token count, used to budget a response. Estimated when absent.
tags array Search terms indexed alongside the content.
entities array Identifiers the chunk documents, e.g. Stripe.setApiKey.
{
  "$schema": "https://docspack.dev/schema/v1.json",
  "name": "@acme/docspack",
  "version": "1.4.0",
  "chunks": [
    {
      "id": "webhooks-signing",
      "file": "chunks/webhooks-signing.md",
      "tokens": 412,
      "tags": ["webhooks", "signature", "security"],
      "entities": ["client.verifySignature", "WebhookEvent"]
    }
  ]
}

Rules a consumer enforces

  • A chunk file resolves inside .llms/ or it is refused. A manifest is third-party input, so this is a security boundary rather than a convenience check.
  • The installed package.json version wins over the manifest's when the two disagree, and the mismatch is reported.
  • Chunk ids are unique within a package and match ^[A-Za-z0-9][A-Za-z0-9._-]*$. The id an answer is headed with is <name>@<version>/<id>.
  • Unknown fields are accepted and ignored. An invented field is not an error, so it is also not a feature — nothing reads it.

Authoring controls

Front matter carries title and tags for a whole document. A single section takes its own with an HTML comment under the heading, which is what to reach for when one page holds eighty of them:

## Two-column layout

<!-- docspack: tags=grid,columns -->
<!-- docspack: entities=TwoColumn -->

Tags are weighted above prose in the ranking, so they are the lever that aims one chunk at one question.

Next