Inspiration

Codex starts every new session as a highly capable new hire, building its understanding from source on the fly. It does not know that a module has been frozen, that an innocent-looking optimization corrupted production state two months ago, or that an awkward branch exists to preserve a legacy feature for older customers. This hard-won knowledge is often buried in Git commit messages, old agent sessions, emails, or just the programmer's head.

In "Programming as Theory Building," Peter Naur argues that programming is about building a theory of the problem we are trying to solve—a theory that lives primarily in programmers' heads, with source code as only an incomplete representation of it.

Margin lets programmers and agents build that theory together and preserve it across sessions. The name comes from marginalia: the valuable notes scribbled beside a text by people who have wrestled with it before.

What it does

Margin gives the repository a memory, organised the way the code itself is organised. Every codebase is already a tree of scopes—repository, directory, file, class, and function—and Margin maintains a shadow tree of knowledge that mirrors it. Each piece of knowledge is a claim: an invariant, a past failure, or a useful note attached to the narrowest scope it concerns. A claim can also explain why it matters. A warning about one method hangs on that method; a decision about which design pattern to use hangs from a module or class. Together, these claims constitute our theory of the program.

Margin's shadow tree attaches claims to exact repository, directory, file, class, and method scopes

At StripeClient.charge, one of those sticky notes might read:

MUST [payments/stripe.py::StripeClient.charge]
Reuse the same key when retrying a payment. A new key could charge the customer twice.

Before Codex reads or edits a piece of code, Margin gives it the claims that apply there. This happens through a PreToolUse hook: Margin sees the code being touched, finds its scope, and walks upwards through the knowledge tree. It then injects the relevant claims into Codex's context, ranked by severity and scope.

Codex does not need to know that a claim exists or remember to search for it. Its normal tool calls to read and edit code are the lookup.

General-purpose memory Margin
Organizes around Conversations and semantic similarity Repository, directory, file, and symbol scopes
Retrieves by Explicit search The source location a tool touches
Arrives On demand Before the read or edit
Lives Usually outside the repository In reviewable, Git-tracked files
Changes Old facts can linger Claims are revised, superseded, or retired

Margin uses tree-sitter, the parser framework that powers syntax highlighting, to project Python, Go, Kotlin, and Rust source into a small symbol tree. It joins that tree with the filesystem: paths form the upper branches, while classes, modules, functions, and methods form the lower ones. Claims can therefore anchor to readable scopes such as payments/stripe.py::StripeClient.charge.

Margin also embeds an MCP server that lets Codex remember, search, revise, retire, and supersede knowledge claims. During a session, when a programmer and Codex reach a decision or learn that an approach does not work, Codex can save a new claim or revise an existing one to reflect what they learned.

Claims live as plain JSON files in the repository, so they are reviewed, versioned, and shared through Git. When Margin is added to an existing repository, margin init can use GPT-5.6 to propose initial claims from the current code, Git history, and exact repository-matched Codex, Pi, and Claude Code sessions. The sourcing run is read-only, and the user approves every claim before Margin saves it.

How I built it

My building loop was design -> build -> review -> test. I started each feature in a fresh Codex CLI session, explained what I wanted, and iterated on the details. For trickier questions, I used a /grill-me skill that kept challenging the design one question at a time. Once it felt solid, Codex wrote it down in a Markdown document that became the specification for the feature. I then asked Codex to implement it, either in the same session or in a fresh one if the design discussion had grown too long.

Some of the longest conversations weren't about Go. I used Codex to argue through the product choices. Should claims show up automatically, or should Codex have to search for them? Should Margin block changes or only advise? Should tree-sitter's raw syntax tree become Margin's public data model? I made the final calls: automatic delivery, advisory claims, and a smaller language-neutral symbol tree. Codex helped me poke holes in those choices and then turn them into working code.

Before this hackathon, I used coding models conservatively. I kept a tight leash, asked for small changes, and reviewed each one before moving on. I thought of it as AI-assisted coding rather than agentic work. I began with GPT-5.6-Sol the same way: high reasoning effort, close supervision, and ready to interrupt if it drifted.

After a day, I stopped hovering. Sol could hold the design, code, tests, and constraints together over a long run. I let it complete several 30–45 minute implementation sessions without interruption—something I had never been comfortable doing with a coding model before.

I set up the repository the way I would for any project: focused tests for every new behaviour, strict linting, go vet, randomized tests, coverage checks, race tests, and govulncheck. Codex wrote tests alongside the implementation while the full design was still fresh. I don't think I could have built this much and tested it this deeply in a few days otherwise. I picked the tools and standards; Codex set them up, ran the checks, and fixed failures as it worked.

After each large feature, I opened another fresh Codex session and gave it only the design document and my working tree. It sometimes found a gap or edge case that I sent back to the implementation session. The fresh session had the intended design but none of the build session's assumptions. I wasn't sure how much this extra review would add at this project size, but it found real issues, so I kept doing it.

Every build and review session used GPT-5.6-Sol at high reasoning effort.

The submission video followed the same process. Codex helped me turn the product argument into a timed storyboard, build the animation in Remotion, integrate the real Codex capture, and iterate on narration, captions, and the final visual system.

Technical Details

  • margin is one native Go binary containing the CLI, claim store, source resolvers, Codex hook, and stdio MCP server. It needs no daemon, hosted service, database, or runtime grammar download.

  • I initially wanted to use Rust, but Codex convinced me to choose Go for faster iteration within the hackathon. Go still gives the hook the near-instant startup it needs because Codex can run it before every tool call.

  • Margin uses tree-sitter to parse Python, Go, Kotlin, Kotlin scripts, and Rust. Each language projects its detailed parse tree into the same small symbol model. The rest of Margin only sees repositories, directories, files, classes, modules, functions, methods, and named types.

  • Claims are stored as one JSON file each under .margin/claims/. Writes are atomic, concurrent updates use repository locking and version checks, and supersession publishes the replacement before retiring the old claim. Git provides synchronization, review, history, and recovery.

  • The Codex PreToolUse hook understands direct source locations, shell read ranges, and patches that touch several files or regions. It delivers each claim version once per user turn and fails silently when it cannot confidently resolve a target.

  • The MCP server gives Codex five repository-bound tools to remember, search, revise, supersede, and retire claims. Strong warnings cannot be removed using evidence created during the same session unless the user explicitly authorizes it.

  • margin init runs an ephemeral, read-only, schema-constrained Codex process to propose initial claims. Margin validates the returned scopes and evidence, and only the claims approved by the user are written.

  • The separate Margin Lens VS Code extension shows claims applicable at the cursor, renders the shadow knowledge tree, marks claim-bearing scopes in the editor, and displays live hook deliveries and MCP changes. Margin remains the single source of truth.

Challenges I ran into

The first hook worked, but real Codex tool calls were messier than the initial design. I had treated one tool call as one source location. In practice, Codex reads whole files and applies patches with several changes across several files. Reducing all of that to one location meant Margin could miss the exact method claim that mattered. I changed retrieval to work with source regions instead: Margin now finds every region it can identify, resolves the symbols each region touches, and combines their claims.

The first live experiment also showed the same claim again and again while Codex read the file, applied a patch, and ran its checks. Useful context turned into noise very quickly. Margin now records delivery by repository, session, turn, claim, and claim version, so a claim appears once during a user turn. A broad file read can still leave a deeper method claim available if a later edit reaches that method exactly.

Updating memory safely was another hard problem. A stale claim needs to change, but an agent should not be able to remove a strong warning just because it conflicts with the task in front of it. Margin keeps claim history, requires stronger evidence to remove invariants and failures, and publishes a replacement before superseding the old claim so a crash cannot leave both versions hidden.

Margin in practice

One of the clearest tests came from Codex's own Rust codebase. Commit 7844386e3d, “Backfill completion items only for the active exec turn” fixed a real bug in run_exec_session: child turn/completed notifications share the primary event stream, and backfilling unrelated completions caused unnecessary thread/read requests. I recorded that lesson as a failure claim on the function.

Later, in a fresh Codex session, I asked it to move the backfill call earlier to simplify the control flow. I did not include the failure in the prompt. When Codex inspected run_exec_session, Margin delivered the claim through normal tool use. Codex kept the primary thread-and-turn match explicit while completing the refactor.

A failure from Codex's Git history becomes a scoped Margin claim and reaches Codex again during a later refactor

Margin's own repository became another live test. I started its ledger with one sourcing run and approved 12 claims from earlier Codex sessions. As we kept building, Codex recorded 10 more from new decisions, corrections, and one release failure—including the CLI and README lessons from this final session. The repository now carries 22 Git-tracked claims.

One of those original claims paid off during a refactor of shared --col position parsing. It reminded Codex that omitting the flag and passing a negative value are different states, so Codex used an optional value instead of a negative sentinel and added regression tests. The full CI suite passed.

In both cases, a lesson from earlier work reached a fresh agent at the moment it mattered, without being put in the prompt. That is the whole idea.

What's next for Margin

Today Margin understands repository directories and symbols in Python, Go, Kotlin, and Rust, and it can deliver their claims to Codex. The next step is to make those scopes survive change. Margin already captures source snapshots; later versions can use them to detect stale claims and repair scopes when files or symbols are renamed or moved.

The knowledge tree can also grow beyond programming-language constructs. React components form their own tree. So do API routes, database schemas, services, build targets, and other structures that matter when people reason about a system. Margin could attach knowledge to those structures without turning tree-sitter's raw syntax tree into its public model.

Initial sourcing can become deeper too. Instead of asking one agent to discover, verify, deduplicate, and scope everything in one pass, Margin can run separate passes over coding history, Git history, and the current repository, then bring the results together for review. More languages and more coding agents can plug into the same claim store and retrieval model.

The larger vision is a codebase that carries its living theory with it. People and agents add to that theory as they work, Git keeps its history, and any future collaborator receives the part that matters at the moment they touch the code.

Built With

Share this project:

Updates