agentfootprint: Instructions file for Claude Code

CLAUDE.md

agentfootprint CLAUDE.md is an instructions file for Claude Code from footprintjs/agentfootprint. It costs 21,563 tokens per session, scanned A, original, MIT.

Repository instructions for agentfootprint, an agent framework built on footprintjs. They map existing features, internal flow, and places where the framework can be extended.

In plain words
What is it for?
Use them when planning agentfootprint changes, tracing how agents and language-model calls run, or identifying the likely files and code paths to modify.
Why use it?
They help developers avoid designing features that already exist and show which upstream framework parts are responsible for behavior.

Instructions file for Claude Code

Written for Claude Code: the file is CLAUDE.md.

This is footprintjs/agentfootprint's own configuration. It tells Claude Code how to work on agentfootprint itself, so it is not a mod to install elsewhere. Copy it as a starting point and replace the rules that are about this project. Everything agentfootprint configures →

Reuse

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.

Copy the file
curl -O https://raw.githubusercontent.com/footprintjs/agentfootprint/main/CLAUDE.md
Clone the repo
git clone --depth 1 https://github.com/footprintjs/agentfootprint

Made for: Claude Code.

Wrote 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.

agentmods badge for agentfootprint CLAUDE.md

README.md
[![agentmods](https://agentmods.dev/badge/instructions/footprintjs/agentfootprint/claude-md.svg)](https://agentmods.dev/instructions/footprintjs/agentfootprint/claude-md)
Your own site
<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>
Per session 21,563 This file is loaded in full into every session.
When invoked 21,563 The same file — it is already loaded in full.
Security scan A 0 findings. Scan, not verified.
Origin original No closer match found in the catalogue.
Token cost

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.

ModelPer sessionOnce 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

Measured 2d ago against content hash e892e6a66772, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-06, from the pricing page.

Security

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.

CLAUDE.md · 209 lines

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 writecolumn-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

Read the full file on GitHub · 209 lines

Changes

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.

  1. 2d ago Changed · +1 lines · +397 tokens per session e892e6a66772
  2. 6d ago First seen · 208 lines · 21,166 tokens per session scan A 24c178fd18f4

Subscribe to this mod's changes

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.

Related

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.

vercel/next.js · 7,296 tokens

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.

openai/codex · 5,182 tokens

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).

microsoft/vscode · 6,785 tokens

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).

microsoft/vscode · 5,001 tokens

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.

github/spec-kit · 7,104 tokens

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.

langchain-ai/langchain · 4,469 tokens