Meet Forge — context management for AI agent harnesses
A git-like CLI that gives AI agents a senior engineer's memory of your codebase — automatically, incrementally, and always in sync. Forge is part of anvil, a Claude-Code-like agentic harness written in Rust. built in rust
$ forge init && forge update
The problem: agents read code, they don't understand it
When an AI agent edits a file, it sees structure — function signatures, types, control flow. What it doesn't see is the reasoning behind it.Claude Code's CLAUDE.md does this at the project level. Forge does it per file — the difference matters once a project stops fitting in one note. Why does this file exist? What must never change? Where does new code belong?
Without that context, agents make plausible-but-wrong decisions. They duplicate logic that already exists elsewhere. They violate invariants that aren't written down. They refactor things that can't be refactored.
Agent reads parser.rs — 400 lines of syn AST traversal.
It doesn't know the 15-line collapse threshold is a deliberate policy decision.
It doesn't know non-Rust parsers should be sibling files, not added here.
It makes a plausible change. It breaks something subtle.
Before touching the file, the agent reads its context note.
"COLLAPSE_THRESHOLD must remain a named constant — it's a tunable policy decision."
"Non-Rust parsers belong in sibling files, not here."
The agent acts with intent. The change is correct the first time.
Think of forge as the notes a senior engineer leaves on their first day handing off a file — not documentation, not a spec, but the things you'd only learn after breaking something in production.
Four commands. That's the whole workflow.
Forge walks your project respecting .gitignore, records the current git hash for every source file, and creates a .anvil/manifest.toml. No context is generated yet — just a baseline snapshot. Fast and free.
Compare stored hashes against current git state. Every file gets a clear status: up to date, stale (hash changed), or missing context. Like git status but for your agent's understanding of the codebase.
For new files: sends full source to Claude and generates a structured context note. For changed files: sends only the git diff and the existing note — Claude patches just the affected sections. Up to four files run concurrently. Prints a token and cost breakdown when done.
forge updateInstalls a PreToolUse hook into Claude Code's settings.json. From that point on, every time Claude reads a file forge silently injects its context note as additionalContext — no prompt changes, no manual steps. The agent always understands why a file exists before it touches it.
ok crates/anvil-core/src/utils/parser.rs
stale crates/forge/src/commands/update.rs (e8f53f6 → cfbe244)
ok crates/forge/src/git.rs
stale crates/forge/src/store/manifest.rs (e8f53f6 → cfbe244)
28 up to date, 2 stale
updated crates/forge/src/store/manifest.rs
Usage 2 files claude-sonnet-4-6
input 12,450 $0.0374
output 8,230 $0.1235
─────────────────────────
total $0.1608
Context files: six sections, every file, injected automatically
Each context file lives in .anvil/ mirroring your source tree.
The format is fixed so agents can query specific sections rather than parsing
free-form prose.
Parses Rust source files using syn and converts the AST into a structured FileSpec summary that an AI agent can reason about without reading every line.
• Must not panic on any valid Rust source file — unrecognized items return None, never unwrap
• COLLAPSE_THRESHOLD must remain a named constant, not an inline literal — it is a tunable policy decision
• Output must be deterministic for a given input — no random ordering, no timestamps
Every context file answers the same six questions. An agent reading
parser.rs for the first time gets all of this before writing a single line.
Incremental updates: diffs in, patches out
Forge doesn't regenerate a context file from scratch every time a file changes. It sends Claude the diff alongside the existing note and asks it to patch only the affected sections. This keeps updates focused and API costs minimal.
The hash stored in manifest.toml is the commit hash of the file
at the last successful update — not HEAD. So if you update a file across three commits
before running forge update, the diff covers all three at once.
The .anvil store: structured like your project, committed with your code
Context files live in .anvil/, mirroring the source tree one-to-one.
The manifest tracks the hash for every file. Both are committed to git — context
evolves alongside code, and diffs are meaningful.
manifest.toml
crates/
anvil-core/src/
tools/read_file.md
utils/parser.md
utils/formatter.md
utils/query.md
forge/src/
commands/update.md
commands/init.md
git.md
store/manifest.md
manifest.toml
↳ "crates/forge/src/git.rs" = "cfbe244..."
↳ "crates/anvil-core/src/utils/parser.rs" = "cfbe244..."
By the numbers: forged on itself
The first thing we ran forge on was anvil — the project that built it.$1.97 for thirty files of handoff notes. The per-run cost breakdown exists because surprise API bills are how side projects die. Here's what that looked like.
Initialized forge — tracking 30 files
$ forge update
updated crates/anvil-core/src/tools/read_file.rs
updated crates/anvil-core/src/utils/parser.rs
updated crates/forge/src/commands/update.rs
... 27 more
Usage 30 files claude-sonnet-4-6
input 187,320 $0.5620
output 94,150 $1.4123
─────────────────────────
total $1.9743
$ forge for-agent claude
forge → claude
hook .claude/hooks/forge-context.sh
settings .claude/settings.json
$ forge status
30 up to date, 0 stale
Design: built like git, reliable like a tool should be
Context files are written to a temp path and renamed into place. A crash mid-write never leaves a corrupt file.
One file failing to update doesn't abort the rest. Errors are collected and reported at the end.
Uses the same engine as ripgrep to walk your project. If git ignores it, forge ignores it. Any language, any file type.
forge init fails immediately if .anvil/ already exists. No half-initialized state.
Updates run four files at a time via a semaphore. Fast enough to not block you, conservative enough to not flood the API.
Every forge update run prints a full token and cost breakdown — input, output, cache reads and writes — so you always know what you spent.
Built with: anthropic-sdk-rust · tokio · syn · ignore · clap