← All Projects

MapKit: A Measured AGENTS.md Navigation Map for Claude Code

An agent editing an unfamiliar large repo spends most of its context budget locating the code before it can change a line. MapKit scaffolds a per-folder AGENTS.md navigation map, writes the interop shim Claude Code actually needs, keeps the map current after every edit, and ships a token-accounting harness that proves the payoff. On its own worked sample repo across 8 stated edits, the map roughly halves the context loaded per edit: 2.1x fewer tokens (53 percent less) with the exact tiktoken counter, cross-checked at 2.3x with a dependency-free heuristic. It is an honest integration-and-measurement build on the upstream DOX pattern, not a new invention, with zero infrastructure and no model SDK.

2.1x fewer context tokens per edit (53% less), 8 stated edits
22,696 to 10,677 tokens across the edit set
Two counters agree: 2.1x exact, 2.3x heuristic
Zero infrastructure, no database, no model SDK
Claude Code Python uv Pydantic Markdown tiktoken pytest

Overview#

An AI agent turned loose on a large, unfamiliar repository spends most of its context budget before it does any work. It rummages: it opens files to find where things live, drags irrelevant code into the window, and only then makes the one edit it was asked to make. That orientation cost is most of the token bill, and it is a context-loading problem, not a model problem, so a better prompt does not fix it.

MapKit is our tool for fixing it structurally. It scaffolds a per-folder AGENTS.md navigation map across an existing repo, writes the import shim that Claude Code needs to see that map at all, gives the agent a traversal that reads root-to-target before an edit, keeps the map current after each edit, and ships a token-accounting harness that measures the context loaded per edit with the map versus without it. The question it answers is not how to give the agent more context. It is how to give it exactly the minimum context for the minimal edit.

Diagram of MapKit's five-step pipeline: an un-mapped repo flows through Scaffold, Shim, Traverse, Maintain, and Measure to become a self-maintaining navigation map with a measured token-per-edit reduction

Figure 1 - Five steps, one map: SCAFFOLD writes a per-folder AGENTS.md. SHIM writes the @AGENTS.md import into CLAUDE.md, because Claude Code does not read AGENTS.md natively. TRAVERSE reads the root-to-target chain before an edit. MAINTAIN keeps the nearest map current after it. MEASURE proves the payoff in tokens.

KEY INSIGHT: The expensive part of an agent editing a large repo is not writing the change, it is finding where the change goes. More context is the wrong lever. A navigation map loads only the relevant chain and keeps the agent inside its usable-attention zone.

Honest framing first#

MapKit is not a new idea, and the page says so before it says anything else. The per-folder AGENTS.md hierarchy is DOX (github.com/agent0ai/dox, by Yan and the Agent Zero team), and the scheduled git-diff-driven maintenance variant is LangChain’s OpenWiki. MapKit’s contribution is narrow and real: a zero-infrastructure, Claude-Code-native, measured implementation of that upstream pattern, with the interop shim Claude Code actually needs and a re-runnable token-per-edit benchmark. It is an integration-and-measurement project. Pitching it as an invention would sink its credibility, and the value it delivers does not depend on pretending otherwise.

The Problem#

On a large repo the agent orients by rummaging. With no map to consult, it opens the immediate source files at each level on the way to its target, works out where things are, and only then reads the file it must change. Every one of those orientation reads is context spent before a single useful token is generated, and on a deep tree with many files per folder it adds up fast.

The AGENTS.md hierarchy fixes this at the structure layer: the agent reads a short chain of folder descriptions from the root to the target, carries the parent rules forward, then reads only the file it must touch. The catch practitioners hit is that Claude Code does not read AGENTS.md natively. Confirmed against Anthropic’s memory docs, Claude Code reads CLAUDE.md; the open feature requests to read AGENTS.md remain unimplemented. So a raw DOX-style tree silently does nothing under Claude Code until the @AGENTS.md import shim is written. MapKit builds the tree, writes the shim, keeps the tree current, and proves the payoff with a number.

BeforeAfter
Agent opens source files at every level to orient before an editAgent reads a short root-to-target chain of folder descriptions, then only the target
Orientation cost is invisible and unbudgetedContext loaded per edit is measured, map vs no-map, by a named counter
A DOX-style AGENTS.md tree is inert under Claude CodeThe @AGENTS.md shim is written into CLAUDE.md so the map is actually loaded
The map decays as the repo changesPer-edit hook and batch git re-derive keep the structural index current
”It saves tokens” is an assertionA re-runnable benchmark prints the reduction on a stated repo and edit set

What We Built: Scaffold and Shim#

mapkit scaffold walks the repo and writes a root AGENTS.md plus one per folder, each carrying the folder’s domain, ownership, rules, work guidance, and an index of its child docs, from a Pydantic model. It is idempotent: re-running refreshes only the child-doc index and never clobbers hand-authored prose, so the map can be enriched freely and re-scaffolded safely.

The load-bearing step is the shim. Because Claude Code reads CLAUDE.md and not AGENTS.md, scaffold writes the documented @AGENTS.md import line into CLAUDE.md inside a marked mapkit:shim block. Without it, a scaffolded tree is inert under Claude Code. This is the one Claude-Code-specific piece, written explicitly and documented as the vendor-confirmed interop path.

KEY INSIGHT: A navigation map that Claude Code cannot see is worse than no map, because it looks like it should work. The interop shim is not a detail. It is the difference between a demo that proves something and a tree that does nothing.

The Measured Number#

MapKit is only worth shipping if the map pays for itself in tokens, so the payoff is a first-class, re-runnable fact rather than a claim. On MapKit’s own worked sample repo, examples/taskflow, a small layered task-scheduling service, across a stated set of 8 representative edits, one per leaf package, the map roughly halves the context loaded per edit: 22,696 tokens without the map against 10,677 with it, a 2.1x reduction (53 percent less) with the exact tiktoken-cl100k_base counter. A dependency-free heuristic counter independently lands at 2.3x (56 percent less) over the same edits. Both counters agree on the shape of the result.

Screenshot of MapKit's context-per-edit HTML report showing a stat band of 2.1x fewer tokens, 53 percent of context avoided, and 12,019 tokens saved, above a per-edit bar chart contrasting the red no-map baseline against the shorter teal map bars for eight edit targets

Figure 2 - The actual sign-off report: The stat band leads with the aggregate 2.1x, then a per-edit chart contrasts the no-map baseline (red) against the map (teal) for each of the 8 edits. It is a single self-contained HTML file, no external CSS, scripts, or fonts, theme-aware, so it emails and prints cleanly in a client packet. The DOX/OpenWiki credit and the honest scope travel on the same page.

The two sides of every row are named so the number is never a bare assertion. With the map, the agent loads the root-to-target AGENTS.md chain plus the target file, exactly what mapkit traverse assembles. Without the map, the baseline models a repo with no map at all: the agent opens the immediate source files along the chain to orient, then reads the target, with the map artifacts excluded so they cannot inflate the baseline. Both sides load the same target file, so the difference is purely orientation cost, measured by the same counter.

Diagram contrasting two ways an agent orients before editing a deep target file: on the left, a no-map agent opens several full source files at each folder to rummage; on the right, a mapped agent reads a short chain of AGENTS.md folder descriptions then only the target

Figure 3 - Where the tokens go: The no-map agent opens whole source files at each level to figure out where things are. The mapped agent reads a short chain of folder descriptions and then only the file it must change. Same target, same counter; the gap is orientation.

What We Built: Maintain#

An un-maintained map decays into a misleading one, which is DOX’s known weak point and the reason OpenWiki exists. MapKit keeps the structural map current two ways. Per-edit, a Claude Code PostToolUse hook runs mapkit maintain after every edit, so a new or removed folder is reflected immediately. On a schedule or in CI, mapkit rederive diffs against the last-mapped commit, recorded in .mapkit/state.json, and refreshes only the affected folders. Because rederive is idempotent, a non-empty diff after running it is a drift signal: the structural map had fallen behind and was just corrected.

Diagram of MapKit's two maintenance paths keeping the structural map current: a per-edit PostToolUse hook that refreshes the nearest AGENTS.md after each edit, and a batch git re-derive that diffs against the last-mapped commit to refresh only the changed folders

Figure 4 - Two ways to stay current: The per-edit hook refreshes the nearest AGENTS.md immediately after an edit, the low-friction default for repos worked in daily. The batch re-derive diffs against the last-mapped commit and refreshes only the changed folders, the scheduled or CI option. Both keep the structural index honest; the prose is reviewed like a docstring.

What It Does Not Do#

These caveats travel with every client-facing deliverable, because they are the difference between a defensible report and an overstated one.

Screenshot of the MapKit report's detail region: a per-edit table listing eight edit targets with no-map, map, and reduction columns totalling 22,696 to 10,677 tokens at 2.1x, above an honest-scope list stating the number is scoped to this repo and edit set, the shim is load-bearing, and the upstream Graphify figure is not this project's claim

Figure 5 - The honesty travels on the page: The same self-contained report carries the full per-edit table and an explicit honest-scope block. The number is scoped to the stated repo and edit set, the shim is called load-bearing, and the upstream vendor headline is named as a different tool’s claim, not MapKit’s. The caveats are not a footnote; they are part of the deliverable.

  • This is integration and measurement, not authorship. DOX and OpenWiki define the pattern upstream. MapKit’s contribution is the zero-infra, Claude-Code-native, measured implementation with the interop shim. The credit is in the README, on the report, and here.
  • The token number is scoped, not universal. It is measured on the stated sample repo and the stated 8 edits, with the counter named. It does not generalize to “N percent on any repo.” The benefit grows with repo size and edit locality and shrinks on a small or flat repo, or when the map is left as placeholder prose.
  • The shim is load-bearing. Under Claude Code the map is inert until the @AGENTS.md import is written into CLAUDE.md. A bare AGENTS.md tree proves nothing under Claude Code.
  • Only the structural map is auto-maintained. The hook and rederive keep the folder tree and child-doc index current. The Domain, Owner, and Rules prose still needs a human or the agent to keep it honest when a folder’s meaning changes.
  • It is not a code graph. MapKit is the prose semantic map (“who owns this and why”), zero-infra, plain Markdown. It is deliberately not the parsed structural graph (“who calls what”) that a tree-sitter-into-a-database tool provides.

KEY INSIGHT: A borrowed vendor headline is not a measurement of your workload. Graphify’s upstream “up to 71.5x fewer tokens” is a different tool’s self-reported number, not this project’s claim. MapKit publishes its own measured reduction on its own sample, and names the counter that produced it.

Platform Portability#

Zero-infra and mostly portable by construction. The map is plain Markdown, and the scaffold, traverse, and measurement core is a plain Python library with no database, server, or model SDK. The AGENTS.md convention is read by multiple agents, so the map itself is cross-tool. The one Claude-Code-specific piece is the CLAUDE.md import shim, which MapKit writes explicitly and documents as the interop path. The Claude Code skill pair and the PostToolUse maintenance hook ship as optional adapters that add no runtime dependency to the core, so the library form (scaffold, traverse, measure on any repo) stands on its own.

As a Consulting Engagement#

MapKit is the navigation instrument in our Agent Harness Maintenance playbook. The engagement makes a client’s codebase legible to AI agents: scaffold the map, author the prose for the folders that matter, wire the interop shim and the maintenance hook, and hand back a dated, per-client HTML report that leads with the client’s own measured token-per-edit reduction. The report generator drives the same harness over the client repo and writes a self-contained <date> - <client>.html file, so engagements stay traceable and the number is reproducible on their own code, never a borrowed figure.

It sits alongside its sibling tools as one suite: TraceKit measures the token bill and grades the trajectory, ContextLedger cuts the bill, RubricGate grades the final artifact, and MapKit cuts the orientation cost so the agent loads the minimum context for the minimal edit. MapKit pairs most closely with FlywheelKit in the harness-maintenance story: FlywheelKit keeps the harness’s skills and wiki current, MapKit keeps its navigation map current.

Technologies#

LayerTechnology
RuntimePython 3.11+, uv
Map modelpydantic model of the per-folder AGENTS.md (domain, ownership, rules, child-doc index)
MediumPlain Markdown, no database and no server
Interop@AGENTS.md import shim written into CLAUDE.md (the vendor-confirmed Claude Code path)
Token countingPluggable counter: dependency-free heuristic in the core, optional tiktoken extra for exact counts
MaintenancePer-edit PostToolUse hook and a git-diff batch rederive against the last-mapped commit
Measurementpytest benchmark marker, context-per-edit harness, self-contained HTML sign-off report
AdaptersClaude Code bootstrap and traverse skills, maintenance hook (no runtime dependency on the core)

The throughline: the agent’s biggest hidden cost on a large repo is orientation, not generation. MapKit gives it a plain-Markdown map, wires the interop Claude Code actually needs, keeps the map current, and prints the token-per-edit number that proves it pays off.

Have a project like this in mind?

That is the kind of work we do at Dotzlaw Consulting. Book a free 20-minute intro call and tell us what you are trying to build, or what is slowing you down.

← Back to Projects