Browse docs

Context Budget — what coding-os costs before it saves anything

Purpose: State, per project profile and from measurement, how many tokens the always-on instruction layer occupies — so every savings claim elsewhere in the docs can be read net of what the system charges to be present. Read when: publishing a token number, adding a rule, or answering "what does this cost me". Skip when: the change touches neither the rule set nor a published benchmark.

Nav: Section Index | Docs Index

The claim this file exists to prevent

A retrieval layer that saves tokens on queries but charges a fixed toll on every turn has a net effect, not a gross one. Publishing only the gross saving is the oldest trick in benchmark writing, and it is the first thing a skeptical reader checks. This file is the toll.

What "always-on" means

Loaded on every turn regardless of what the agent does:

Layer Always-on? Why
CLAUDE.md / AGENTS.md yes the runtime injects it into every request
.claude/rules/*.md yes same
.claude/skills/** no loaded by the Skill tool, on demand, per matching glob
.claude/commands/** no loaded when the slash command is invoked
MCP tool schemas no on Claude, yes on runtimes without deferred tools Claude Code fetches schemas through ToolSearch; only names are resident
.claude/hooks/** no separate processes; never enter the model's context

Counting the skills or hooks directory toward context cost inflates the number by an order of magnitude. A scaffold writes 395–461 files depending on preset; 9 to 12 of them are ever in context (one root file, seven core rules, one per stack).

Measured budgets

Regenerate with:

uv run python src/scripts/context_budget.py                 # representative span
uv run python src/scripts/context_budget.py --all-presets   # every preset

The profiler runs the real cos init for each preset into a temp dir, then sums the characters of the root instruction file and the rules directory. Tokens are characters / 4 — the same heuristic the graph envelopes report, and it is an estimate, not a tokenizer.

Measured 2026-08-15, all 21 presets, coding-os 0.3.19:

Profile Stacks Root Core rules Stack rules Always-on total Share of a 200k window Skills on disk (lazy)
t3-style nextjs 3,238 9,266 199 12,704 6.4% 46
nuxt-fullstack vue-nuxt 3,173 9,266 286 12,726 6.4% 46
wordpress-cms wordpress 3,195 9,266 277 12,738 6.4% 46
tall laravel 3,179 9,266 320 12,765 6.4% 46
jamstack astro 3,238 9,266 328 12,833 6.4% 46
flutter-baas flutter 3,181 9,266 465 12,913 6.5% 46
rails-react rails, nextjs 3,370 9,266 346 12,982 6.5% 47
ai-saas nextjs, fastapi 3,333 9,266 414 13,014 6.5% 47
nextjs-fastapi nextjs, fastapi 3,335 9,266 414 13,016 6.5% 47
django-next django, nextjs 3,358 9,266 396 13,021 6.5% 47
mean node-express, angular 3,318 9,266 556 13,141 6.6% 47
nest-angular nestjs, angular 3,326 9,266 559 13,152 6.6% 47
go-react go-fiber, nextjs 3,350 9,266 536 13,153 6.6% 47
mern node-express, nextjs 3,355 9,266 536 13,158 6.6% 47
pern node-express, nextjs 3,355 9,266 536 13,158 6.6% 47
laravel-vue laravel, vue-nuxt 3,286 9,266 606 13,159 6.6% 47
rn-api react-native, fastapi 3,278 9,266 628 13,172 6.6% 48
dotnet-react aspnet-core, nextjs 3,394 9,266 567 13,227 6.6% 47
spring-react spring-boot, nextjs 3,380 9,266 617 13,264 6.6% 47
rust-svelte rust-axum, svelte-sveltekit 3,368 9,266 744 13,379 6.7% 47
hexagonal-product go, go-fiber, fastapi, react-native 3,534 9,266 1,171 13,972 7.0% 50

Read the spread, not an average. The whole 21-preset range is 12,704 to 13,972 tokens — 6.4% to 7.0% of a 200k window. A four-stack polyglot pays 1,268 tokens more than a single-stack CMS, because the per-stack rules are 199–1,171 tokens each and everything else is shared.

The dominant term is 9,266 tokens of stack-agnostic core rules, identical for every profile. If the always-on budget is ever to come down meaningfully, that is the only place with enough mass to matter — not the stack overlays.

Note the last column: 46 to 50 skills sit on disk and none of them are in context. A scaffold writes 395 files for t3-style and 461 for hexagonal-product; 9 to 12 enter the prompt.

This repo, for contrast

uv run python src/scripts/context_budget.py --project .
Profile Stacks Root Core rules Stack rules Always-on total Share of 200k
coding-os meta 3,986 9,779 1,868 15,634 7.8%

Why the meta-repo is not a consumer number

The meta-repo pays for four meta-* stack rules that only apply to work on the kernel (1,868 tokens), a root instruction file ~800 tokens longer than a consumer's, and model-routing.md, which ships here because the cognition module is enabled and is unlinked under the default standard profile. Net: about 2,900 tokens a consumer never sees. Any figure quoted publicly must come from the profiler's preset runs.

An earlier revision of this table published 19,977 tokens (10.0%) for this repo, and it was wrong. It counted dimension-registry.md (2,042) and skill-enforcement.md (2,448) as resident. They are not, in any install: install-adapter.sh holds both in _NON_ACTIVE_RULES and never symlinks them, because they are generated from every installed stack and SessionStart's skill_primer card already injects the installed-stack-only view. That row was the one figure in this document not produced by executing the profiler — which is why --project now exists, and why no hand-computed number belongs here.

Empirical cross-check

The estimate above is a static file measurement. The runtime figure comes from agent transcripts, where the first assistant turn of a session carries the whole resident prefix:

cos doctor --tokens --tokens-days 30

Across 132 sessions in this repo the median first-turn context was 58,446 tokens. A project with a ~6 KB instruction file measured 38,972, which puts the Claude Code floor — system prompt plus resident tool schemas, before any project instruction — near 37,000 tokens. The difference tracks the static estimate closely enough to trust the method, and it also means the honest denominator for "what fraction of my window is coding-os" is the delta, not the whole first-turn figure.

The cost that is not tokens

Prompt caching makes the dollar cost of the always-on layer small: measured over 73,898 turns in this repo, 99.1% of input tokens were cache reads, billed at a fraction of the base rate. The prefix is written once per session and read cheaply thereafter.

What caching does not buy back is instruction adherence. The published evidence is that following degrades as instruction density rises, with a bias toward instructions that appear earlier — see IFScale (20 models; even frontier models reach only 68% adherence at 500 concurrent instructions, with reasoning models showing "threshold decay": near-perfect until a critical density, then a steeper slope) and ManyIFEval.

This project has not measured its own position on that curve — model adherence under its own instruction density is still an open question. What it has measured is which rules do any mechanical work:

uv run python src/scripts/rule_audit.py

Every hook BLOCK lands in an agent transcript naming the hook script, so the count is durable and re-derivable. The script reads the resident rules — .claude/rules/, not the src/core/rules/ source tree — so a rule that ships to nobody cannot appear. Over 673 sessions in the last 180 days of this repo, 786 attributed blocks (a rolling window: the counts move, the ranking does not):

Rule Tokens Blocks Per 1k tokens Verdict
test-discipline.md 1,113 344 309.1 enforced
memory.md 1,244 148 119.0 enforced
thinking_os.md 1,141 83 72.7 enforced
git-workflow.md 2,097 129 61.5 enforced
anti-overengineering.md 1,731 79 45.6 enforced
meta-graph-first.md 643 3 4.7 enforced (warn-mode)
api-contract-discipline.md 905 0 0.0 convention
transparency-banner.md 1,035 0 0.0 convention
meta-meta-engineering.md 418 0 0.0 convention
meta-hook-author.md 411 0 0.0 convention
meta-mcp-tool-author.md 396 0 0.0 convention
model-routing.md 513 0 0.0 dormant
Total 11,647 786

A convention is not wastetransparency-banner.md and api-contract-discipline.md govern behaviour no hook can observe, and dropping them would remove the guidance without replacing it. But 3,678 tokens, 32% of this repo's rules layer, is carried entirely by the model's attention, which is the budget instruction density spends first.

A consumer's split is better than this repo's, and it is the one that should be quoted: of the 9,265 tokens of core rules a preset install receives, 7,325 (79%) are enforced by a hook that fires, and the 1,940 that are not are exactly the two rules above. Four of the five unenforced files in the table — every meta-* — reach no consumer at all.

An earlier revision of this section named two pruning candidates, dimension-registry.md and model-routing.md. Both were already resolved before it was written: the first is in _NON_ACTIVE_RULES and reaches no install, the second is owned by the cognition module and is unlinked under the default standard profile. Verify a rule is resident — ls .claude/rules/ in a real cos init — before proposing to remove it.

Rules for anyone adding to the always-on layer

  1. A new always-on rule must name what it prevents that no existing rule does.
  2. Prefer a skill (lazy, glob-scoped) over a rule (resident) whenever the guidance applies to a file type rather than to every turn.
  3. Regenerate the table in this file in the same commit as any change to src/core/rules/** or a stack's rules/.

See also

  • third-party-token-bench.md — the savings side of the ledger, and the harness that must net it against this cost.
  • test-governance.md — the same measure-before-asserting discipline applied to suite runtime.
  • src/scripts/context_budget.py — the profiler.