zack petersen

Building with agents

How I build with Claude Code

In 2026 I adopted an abandoned repository and turned it into a revenue-producing software as a service (SaaS) product within three months, working primarily through Claude Code. The agent plans, implements, reviews, opens the pull request, and monitors continuous integration (CI). I decide what gets built, verify what ships, and own production.

The result depends on the setup more than the model. Everything an agent needs to make the right decision lives in the repository, not in a conversation that ends. Hooks and scripts enforce the rules that matter. That is what keeps a largely agent-written codebase maintainable as it grows, instead of degrading into slop. The codebase carries more test code than application code, and every change lands through the same loop.

The loop, from ticket to production

The purpose of the loop is to record every decision, every major change, and anything else an agent needs in order to keep building the codebase correctly. Each step writes something down that the next step reads.

01

Interview, then spec. Before any feature, I interview the stakeholder until the behavior is unambiguous, write a spec, and get sign-off. The spec is the only context the implementer receives, so every ambiguity is resolved here rather than guessed at later.

02

Review the plan with fresh eyes. A hook blocks any plan until a separate agent with no conversation context has reviewed it. A model that reviews its own plan agrees with itself, so the reviewer never sees the conversation that produced the plan.

03

Implement from the spec alone. A fresh agent receives the spec and the repository conventions, nothing else. If the implementer cannot build the feature from the spec alone, the spec is incomplete and gets fixed before any code is written.

04

Diff the branch against the spec. A second fresh agent reports what the branch satisfied, what it violated, and what it silently added. The list of silent additions is what catches scope creep that a general code review would accept.

05

Verification before any claim. I run the verification commands and test the feature myself before the pull request opens. Neither the implementer's report nor the reviewer's counts as proof.

06

One review pass, then merge. Every pull request gets one constrained artificial intelligence (AI) review against a severity rubric. Each finding gets a written disposition in the pull request, and only accepted blockers get a fix pass, so the reasoning behind every change survives with the change.

07

Deploy and monitor. A merge to the main branch deploys to production. A read-only smoke suite drives the live site after every production deploy, and a failed run opens an incident on its own.

What the machine enforces

Rules that have to hold across sessions go into a hook, a lint rule, or a permission list. An instruction the agent is expected to remember is not enforcement.

Model guard. A hook denies any agent dispatch that does not name a model, so mechanical work such as test generation, renames, and documentation sweeps never silently inherits the most expensive model.

A single path to the database. The raw database command line tool is denied outright. The one allowed wrapper takes the target environment as its first argument, so a permission rule can distinguish local from cloud, and every cloud write requires a human at a terminal.

Feedback in the same turn. A post-edit hook lints migrations and checks that every file path a document references still exists. A failure returns to the agent as a blocking error, so it is fixed in the same session instead of in CI an hour later.

A manifesto with a tiebreak. Ten numbered design laws the agent reasons from when no rule covers the case, each with an example from the codebase. Lower numbers win, and an unresolvable conflict is escalated to a human instead of decided silently.

Decision records. Architecture decisions are recorded with evidence from the repository, and the state document is updated in the same pull request that changes the state it describes, so the next session starts from the current state of the system rather than a stale description of it.

One worktree per agent. Every agent task runs in its own git worktree on its own branch. Resources a worktree cannot isolate, such as the local database and migration numbering, have a single owner defined in a written contract.

Agents on call

Agents also watch production. They monitor Sentry, Slack, and customer support channels, triage what comes in, and open issues with the evidence attached, the way an on-call rotation does. At Reserv I built the team's Claude Code on-call plugin for the same purpose: incident triage, Dependabot review, database queries, and rotation summaries, set up as a plugin marketplace other teams can install from.

What I do myself

I verify and test every feature the agent builds to confirm it does exactly what was intended. Every production write, every secret, and every merge goes through me. Development is autonomous. Anything that touches production requires a human.

The portable parts

The pieces of this setup that are not specific to one codebase are public: the model guard hook, the self-review plan gate, the pull request triage command, the worktree manager, and a manifesto template, with machine-specific values marked FILL IN.

github.com/zackcpetersen/claude-setup

Say hi

Get in touch.

Email is the best way to reach me, and I reply to every message.

zpetersen78@gmail.com