Borrowing it
Nothing to install: this file belongs to footprintjs/agentfootprint. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.
curl -O https://raw.githubusercontent.com/footprintjs/agentfootprint/main/CLAUDE.mdgit clone --depth 1 https://github.com/footprintjs/agentfootprintWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/instructions/footprintjs/agentfootprint/claude-md)<a href="https://agentmods.dev/instructions/footprintjs/agentfootprint/claude-md"><img src="https://agentmods.dev/badge/instructions/footprintjs/agentfootprint/claude-md.svg" alt="Measured on agentmods" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.21563 | $0.21563 |
| Opus 5 | $0.10781 | $0.10781 |
| Sonnet 5 | $0.04313 | $0.04313 |
| Haiku 4.5 | $0.02156 | $0.02156 |
Grade A, and why
agentfootprint CLAUDE.md scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 2d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
How it starts
The opening of the file, as written. The whole thing — 209 lines — stays where its author put it; the contents beside it link to each section on GitHub.
agentfootprint — feature-work map
Agent framework layered on footprintjs: every runner (Agent, LLMCall, compositions, patterns) is a footprintjs chart built ONCE at construction and executed on a fresh FlowChartExecutor per run. Engine seams (stage kinds, $-methods, engine handlers) live UPSTREAM in footprintjs and are closed here. This file maps this repo's seams and blast radius — trust the code where any doc disagrees.
Before you design it: it may already exist
Read this table before proposing any new capability. Everything below already ships. The failure it exists to stop is real and expensive: a reader searches for the words THEY would use, finds nothing, and designs a feature the library has had for releases. That has happened repeatedly — the typed-HITL ask, element bindings by role and name, and the artifact-kind renderer were each re-proposed after they shipped.
Keyed by what you would call it, not by what it is called here. If your idea is
not in this table, search src/index.ts for the nearest noun before writing code.
| If you are about to build… | It is | Where | Since |
|---|---|---|---|
| turning a written operational procedure (a runbook, a triage playbook) into ONE agent tool whose every answer is EVIDENCE — coverage folded up from the inner tools it calls, rule name+version, verdict rows with GENERATED meanings, and the recorded walk as an artifact ticket, never bytes | runbookAsTool — dials: procedure (factory, invoked per call with ctx.tools) + resultKind ('verdict/*' arms the rowset projection; anything else ships spine + the chart's report) + rules {name, version} (default absent ⇒ rule_version: 'undeclared') + verdicts {decider, maxRows} (default 50; verdict_meanings = statically declared branches + this run's rule labels + the DEFAULT branch's label, which reaches evidence only when the chart calls decide(s, rules, {branch, label}) — fp ≥9.16.1, the default is chosen by NO rule so nothing else can name it, and inside a generated fan-out branch the static walk is blind too; an undeclared or blank label stays ABSENT from the map, never invented from a branch id, and there is deliberately NO caller-supplied meanings map) + presentation ('prose' default = ship table + VERDICT_RENDER_NOTE "output it VERBATIM"; 'panel' = the HOST renders the rowset, so NO table key at all + PANEL_RENDER_NOTE "the rows are already on the reader's screen — do not reproduce them"; the rowset half is byte-identical across modes, table stays RESERVED in both, an unknown value THROWS at definition) + walk {cap, recording} (cap default 500; over-cap ⇒ control-flow projection, declared · recording: true or {label, maxBytes}, default OFF — ALSO files the inner chart's own {snapshot, events, structure} under recording/run and puts its ref on the spine as walk.recording_ref, because the ROW projection cannot be drawn; snapshot read from the REDACTED mirror so one redact means the same for both; over maxBytes (DEFAULT_RECORDING_MAX_BYTES = 5,000,000) it is REFUSED not truncated; every absence — no store / over size / unserializable / store threw — is STATED in walk.recording_note, and the four recording_* fields are absent entirely when the dial is off) + composedOf (drift-checked at agent BUILD) + kept recorders/keepRecord/keepRecordLimit/redact; reserved state keys verdicts/coverage/report (the report bag lands BESIDE the spine, never over it — a report field spelling af_coverage/af_provenance/rule_version/walk/report_note or a live projection key is discarded and NAMED in result.report_note; precedence is explicit in report.ts, never spread order); inner absent() passes through VERBATIM unless the call said allowAbsent; walk kind recording/chart-walk + walk_segment discriminant |
src/core/runbook/ |
9.76.0, recording 9.79.0 |
speaking MCP from a BROWSER — the SDK is browser-clean (its client + streamableHttp bundle at platform:'browser' with zero node: edges and never pull in client/stdio.js); the one barrier was that lazyRequire gets CALLED there, so the fix is to let the caller supply what the loader would have found |
mcpClient({ sdk }) (McpSdk = the two SDK modules you imported statically; the library STILL builds the transport, so headers/fetch/gateway vending/retryOnThrottle/_meta all keep working) · mcpClient({ connection }) (McpConnection = listTools/callTool/close, deliberately NO connect — you already did; the only arm that reaches the SDK's jsonSchemaValidator, i.e. CSP) + McpConnectionOptions; refuseConflictingOptions REFUSES at construction every option a transport would have consumed, naming where it moved (a knob naming a behaviour that no longer happens is the defect class); transportUrl resolves a relative url against globalThis.location.href (absolute takes the identical branch, Node refuses by name); sdkLoadFailure classifies the seven load sites so a browser is never told to install a package it has (resolution failure ⇒ byte-identical historical message); retryingFetch + ThrottleFetch promoted out of @internal so the connection arm keeps its 429 handling. stdio keeps lazyRequire FOREVER — it spawns a subprocess. ZERO packaging change: no subpath, no browser condition (TypeScript is blind to it), peer stays optional (no literal dynamic import()). Fenced by test/lib/mcp/browserGraph.test.ts |
src/lib/mcp/ |
9.81.0 |
calling ANOTHER registered tool from inside a tool's execute — composition over the agent's own dispatch map instead of importing the module and building a second query stack |
agentToolDispatch + ctx.tools (ToolDispatch has/call) — sees static and skill-carried tools, NEVER ToolProvider-delivered ones (no build-time list, the 9.72.0 caveat); inner calls get the outer facts with hasArtifacts false and a derived toolCallId, needs resolved fail-closed non-interactively, checkIn and wants tools refused by name, no nested dispatch; declare ingredients via composedOf (and gates for a pausing procedure) — both travel MCP _meta |
src/core/agent/toolDispatch.ts |
9.76.0 |
| a tool returning numbers WITH the caveats that make them honest — interval/aggregation grain, is-it-a-counter, when the world was measured, which ground was NOT covered — as typed data the model reads compactly and the record keeps whole | semantic() + tools.semantics_declared (model sees semanticsForModel projection; coverage field absorbed by the coverage()/absent() channel) |
src/lib/semantics/ |
9.53.0 |
| a build gate that refuses a triage/inventory tool that forgot its caveats, by tool name and field name | checkSemantics + defineTool({ resultClass }) ('triage'/'inventory', the closed set) + bin agentfootprint-check-semantics |
src/lib/semantics/check.ts |
9.53.0 |
an agent that runs out of maxIterations mid-task handing back a HALF-SENTENCE as its answer — and nothing saying the budget ran out |
wrapUpAtMaxIterations (default ON) + WRAP_UP_INSTRUCTION + agent.budget_exhausted + stoppedEarly.wrappedUp |
src/core/agent/stages/wrapUp.ts |
9.56.0 |
| the conversation outgrowing the context window — dropping, summarizing or token-budgeting old turns, every removal on the record (the three refusal rows below all guard this window) | .window() + slidingWindow / summarizeOldest (= .compaction()) / tokenBudget + keepRecentTurns (default 6) + thresholdTokens (required, deliberately no default) + retain: 'conversation' (default) / 'discard' |
src/core/agent/window/ |
7.17.0 |
| keeping the user's own request in context while the window shrinks — the task's anchor, un-droppable by every window strategy including one you wrote | 'current-request' refusal + currentRequestIndexOf + WindowStrategyInput.currentRequestIndex |
src/core/agent/window/currentRequest.ts |
9.55.0 |
| the window evicting the EVIDENCE while keeping the task — the tool result carrying the only valid ids leaves, and the model invents one that has never existed | keepLastToolResults (default 2; 0/false disables) + 'last-tool-result' refusal + toolResultPinsOf + WindowRecord.observations (what was kept, and its exact char cost) |
src/core/agent/window/lastToolResult.ts |
9.57.0 |
| telling the model WHICH tools' results a drop took, so it re-calls instead of reconstructing from memory — and filing the same fact on the record even when no notice was authored | droppedToolNames + the notice's tool sentence + WindowRecord.droppedObservations |
src/core/agent/window/toolNames.ts |
9.57.0 |
| an instruction that SAYS a run-time number rather than only gating on it ("you are on action 25 of 30") — with the library owning absence, so never "23 of undefined" and never a fabricated zero | promptTemplate + the closed TEMPLATE_FACTS vocabulary (action/actionBudget/actionsRemaining) + skipped: 'unknown-fact' + Injection.templated |
src/lib/injection-engine/promptTemplate.ts |
9.57.0 |
| an injection predicate that can see how much of the action budget is left | InjectionContext.maxIterations / .iterationsRemaining + iterationsRemainingOf (the ONE denominator, shared with the cache decision) |
src/lib/iterationBudget.ts |
9.57.0 |
report progress from inside a tool — "hop 3 of 12 done", said mid-call while a long-running execute is still working (the record was otherwise atomic: tool_start, silence, tool_end) |
ctx.progress + agentfootprint.stream.tool_progress |
src/core/tools.ts |
9.52.0 |
show tool progress to the user — a mid-call report reaching the live status line / chat bubble, not just the record (message shown verbatim, capped at 120 chars with the cut stated; otherwise an honest generic line, never a payload dump) |
selectStatus + progressMessageOf + tool.progress templates |
src/recorders/observability/status/statusTemplates.ts |
9.54.0 |
| declaring which skills connect — the SkillMap as one named thing (the agent that mounts it is the SkillWalker; there is deliberately no walker class) | defineSkillMap + SkillMap (permanent reference-equal aliases of skillGraph/SkillGraph) |
src/lib/injection-engine/skillGraph.ts |
9.51.0 |
| guarding a skill transition on state or a tool result's fields — a route condition as DATA (comparable, drawable, evidence-recorded), not an opaque predicate | guard: + compileGuard (ops 'eq'/'ne'/'gt'/'gte'/'lt'/'lte'/'in'/'notIn') + guard-unsatisfiable |
src/lib/injection-engine/skillGuard.ts |
9.51.0 |
| seeing the skill map in a recording — the author's nodes + edges (guards included) as DATA, never parsed from prose or inferred from fired hops | skill.graph_declared + buildSkillGraphDeclared |
src/core/agent/skillGraphDeclared.ts |
9.50.0 |
| "where could the run go next?" — the reachable skill set at every cursor move, typed on the move itself | cursorMove.reachable + reachableSkills |
src/lib/injection-engine/buildInjectionEngineSubflow.ts |
9.50.0 |
| putting the ASSEMBLED system prompt in the recording — the exact string the model read (opt-in; default OFF is a privacy decision) | recordSystemPrompt |
src/core/agent/types.ts |
9.50.0 |
| a typed HITL prompt — let a person pick from a list, choose a range, use a real control instead of typing prose | AskComponent + componentId (consumer-registered vocabulary, opaque here) + inline props + propsRef (artifact claim ticket for the big half) |
src/core/askComponent.ts |
9.24.0 |
| carrying WHAT the person chose back, with what they could see | DecisionValue (kind / value / from? + coverage {seen, total, filter?}) |
src/core/checkin.ts |
9.47.0 |
| archiving a finished run — filing it, attaching it to a bug report, feeding it to an analysis tool | persistRecording + RecordingEnvelope + run.complete (required) + privacy.mode ('full' today; 'structure-only'/'redacted' refuse by name) |
src/recorders/observability/recordingEnvelope.ts |
9.48.0 |
| packaging a run for a HUMAN to file — a zip whose evidence is the archive envelope, plus host facts and a readable transcript | exportBugReport + include (the consent seam; left-out units are counted in manifest.excluded) + warnOverBytes (default 20 MB) |
src/lib/bug-report/build.ts |
— |
| writing archived runs somewhere — a directory, one JSON file per run | fileRecordingSink + RecordingSink |
src/recorders/observability/fileRecordingSink.ts |
9.48.0 |
| declaring an agent's whole setup as one named, versioned thing — a preset, a template, a blueprint, "the support agent we all use" | defineAgentRecipe + AgentBuilder.recipe() |
src/recipes/ |
9.48.0 |
| naming your own branches and nodes — which prefix is reserved, and telling framework plumbing from consumer structure in a trace | RESERVED_SUBFLOW_PREFIX + isReservedSubflowSegment |
src/conventions.ts |
9.49.0 |
| keeping a large tool result out of the model's context | artifacts (bare store, or { store, placement: { maxInlineChars }, recordings } — placement omitted ⇒ never placed; recordings: true / { label }, default off) + wants + placement |
src/artifacts/ |
9.21.0 |
the ticket placement just minted being REFUSED by your own wants argument as a kind mismatch — because the mint says tool-result/<toolName> and your consumer says dataset/rows |
Tool.resultKind + placedResultKind(toolName, declared?) (the mint speaks the consumer's vocabulary; the exact-match matcher is untouched) |
src/artifacts/placement.ts |
9.70.0 |
| letting the UI draw an artifact without the model naming a component | registerArtifactComponent (in the agentfootprint-lens package) |
— | — |
| finding which tools the model keeps writing by hand | agentfootprint.tools.code_run + codeShape |
src/core/codeRunnerTool.ts |
9.46.0 |
| a skill wrongly activated by a keyword staying loaded for the whole turn — suspending/parking a map's prompt + tools when its contribution goes unused, WITHOUT touching its cursor, and re-engaging it on evidence | .maps({ renewalGrace }) (default 3) + MountedMap.nonParkable + advanceEngagement + agentfootprint.map.engaged/parked + skip reason 'parked' |
src/maps/ |
9.58.0 |
| a value that must say how it knows itself — an unknown count that can never render as zero | Claim<T> (known/unknown/notApplicable) |
src/lib/claim/claim.ts |
9.58.0 |
| asking a debugging model "what did this run contradict itself about, and why?" — the Context Integrity findings, joined to the step that filed them | find_context_errors |
src/lib/trace-toolpack/traceToolpack.ts |
9.61.0 |
| the model inventing an id or a reading that no tool ever returned — a deterministic fabrication detector on the final answer, with a posture for how hard it pushes back | .namesAndNumbersFromEvidence() + posture ('assist' record+flag, the default / 'guard' one revision then ship flagged / 'rails' refuse instead) + shapes + exempt + minDigits (default 4) + nudge (default off) |
src/core/agent/evidence/ |
9.35.0 |
| counting a HUMAN-VERIFIED value as ground for the choice-seam check — the person clicked a row, the app verified the cells against the artifact, and the id the model takes from that selection is not fabricated; the source label travels onto the record | externalGrounds + ExternalGround + external_ground_used |
src/integrity/unsupported-argument/check.ts |
9.72.0 |
| a lookup tool that answers "nothing found" for EVERY id because a filter broke, and an agent reporting that absence as fact — the run itself produced the id, the lookup came back empty, and that PAIR is worth a look | noticeEmptyLookups + readLookupResult + EMPTY_LOOKUP_CEILING (dial default OFF and needs a tool declaring argumentsFrom too — two halves; kind empty-lookup at seam write, always advisory: true; empty = a zero-length ARRAY or an absent() envelope, every other shape files not-applicable and no finding; the ceiling is quoted verbatim into every message) |
src/integrity/empty-lookup/ |
9.77.0 |
an agent answering a NEW question out of an OLD turn's tool results — grounded, four turns stale, and the evidence gate approving it (Tool calls 0 and "all 7 values were found in what the tools returned"). ALSO the bug half: the gate's two sentences claimed the flagged values "appear in no tool result FROM THIS TURN" while its index walked every role:'tool' turn — a boundary asserted and never measured; both now say "no tool result this run read" |
noticePriorTurnEvidence + PRIOR_TURN_EVIDENCE_CEILING + priorTurnEvidenceOf + AnswerGroundingReading (dial default OFF and needs .namesAndNumbersFromEvidence() too — two halves, and the second is structural: the gate owns the extractor that decides which tokens are values; kind prior-turn-evidence at seam claim, always advisory: true; EvidenceCorpus.values became a Map<form, turn> stamped in the walk that was already happening, a TURN = each role:'user' message isLibraryAuthoredTurn did NOT write (counting the gate's own correction would file against every revised answer); fires when ≥1 value is grounded and NOT ONE came from the turn being answered — ONE current-turn value files nothing, which is what keeps an honest follow-up quiet and is the design's falsification test; the zero-tool-call turn is the SAME kind with a stronger witness, not a second kind; corpus is the LIVE WINDOW so ordinals are window-relative and the distance is a FLOOR, while the boundary stays exact ('current-request' is un-droppable); memory/RAG values are exempt from grounding and invisible — it can under-report, never over-report; the ceiling is quoted verbatim into every message) |
src/integrity/prior-turn-evidence/ |
9.83.0 |
a tool's ROWS quietly disagreeing with what the tool promised — a LUN 0 stored as "" because it is falsy, a numeric column arriving as quoted strings, a declared column present in no row at all |
Tool.resultColumns + checkColumnTypes + COLUMN_TYPE_CEILING + readRowset (dial 'off' (default) / 'warn' (file findings, model reads the rows unchanged) / 'enforce' (refuse the rows, resultCeiling's teaching-sentence idiom, delivered status 'invalid') — the toolArgsValidation trio, this seam's mirror; needs a tool declaring resultColumns too — two halves; types number/string/boolean/date, bare word or {type, nullable}, deliberately NO 'unknown'; OPEN — unlisted columns allowed and unjudged; TWO kinds at seam write — column-type-mismatch (there, wrong type) vs missing-column (declared, in no row); rowset = an ARRAY OF PLAIN OBJECTS with ≥1 row, everything else incl. the ZERO-ROW result files not-applicable (empty is empty-lookup's subject); travels MCP _meta; the ceiling is quoted verbatim into every message) |
src/integrity/column-types/ |
9.78.0 |
a model head-mathing a total from tool-result numbers while a compute tool sits unused on the wire — a LATE line each iteration naming the staged refs and the wants tool that spends them (recency working FOR the instruction), plus the revise correction naming the same route |
nudge: true (default off) + stagedRefsNudgeLine + findStagedRefs + grounding_nudged |
src/core/agent/stagedRefs.ts |
9.75.0 |
| a tool answering "I looked and found nothing", routably | absent + looked_for + checked/not_checked/cannot_cover + tryInstead (delivered status 'absent', routable by onToolStatus) |
src/core/agent/coverage/absent.ts |
9.43.0 |
| stating what a clean answer does NOT rule out | coverage + the declaration { checked, not_checked?, cannot_cover? } |
src/core/agent/coverage/ledger.ts |
9.43.0 |
minting one of those shapes from a tool that is NOT JavaScript — the canonical note sentences and reserved marker keys as DATA, so a Python/Go/Rust sidecar reads a file instead of regex-scraping dist/esm (which a consumer really did) |
canonical-notes.json at the package root + the ./canonical-notes.json exports entry, GENERATED from the built barrel by scripts/gen-canonical-notes.mjs |
scripts/gen-canonical-notes.mjs |
9.70.0 |
| proving a session store really honours the port | runSessionLifecycleConformance + declared skips (by case name WITH the reason; a declared case still RUNS) + outcomes 'passed'/'not-applicable'/'declared'/'failed' |
src/hosting/conformance/ |
9.37.0 |
| deciding who owns a contested session write | resolveSessionOwner |
src/hosting/sessionOwnership.ts |
9.37.0 |
| making a caller-supplied id safe for a backend | encodeIdentityField |
src/memory/identity/encode.ts |
9.37.0 |
| scoping a skill's tools so they reach the model only while it is active | toolsFromActiveSkill + a no-arg posture (default off) + the stamp autoActivate: 'currentSkill' (a default, never an override) |
src/core/agent/toolsFromActiveSkill.ts |
9.36.0 |
| subscribing to every event in one domain at once | DomainWildcard |
src/events/dispatcher.ts |
9.4.0 |
| pausing a run for a person and resuming it later | checkInApproved / checkInDeclined ({ by, note?, value? }; a decline is NOT an abort — the model gets a "declined by human" tool result and adapts in-loop) |
src/core/checkin.ts |
7.5.0 |
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 2d ago Changed · +1 lines · +397 tokens per session e892e6a66772
- 6d ago First seen · 208 lines · 21,166 tokens per session scan A 24c178fd18f4
agentfootprint CLAUDE.md is an instructions file published in the GitHub repository footprintjs/agentfootprint (20 stars, last pushed today), licensed MIT. It adds 21,563 tokens to every session, about $0.1078 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.
Other instructions, from other repositories
next.js AGENTS.md
AGENTS.md instructions for vercel/next.js, covering next.js development guide, codebase structure, monorepo overview, core package: packages/next and other important packages.
codex AGENTS.md
AGENTS.md instructions for openai/codex, covering rust/codex-rs, the codex-core crate, code review rules, crate api surface and model visible context.
vscode buildNext.instructions.md
Working notes and architecture documentation for the new esbuild-based build system in build/next. Use when making changes to the new build pipeline (transpile/bundle commands, NLS plugin, source-map handling, resource copying, or self-hosting watch tasks).
vscode oss-third-party-notices.instructions.md
Instructions for microsoft/vscode, covering vs code oss third-party-notices pipeline, architecture, pipeline flow in ci, applying the notice (cutover) and fallback chain (never fail the build).
spec-kit AGENTS.md
AGENTS.md instructions for github/spec-kit, covering agents.md, about spec kit and specify, quickstart — add a new integration in 5 steps, integration architecture and integrationmanifest — file tracking.
langchain AGENTS.md
AGENTS.md instructions for langchain-ai/langchain, covering global development guidelines for the langchain monorepo, corridor security analysis, project architecture and context, monorepo structure and development tools & commands.