docspack v1.5.0
Documentation

Connecting an agent

There are two ways to give an agent the documentation. The command line is the simpler one and works everywhere; MCP is there for clients that prefer a declared tool.

Any agent that can run a shell command can use docspack:

bash
npx docspack ask "how do I verify a webhook signature"

Tell the agent the command exists, with one line in AGENTS.md or CLAUDE.md. One command writes it for you, into whichever of those files the project already has:

bash
npx docspack agent install
md
Run `npx docspack ask "<question>"` for documentation on this project's dependencies.
It answers from the installed versions.

That is the whole setup. There is no server to configure, nothing per-agent, and nothing resident when nobody is asking. It works in Claude Code, Cursor, Codex, Aider, a shell script, or a CI job, including agents that do not speak MCP at all.

ask prints exactly what the MCP tool returns: the best-ranked chunks with their package, version and file, bounded by the same token budget. The two interfaces are the same code path, so neither is second class.

Writing the wiring, and keeping it current

docspack agent install writes a block delimited by <!-- docspack:start --> and <!-- docspack:end -->. Everything outside the markers is left exactly as it was, and re-running rewrites the block in place rather than appending a second copy — so a repository wired a year ago gets the current text by running the command again.

It writes more than the block when the project has somewhere to put it:

FlagWhat it writes
(default)the block in AGENTS.md or CLAUDE.md, whichever exists
(default, with .claude/).claude/skills/docspack/SKILL.md, a skill whose body loads only when it is used
--feedbackthe reporting block below, as well
--hooksa SessionStart hook that runs docspack sync, so the index follows the lockfile
--mcpthe MCP server in .mcp.json
--recipe repo, --recipe factorya way of working on top — see Recipes
--dry-runnothing; prints the plan
bash
npx docspack agent check

check writes nothing and exits non-zero when the wiring is missing or out of date. It needs no flags: it reads back which of those surfaces the project chose and compares them against what this version would write, so it belongs in CI. A pasted instruction that has drifted from what the tool does is otherwise something nobody ever notices.

check also prints what each instruction file costs: an agent sends CLAUDE.md or AGENTS.md again on every turn, so the size is paid once per turn. Over 1,000 tokens it names the file’s three largest sections, which are usually reference material that would cost nothing in docs/ until an agent searched for it. See Setting up an agent to spend fewer tokens.

Every command the block and the skills tell an agent to run starts with npx. An agent’s shell does not have node_modules/.bin on its PATH, so a bare docspack would fail in a project that installed it as a dev dependency, and the agent would spend a turn finding out why. The hooks use npx --no-install, so they do nothing, silently, where docspack is not installed.

Recipes: a way of working

A recipe is everything above plus the instructions and layout for one way of working with agents. The default, deps, is what agent install has always written. factory is for autonomous sessions in ephemeral containers — a “dark factory”, where the repository is the only state that survives:

bash
npx docspack agent install --recipe factory
WhatKindPurpose
the block in AGENTS.md / CLAUDE.mdmanagedthe rules every session needs: which milestone is yours, recall before deciding, propose lessons, never edit approved knowledge
.claude/skills/docspack-factory/SKILL.mdmanagedthe procedure: milestones, CI incidents, lessons, governor sessions
.claude/settings.jsonmanagedSessionStart runs docspack sync, then docspack index --from .factory/knowledge
.factory/README.md, .factory/templates/*seededthe layout, and templates for a milestone, an incident and a lesson
.factory/plan/, knowledge/, inbox/seededone file per item, so parallel branches do not conflict

Managed files are rewritten on every install and checked by agent check. Seeded files are written once, when absent, and never again: they are the project’s to fill in, and filling one in is not drift. The recipe is recorded in the start marker (<!-- docspack:start recipe=factory -->), so agent check still needs no flags.

A milestone is a file in .factory/plan/ whose frontmatter carries status and branch; an agent finds its assignment with Grep and reads only that file. Only .factory/knowledge/ is indexed, and lessons reach it when a person moves them out of .factory/inbox/ in review — an agent-written rule becomes something every later session trusts, so a human decides.

Finding things in an ordinary repository

repo is for everyday work in a repository with lots of docs and lots of code. It gives the agent a search over the repository’s docs and code, and asks it to use fewer, larger tool calls:

bash
pnpm add -D docspack          # the hooks run the project's own install
mkdir -p .claude              # with Claude Code: where the skills and the hooks go
npx docspack agent install --recipe repo
npx docspack index --repo     # once; after that the SessionStart hook rebuilds it
WhatKindPurpose
the block in AGENTS.md / CLAUDE.mdmanagedask recall --name repo-code where something lives, and --name repo-docs what the docs say, then read only that range; and read, search and edit in fewer, larger tool calls
.claude/skills/docspack-repo/SKILL.mdmanagedhow to read an answer, when grep is better, and what to do when the index is out of date
.claude/settings.jsonmanagedSessionStart runs docspack sync, then docspack index --repo

The fewer-calls part of the block is what saves tokens: over 780 Claude Code sessions it cut the cost of feature-sized tasks by 24%, and saved little on short ones. The index finds things but did not measurably lower a session’s cost on its own. Setting up an agent to spend fewer tokens has the numbers and the block to paste by hand.

The index is described in Indexing your own sources. Without Claude Code nothing builds it when a session starts, so the block also tells the agent to run docspack index --repo when recall finds nothing indexed.

Letting an agent report a problem

An agent reading documentation is unusually well placed to notice it is wrong. Add a second block to AGENTS.md if you want it to write those observations down:

md
If the documentation is wrong, record it: `npx docspack feedback add --chunk <id>
--kind <drift|incorrect|missing> --evidence "<claim>"`. The chunk id is the
heading above each answer. Only claims that can be shown false; incorrect and
missing also need --expected, --actual and --repro. It writes to a local file
for a human to review, and sends nothing.

The chunk id is the ## @acme/docspack@1.4.0/webhooks heading printed above every answer, so an agent already has what --chunk needs without another query.

The last sentence is the one that matters. An agent that thinks it is filing an issue behaves differently from one that knows it is appending to a file a human will read, and only the second is true. See the chunk on trust and safety for what add refuses and why.

This block is deliberately separate. Reading documentation and reporting on it are two decisions, and a team that only wants the first pastes only the first.

What a query costs

A query spawns a process, which sounds expensive and is not: about 101 milliseconds, of which roughly 41 is Node itself starting. That is invisible next to the seconds a model spends thinking, and it is only paid when a question is actually asked.

Commands that need heavier machinery load it when they run, not at startup. Importing the whole library costs about 263 milliseconds, against about 16 for the query path alone, so ask imports only what it needs.

MCP, for clients that prefer a tool

bash
claude mcp add docspack -- npx -y docspack mcp

Or, for Cursor and other clients that read a JSON configuration:

json
{
  "mcpServers": {
    "docspack": { "command": "npx", "args": ["-y", "docspack", "mcp"] }
  }
}

The server exposes two tools. query_local_docs takes a free-text query and an optional packageFilter, and returns text identical to docspack ask. record_docs_problem is the MCP equivalent of docspack feedback add, taking chunkId, kind, evidence and — for anything but drift — expected, actual and repro. The server speaks the protocol on stdout and writes diagnostics to stderr.

record_docs_problem is the only tool that writes anything, and what it writes is a line in a local file. It cannot reach a maintainer: docspack has no code that can send a report, over MCP or otherwise. Its description says so, because a model that believes it is filing an issue behaves differently from one that knows a human reads the file first.

Every rule is enforced in one place, so MCP is not a looser way in than the command line. A kind outside drift, incorrect and missing is refused by the schema; an incorrect finding without a reproduction is refused by the same check the CLI uses; a chunk that is not installed is refused before anything is written. When a call is refused, the reason comes back naming the field that was missing, so an agent can correct itself instead of guessing.

The trade is real in both directions. A declared tool advertises itself: the agent sees the name, the schema and the description, and knows when to reach for it without being told. In exchange, the tool definition occupies the context window for the whole session whether or not it is used, the server process stays resident, and every client configures MCP differently.

Choose MCP when you want the agent to discover the capability by itself. Choose the command line when you want zero setup and nothing running in the background — which is most of the time.

How results are scoped

Both interfaces read the package.json of the directory they run in, and restrict results to the package versions that project installed.

This matters because the index is shared. Another project on the same machine may have indexed a different major version of the same library. That version is in the database, but it is invisible to this project’s queries. An agent cannot accidentally answer from documentation for a version you are not running.

How much context a query returns

Agents over-fetch. Left alone, a retrieval tool will happily return more than the model can use and crowd out the rest of the conversation.

docspack bounds every response, over MCP and on the command line alike. It returns the three best-ranked chunks by default and stops adding chunks once the response would exceed 3,000 tokens, using the token count recorded for each chunk rather than measuring after the fact. A single chunk larger than the budget is still returned, so a query never comes back empty because of the limit.

The same ranking docspack search uses, over the same 15 documents.