Mac Anderson

Coding agents, Autonomous agents

Letting agents write the code

I wrote code by hand for 16 years. In 2026 I let agents write all of it, and spent seven months learning to manage them. The record of those months, in my own words.

Mac Anderson17 min read

I wrote software by hand for 16 years. In February 2026 I made a decision: agents would write all of the code I shipped. My job would be to direct them, read their work, and decide what merged. Some of it went well. A lot of it went wrong. The hardest part turned out to be managing the agents, and I built Oxagen to do that job.

This is the record of those seven months, 26 February to 20 September 2026, read back from what I left behind: my GitHub history, my git history, and the 8,133 prompts I typed to Claude Code.

What the record covers#

The 8,133 prompts come from one laptop, set up on 29 June 2026. They cover 81 days of the seven months. I also used Claude on other machines, before that laptop and at the same time, and those conversations are not in the log. There is no way to rebuild them.

So every prompt figure here is a sample, not a full count. The topics, the hours, the happy words, and the swear words describe those 81 days only, and each one is a minimum. The real totals are higher, but I cannot say by how much, so I do not guess.

The GitHub and git numbers are different. They come from my GitHub account and from 13 local clones, they cover the full dates given for each, and they are complete for what they count.

Chapters#

Each chapter comes from reading the prompts in order. The quotes are mine, trimmed, with the swearing taken out.

ChapterDates
Before the log26 Feb to 28 Jun
Beat Claude Code29 Jun to 9 Jul
Stella is born10 Jul to 19 Jul
Protocols and proof20 Jul to 31 Jul
The hard weeks1 Aug to 11 Aug
Less is more12 Aug to 19 Aug
Many agents at once20 Aug to 30 Aug
Oxagen becomes the control plane31 Aug to 10 Sep
Starting over from a new spec11 Sep to 20 Sep

Before the log#

GitHub shows the work starting on 26 February. March brought 689 contributions, April 1,846, and May 2,167. On 28 May the first commits landed in the Oxagen repository: the foundations and the agent runtime. My prompts from these months were on an earlier laptop, so this chapter rests on commits alone.

Beat Claude Code#

I set up a new laptop on 29 June and worked fast on the TypeScript Oxagen command-line agent. I added caching, effort levels, a code graph, and an SWE-bench test setup, and I told the agents building that setup not to favour my own agent. On 3 July I set the goal: "Stripe for agents." Four days later I dropped metered billing and moved to governance, traceability, budgets, and permissions. The same day I wrote "if you see it you own it" into my agent instructions.

What I typed then, about the benchmark: "i do not want to falsely promote that oxagen is better."

Stella is born#

One night of "crazy ideas" led to the mutation verifier. It checks that each test fails when its fix is removed, so a test that passes no matter what counts for nothing. The next day the Rust rewrite got a name, Stella, and a public repository. Done came to mean a regression test that fails on the old code and passes on the new code. By 17 July you could install Stella 0.3.0 from Homebrew, and fleets ran with no coordinator at all.

The line I keep coming back to from that week: "determinism is fast, cheap, reproducable, and better than intelligence 10/10 times."

Protocols and proof#

The context protocol was renamed the Context Graph Protocol, and its SDK shipped on npm. ArenaBench went public. Steering records stored each agent's standing instructions in git, as TOML files. On 31 July I ran the first head-to-head test against Claude Code on Terminal-Bench 2.1, with the rules published before the run. Both agents used the same model. Stella solved 58 of 89 tasks, and I published the run.

On 22 July I wrote the motto: "verification can not lie."

The hard weeks#

Benchmark runs had hidden caps. A verifier model spent four minutes and never wrote its test. On 8 August I found that the code graph had been empty, with no error, because init never ran. Stella's "losses" came from a $1-per-task budget cap. So proving the agent worked took more effort than building it.

I made rules from these problems, and they still hold. Prove a defect with a failing test first. Check results with tests, not with a model. Never cap a benchmark. On 11 August I also published a result that made Stella look worse: on Sonnet 5, Stella cost about four times what Claude Code did, and I decided the prompts caused the cost.

What I typed on the worst of those days, in capitals: "WE HAVE MOVED TO FAST AND I AM WORRIED I WILL HAVE TO THROW AWAY THIS PROJECT."

Less is more#

Semantic code search started working, and Stella's 72 tools shrank to five. Verification moved out of Stella into a plugin that can block a turn. The core became one loop. Everything else became a plugin, written in any language. On 19 August I deleted the pipeline crate, and self-driving Stella started working through its own list of issues.

My note on 13 August: "less is more and way less is best the 5 tools kicked ass."

Many agents at once#

I ran ten to fifteen agent conversations at once, each on a long goal that needed little input. So most of my prompts were short: "go," "resume," and "merge." I typed fewer prompts, and the output climbed. I moved everything to AWS. I wrote down how I steer my agents as standing decisions. I had Stella build a supply-chain demo app on its own. On 30 August a file-by-file review of Oxagen opened 1,059 issues, and GitHub counted 1,144 contributions that day, the most of any day.

The brief I gave for that stretch: "it is supposed to be hands off autonomous with controls to rollback."

Oxagen becomes the control plane#

I removed the generative AI features from Oxagen and made Stella the engine inside it. Agents got their own identities and permissions, the same way people do. The Terminal-Bench page went up: Stella solved 58 of 89 tasks, and Claude Code solved 44. I added wrappers, hooks installed beside an agent, so Oxagen could govern Claude Code and Codex. Oxagen started pricing by the governed action: one call routed through Oxagen that it checked and recorded.

The split I wrote down on 31 August: "I think stella has the best agent. I think oxagen has the best control plane."

Starting over from a new spec#

I restarted Oxagen from a new spec. The spec said: wrap any agent, decide what each tool call may do, replay every run, and match spend to the cent. About twelve agent conversations, running side by side, built the demo mockups in one day. Within the week, a macOS installer wrapped Claude Code and Codex. Oxagen became a gateway for model calls, and every model call on my own laptop went through it.

Why the tool call, from my prompt on 11 September: "they are worried about agents and the damage is done at tool call level."

The calendar#

I gave each day in the prompt log the area of work that led its prompts. Shipping work led on 50 of the 81 days: CI checks, pipelines, deploys, and the machines that run them. Building the agent led on 19 days, proving it works on 7, and selling it on 5. So when I ran many agents at once, most of my summer went into the systems around the agents, not into the agent itself.

Good days and bad days#

I counted happy words and swear words in my prompts, by day, from fixed word lists. The happy words fall across the July launch weeks. Almost all of the swearing falls in August. That month I was trying to prove that Stella's work was done when Stella said it was.

What I was building when it went well:

  • 12 July. Stella's first week in public. The README brief asked for a project that would inspire a community that is sick of token waste.
  • 19 July. A fleet design with no coordinator, where every agent works in one worktree. "BUILD THIS DESIGN I LOVE THIS."
  • 31 July. Watching the first Terminal-Bench run I trusted reach 58 of 89. "I would have worked hard for a reason."
  • 2 August. A git-backed journal that can resume any turn. "an amazingly elegant answer to the durability problem."
  • 13 August. Cutting 72 tools down to five. "less is more and way less is best."
  • 11 September. Starting Oxagen over from a new spec, with 12 mockups built side by side. "We need to be perfect here."

What I was building when I swore at Claude:

  • 31 July. A "fair" benchmark that had a hidden budget cap. "Dont lie."
  • 4 August. A Files tab that showed no reads and no writes, and a verifier that never wrote its test. "I WILL NOT TOLERATE WIERDNESS IN THE CRUD SYSTEMS."
  • 8 August. A full day of benchmark runs I could not trust. The code graph was empty, with no error, because init never ran. "NEVER RUN A BENCHMARK WITH A BUDGET CAP."
  • 11 August. Correct work was thrown away at the sandbox boundary, so a pipeline mode scored below the plain loop.
  • 22 August. A redesign reported as finished that did not match the drawings. "Burning tokens for what?"

Each time, an agent said something was done, and it was not. Stella's regression tests, and later Oxagen's record, were built to answer that problem.

By topic, prompts about design have the most happy words. Prompts about verification and model providers have the most swear words.

When I work#

I send prompts in every hour except the early morning. The busiest hour is 1 p.m., with 638 prompts. The hours from midnight to 5 a.m. hold 919 prompts, which is 11 percent of the total. They also hold 53 of the 124 swear words, which is 43 percent. The 1 a.m. hour alone holds 32 swear words.

Wednesday is my busiest day of the week, with 1,363 prompts. Monday is my quietest, with 973. I send more prompts on Sundays than on Mondays.

Two products took turns#

Oxagen started first, on 28 May. In the week of 6 July it had 1,421 commits. Then, through August, Oxagen got few commits and most of the work went to Stella. I decided that Stella would be the engine inside Oxagen, and I rebuilt Oxagen around it. In the week of 14 September, Oxagen had 3,501 commits.

What I built#

Each row is one part my agents built from my plans in these seven months, with the day it started.

StartedPartWhat it is
30 JunA coding agent CLIThe first Oxagen command-line agent, in TypeScript, with effort levels, caching, and a code graph.
30 JunAn SWE-bench test setupMy first benchmark setup. I told the agents building it not to favour my own agent.
10 JulA mutation verifierChecks that a test fails without its fix. Only then does the fix count.
11 JulStellaAn open-source coding agent for the terminal, written in Rust. It works with any model and your own API key.
11 JulRegression testsDone means a test that fails on the old code and passes on the new.
12 JulArenaBenchA setup that compares agents on the same tasks and terms. It now has its own public repository.
12 JulThe command deckStella's full-screen terminal interface.
19 JulFleetsMany agents work in one worktree with no coordinator. The first agent to write a file locks it.
20 JulContext Graph ProtocolAn open protocol, with an SDK, for the graphs of context that agents read.
27 JulSteering recordsStanding instructions for agents, stored as TOML in git, with tests that check they helped.
2 AugDurable turnsA git-backed journal that can resume any turn.
6 AugSelf-drivingA loop that audits the code, files issues, and fixes them.
6 AugThe ObservatoryA local dashboard that replays every Stella run.
10 AugTool-first architectureEvery capability is a tool, and every tool has one job.
12 AugSemantic code searchOne search tool that finds code by meaning, using embeddings over a tree-sitter code graph.
16 AugA plugin socketOne loop, with everything else a plugin, in Rust, TypeScript, or Python.
27 AugVoice inputHold the spacebar and talk to Stella.
29 AugRainforestA supply-chain demo app that Stella built on its own.
2 SepAgent identitiesEach agent gets its own identity and role-based permissions.
6 SepClaude Code and Codex wrappersHooks that put other vendors' agents under Oxagen's rules.
11 SepThe Oxagen control planeIdentity, authority, budget, tools, and the record, in one place.
14 SepA desktop installerA macOS app that wraps Claude Code and Codex.
18 SepA model gatewayModel calls routed through Oxagen, priced and recorded.

Learning to manage a fleet#

With one agent, you give it a task, watch it work, and read the diff. With six agents at once, nobody can watch them all, and the job becomes managing them. It was the hardest thing I learned in seven months, and none of it was about prompting.

I started with one agent on one branch, and I watched it work. That setup works, but it cannot grow, because I can only watch one thing at a time. So I added more agents. In the setup I ended with, six or more agents work in parallel, each in its own git worktree. Background agents are on, so work continues while I read something else.

More agents caused problems I had not expected. Two agents edited the same branch. A branch merged into main with no conflicts, but it still did not work with code that had merged beside it. I had to repair a broken main three separate times before I understood the cause: a merge with no conflicts says nothing about whether the code works. Agents also finished, reported success, and left their work uncommitted. These problems happened between agents, not inside any one agent.

Running many agents needed:

  • A separate worktree for each agent, so two agents cannot edit the same files.
  • A written Done Checklist. Without one, an agent decides for itself what finished means.
  • Checks that run without me. There are 21 of them, so I do not have to review every agent's work by hand.
  • A trial merge before the real one, because a merge with no conflicts can still break the code.

What I still could not answer:

  • What each agent did, in order, and what it read.
  • What that cost, and which piece of work it paid for.
  • Who allowed each action, and under which rule.
  • Which agent is stuck right now, and on what.

I could build the first list myself. The second list is a management problem, and it got worse with every agent I added. I built Oxagen to answer it.

The code my agents wrote#

The number of lines does not show whether code an agent wrote works. Tests, checks, and decision records do. These counts come from tracked files on 21 September 2026.

CountValueWhat it covers
Test files2,258Unit, integration, and end to end, across the repository.
Architecture tests272They fail the build when code breaks a structure rule, such as a layer, import, or boundary rule. They do not test behaviour.
Checks in CI21Separate checks, including one that reads the site's text and fails on an em dash.
Decision records136Architecture decision records, plus 5 schema change records. Each one says what was decided and why.

A human reviewer notices when a file imports across a boundary it should not. Many agents working in parallel do not notice. Each may break the same rule in a different place on the same afternoon. A test that fails the build checks every change, however many agents make them. So with many agents, the architecture tests matter most.

The audit#

In September I had the operator console checked against its own specification. The reviewer was told to look hard for problems and to assume the work was incomplete. The review returned 14 findings. Two of them must be fixed before a release. Its summary said: "The app has substantial working foundations, but it does not yet close the core operator workflows."

The audit is published, with every finding, its acceptance criteria, and the repository it checked. It sits in a different repository from the code, so nobody can quietly edit the findings to match what shipped. It shows how the work is checked. It does not show that the work is finished. The work must still clear the two release blockers the audit named.

Oxagen was built using Oxagen#

A coding agent sends every model call to one address, its base URL. In the Oxagen repository, the base URL is Oxagen's own gateway running on my laptop. So every model call made from that repository goes through the gateway, and there is no other path. Oxagen sees each call, measures its cost, and records it. So Oxagen governed and priced the runs that built Oxagen.

Tool calls work the same way. A hook checks each tool call and can refuse it before it runs. Without a rule, every agent would start its own full test build, so the repository has a hook that denies an agent a full test build. This is Oxagen's main idea: the agent asks, and a rule answers. Here it applies to the agents writing Oxagen.

The prompts that produced this story went through the same gateway. The prompt log it uses is the record the gateway kept.

One laptop is not a deployment. The local gateway and its record use the same code as the hosted control plane, and they are what a single operator runs. I do not claim more than that.

The rules I kept#

Most of these started as a frustrated prompt. Later each one became a line in a CLAUDE.md file, a check in CI, or a design rule for both products.

RuleWhat I typedWhen, and what it became
Proof over claims"verification can not lie"22 Jul. It became the regression test.
Determinism first"determinism is fast, cheap, reproducable, and better than intelligence 10/10 times."10 Jul. It became Stella's design thesis.
Measure like for like"WE ARE TO NEVER RUN A BENCHMARK WITH A BUDGET CAP OR OUTPUT TOKEN CAP"8 Aug. It is now a rule for every benchmark run.
Prove the bug first"Make me prove a defect with a failing test before I'm allowed to describe it."8 Aug. It went into AGENTS.md and CLAUDE.md.
Less is more"less is more and way less is best"13 Aug. 72 tools became five.
Nothing gets lost"Any lost work is unforgivable"2 Aug. It became durable turns.
Plain words"An 8th grader should be able to conceptually grasp the work"3 Aug. It became a prose rule, and later a CI gate.
Fix what you see"IF YOU SEE IT YOU OWN IT"7 Jul. It grew into fix over file.
Govern the tool call"the damage is done at tool call level."11 Sep. It shaped how Oxagen answers requests.
Owned intelligence"oxagen believes both people and companies should have owned intelligence"6 Sep. It is the long bet under both products.

Why Oxagen#

The agents could write the code. The hard part was knowing what each agent did, what it cost, and who allowed it.

Oxagen is workforce management for autonomous agents. You give each agent its own identity. You set its authority, budget, tools, and skills in one mandate. For actions routed through Oxagen, the agent asks, a rule your team wrote answers, and Oxagen records the answer with its cost. A mandate has four parts:

  • Access: the identity the agent acts as, and what it may request.
  • Budget and rules: what it may spend, and the rules it works under.
  • Equipment: the tools, skills, and business context it may use.
  • Record: what each governed run read, changed, and cost, and which rule answered each request.

Oxagen shows you every governed action, the rule that answered it, the person who approved it, and which agent spent what, on whose behalf. This story was written from the same kind of record that Oxagen keeps.

Stella is the open source coding agent where this work started, AGPL licensed and free to run. You use Oxagen when a team, not only you, is responsible for the agents.

The counts#

I did not type this code. Agents wrote it. I directed them, read their work, and merged it.

CountValueDates and method
GitHub contributions21,86126 Feb to 20 Sep 2026. Commits, pull requests, issues, and reviews, as GitHub counts them. The same account shows 38 in all of 2025.
Commits6,341On the default branch of 13 repositories, 28 May to 20 Sep. I made commits on 114 of those 116 days.
Pull requests merged4,42728 May to 20 Sep. Every pull request my account opened, in any repository.
Prompts to Claude Code8,13329 Jun to 20 Sep 2026, across 1,769 conversations on one laptop.

My agents added 3,906,359 source lines and removed 1,529,699. That counts source files on default branches only, and leaves out lock files, build output, fixtures, and generated code. Most of the removed lines were code added a week earlier and then taken out.

The repositories are four months old, with no release schedule, no on-call rotation, and no other engineers. When I opened and merged a pull request myself, no second person reviewed it. The prompt count is the least complete number here, because it covers 81 days on one laptop.

How this was counted#

GitHub contributions come from GitHub's contribution calendar for the account macanderson, 26 February to 20 September 2026, private repositories included. For 1 January to 20 September, GitHub counts 7,345 commits, 4,732 pull requests, 5,076 issues, and 4,577 private contributions.

Prompts come from Claude Code's prompt history on one laptop, 29 June to 20 September 2026. The earlier laptop's history is not included. I loaded the prompts into SQLite and read them in full, in order.

Commits and lines come from the default branch of 13 local clones. Each commit counts once, by its hash. The counts cover the 10 name and email pairs I have used for commits, across two GitHub organizations. GitHub's contribution graph also counts the default branch only. Counting only that branch means a rebased branch is not counted twice. Counting every branch would have raised the commit count by nearly half. Pull request counts come from the GitHub search API for my account over the same dates.

Lines fall into three groups. All lines means every text line in every diff. Authored lines leave out machine output: lockfiles, build output, vendored code, snapshots, benchmark artifacts, and event logs. Code lines keep only files with known source code extensions. The source line counts on this page are code lines.

Happy words and swear words are counted from fixed word lists. On 11 September, a mockup brief pasted into 15 conversations repeated the word "wow" 30 times, so the count leaves out "wow." No swear word is printed on this page.

Topics are assigned by keyword, one per prompt. About half the prompts matched no topic and are left out of the topic counts.

Benchmark numbers are the ones I published or typed at the time. The 58 of 89 result is Stella against Claude Code on Terminal-Bench 2.1, both on the same GLM model, on 31 July 2026.

Cite this

Anderson, M. (2026, November 2). Letting agents write the code. macanderson.com. https://macanderson.com/research/letting-agents-write-the-code

BibTeX
@online{anderson2026lettingagentswrite,
  author  = {Anderson, Mac},
  title   = {Letting agents write the code},
  year    = {2026},
  date    = {2026-11-02},
  url     = {https://macanderson.com/research/letting-agents-write-the-code}
}

Related research

Updates by email

New research reaches subscribers first.

No spam. Unsubscribe any time. Read the privacy note.

Optional analytics

With your permission, this site sets analytics cookies to show how people find and read it. Nothing is set until you choose. You can change your choice in Privacy.