# Setting up an agent to spend fewer tokens

This page is about the cost of an agent session, and what to put in `CLAUDE.md` or `AGENTS.md`
to lower it. Every figure on it comes from Claude Code sessions run by docspack's benchmark,
1,100 of them, on Vite and on docspack's own repository. The method and every result are in
`docs/design/repo-index.md` and `docs/design/compact-output.md` in the docspack repository.

## What an agent session spends its tokens on

A session is a series of turns. Each turn sends the whole conversation to the model again: the
system prompt, the tool definitions, `CLAUDE.md`, and every message and tool result so far. So a
session costs roughly its number of turns times the size of its context.

| Task size | Turns | Share of input that is the same base, sent again |
| --- | --- | --- |
| Find where something is | 3–4 | 95% |
| Change a behaviour | 7–8 | 88% |
| Build a small feature | 19–20 | 53% |

The base was about 18,000 tokens per turn, and about 16,000 of that is Claude Code's own system
prompt and tool definitions. What the agent writes was under 1% of all tokens, but output is
priced at five times input, and the resent base is mostly read from the cache at a tenth of it. So
the agent's output was 12% of the cost of a short task and 25% of a long one. Most of that output
is reasoning, commands and edits. The agent's prose was about a tenth of it. Two things follow:

- **Fewer turns save the most.** Every turn pays for the whole base again, and fewer turns also
  meant less output: 3,800 tokens a feature session instead of 5,200.
- **Every line of `CLAUDE.md` is paid for on every turn.** A 2,200-token `CLAUDE.md` costs about
  44,000 tokens over a 20-turn session.

## The CLAUDE.md block for fewer tool calls

Paste this into `CLAUDE.md` or `AGENTS.md`. `docspack agent install --recipe repo` writes it for
you, inside its managed block:

```md
## Working efficiently in this repository

Every tool call is a turn, and every turn resends the whole conversation. Use fewer, larger calls:

- Read several files, or several ranges of one file, in one shell command
  (`sed -n '40,90p' a.ts; sed -n '1,60p' b.ts`) instead of one Read per file.
- Search once, with a pattern that covers everything you are looking for.
- Make related edits together, and run the tests once the change is complete.
```

Keep the wording. It is the exact text that was measured, and the measurement below applies to
it, not to a rewrite.

## What the block saves, and where it saves nothing

Measured over 780 Claude Code sessions, 10 per task, against the same repositories with nothing
added to `CLAUDE.md`:

| Task | Tokens used | Cost | Turns | Tasks passed |
| --- | --- | --- | --- | --- |
| Build a small feature (7 tasks) | 79% | 76% | 19.2 → 9.5 | 70/70 both |
| Change a behaviour (16 tasks) | 89% | 93% | 7.7 → 6.3 | 158/160 both |
| Find where something is (16 tasks) | 101% | 99% | 3.7 → 3.4 | 148/160 both |

The block is worth about a quarter of the cost of a long task, and almost nothing on a short one.
A three-turn session has few turns to save. It never cost a task its pass. The agent did read
and edit through the shell instead of the Read and Edit tools, so its edits arrive as scripts,
which are harder to review than one Edit call at a time.

## Keeping CLAUDE.md short

Everything in `CLAUDE.md` is sent on every turn, whether the task needs it or not. Reference
material, such as how the release works or what each package does, is better kept in the
repository's docs. There it costs nothing until the agent asks for it:

```bash
docspack index --repo
docspack recall --name repo-docs "how does a release work"
```

Keep in `CLAUDE.md` what applies to every task: the commands to build, test and lint, and the
rules the agent must not break. Move the rest into `docs/`, under headings in the words someone
would search for.

`docspack agent check` prints what each instruction file costs per turn. Over 1,000 tokens, it
also lists the three largest sections, which are where reference material usually sits:

```
CLAUDE.md ~1555 tokens, sent again on every turn: ~31100 over a 20-turn session
  ~573  ## Part 3 — TypeScript Monorepo
  ~455  ## Part 1 — Behavioral Guidelines
  ~453  ## Part 2 — General Coding Quality
```

The count is an estimate at four characters a token. Markdown that is mostly code and commands
tokenizes more densely: one `CLAUDE.md` estimated at about 1,500 tokens added 2,238 to every call.

A pointer line such as "read `docs/schema.md` only when working on migrations" also costs tokens
on every turn, one line per document. With the docs indexed, the agent can search them, and the
pointer lines are not needed.

## Finding things without reading whole files

`docspack index --repo` builds two indexes of the repository: `repo-docs`, its Markdown, and
`repo-code`, a map of its code with one entry per declaration. A `repo-code` answer gives the
`file:line`, the signature and the doc comment. A three-entry answer is about 200 tokens.

```bash
docspack recall --name repo-code "where is the socket that pushes updates to the browser created" --limit 1
```

```
## packages/vite/src/node/server/ws.ts:118 createWebSocketServer
export function createWebSocketServer(
```

The index is for finding things. It does not lower a session's cost on its own. With Claude
Code, an agent that searched with Grep and read ranges spent about the same as one that asked the
index, because Grep returns matching lines, not whole files. Use it when the question names
what the code does, not what it is called. When the name is known, `grep -n` is as good.

## Answers about dependencies

`docspack ask` answers from the documentation of the versions in `node_modules`, at most 3,000
tokens per answer. That is cheaper than a web search, and the version is the one installed:

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

## What does not save tokens

These were measured and found to save little or nothing in a coding session:

- **Telling the agent to write tersely.** Its prose is about a tenth of its output, which puts
  it at 1–3% of a session's cost. Widely shared rules for this ("NEVER output pleasantries", "NO
  hedging", "Output ONLY the requested code") were measured over 140 feature sessions: the agent
  wrote 12% less prose, its output fell 2%, and the cost did not change. No task was lost either
  way. If you like terse replies, put the rules in your own `~/.claude/CLAUDE.md`, not the
  repository's: they are a matter of taste, and every collaborator pays for them on every turn.
- **Re-indenting code, or other lossless reformatting.** The tokenizer already encodes runs of
  spaces cheaply: 1,964 tokens became 1,961.
- **A code index on its own.** See the section above: it finds things, and Grep is about as cheap.

What did not lose information and did save: docspack's own answers say each location once.
That made a `recall` answer about code 70% smaller, though it is a small part of a session.

## Setting it up in a repository

```bash
pnpm add -D docspack                       # 1. a dev dependency: the hooks run this install
mkdir -p .claude                           # 2. with Claude Code: where skills and hooks go
npx docspack agent install --recipe repo   # 3. the block, two skills, two SessionStart hooks
npx docspack sync                          # 4. dependency docs, for `ask`
npx docspack index --repo                  # 5. repo-docs and repo-code, for `recall`
npx docspack agent check                   # 6. in CI: fails when the wiring drifts
```

Step 3 writes the block above and the `recall` and `ask` instructions into `CLAUDE.md` or
`AGENTS.md`. Without `.claude/` it writes only that block. With it, it also writes the skills and
a `SessionStart` hook that runs steps 4 and 5 at the start of every session, so the indexes stay
current. Commit `CLAUDE.md` and `.claude/`. The index itself is in `.docspack/`, which is
gitignored for you.

Every command the block tells the agent to run starts with `npx`, because an agent's shell does
not have `node_modules/.bin` on its PATH. That is also why docspack has to be a dev dependency:
`npx` then runs the project's own version, and the hooks, which use `npx --no-install`, find it.

`index --repo` takes the files `git ls-files` lists, tracked or new, and skips what `.gitignore`
ignores. It also skips `node_modules`, tests, fixtures, type declarations and changelogs, which
nobody asks where something lives in.

To see whether it pays in your repository, try it on a task that takes the agent a dozen turns or
more. That is where the measured saving was. On a quick lookup expect little difference.
