How I build with AI
I build production software with AI coding agents, inside the same controls a software company puts around a new engineer: every change to the product is tested and approved before it ships, agents get only the tools their job needs, and every rule has a written reason. Safe As Houses, the client portal for my business, is where this is most developed.
- Step 1MeI write the request in plain English, the way I’d write a product brief, often from my phone.
- Step 2Lead agentA Claude Code session running in the cloud plans the work and keeps a written status file as its memory.
- Step 3Specialist agentsIt hands each piece to an agent with a single job.
- Step 4Pull requestEach change arrives as a pull request: a proposed change, with its own private preview and steps to try it.
- Step 5Automated checksTests, a full build and checks that one client can never see another’s data must pass before anything merges.
- Step 6Me againI try the preview, then approve it or say what to change. No change to the product ships without my sign-off.
The specialist agents in step 3
- A verifier that runs the checks and reports what failed. It never edits code, so the agent that wrote a change can’t also pass it.
- A release agent that turns finished work into a pull request with a preview link.
- A database agent that writes database changes and tests them on a throwaway copy only.
- A documentation agent that keeps the written record in step with the code.
- A security reviewer for every change that touches sign-in, data or the server. It reports and never edits.
Then the loop starts again with the next request.
Why I build
In my day job, the technical side of product management is working with engineering, data science and applied research teams: planning systems with them, weighing trade-offs, and knowing what will be hard before it is. Building my own products on real production stacks keeps that judgment current. I make the same calls I discuss at work, about data models, APIs, test strategy, AI model choice, running costs and failure modes, and then I live with the results. Each project page lists its stack and the technical decisions behind it.
A standard delivery pipeline
Nothing an agent writes goes straight to the live product. Each change is a pull request, and GitHub refuses to merge it until three required checks pass: type checks, lint and unit tests; a production build; and the tests of the data-access rules. That applies to the agents as much as to me.
Every pull request also gets its own private preview, and browser tests open it the way a visitor would. The agent that writes a change never approves it; I do. I judge each change by what it does on its preview, and the checks, plus a security-review agent on sensitive changes, cover the code.
The toolchain
What the current setup runs on:
Building
- Claude CodeThe lead agent and the specialist agents, in cloud sessions
- OpenAI CodexMonolith Ultra, inside the code editor
Shipping
- GitHubPull requests, review, and a protected main branch
- GitHub ActionsThe required checks on every pull request
- VercelHosting, with a private preview for every pull request
Testing
- VitestUnit tests
- PlaywrightBrowser tests, run against each preview
- SupabaseA throwaway local database for testing data-access rules
Least-privilege access
Most of the work runs on temporary machines in the cloud rather than on my laptop. The verifier and the security reviewer aren’t given tools for editing code at all. Agents don’t touch the production database: each database change is written and tested on a throwaway copy, and I apply it to production myself. Keys and passwords for outside services live in the hosting provider’s settings, never in the code.
The riskiest rules are enforced by code, because a written rule can be forgotten. Small guard programs check every command an agent runs, block the ones that delete work or rewrite history, and stop old database changes from being edited.
Incidents become rules
When something goes wrong, I handle it the way an engineering team handles an incident: find the cause, then change the process so it can’t happen the same way again. Each rule in the agents’ written rulebook records the date and the reason. A few from the client portal:
- 1August 14: a fix’s change-log entry went out with unrelated work, but the fix itself was never sent to GitHub. For two days the record said it had shipped when it hadn’t. “Shipped” now means confirmed on GitHub, and a script checks it.
- 2August 18: a broken version went out, because two agents had edited the same file and one saved the other’s unfinished work along with its own. Now each agent works in its own copy of the code.
- 3September 25: the rule to check each change exactly as it would ship kept getting skipped. It became one command, and now the same check runs automatically on every pull request, where it can’t be skipped.
- 4September 30: notices and side threads had made the chat hard to follow. Messages are now quiet by default, each one ends with the single thing I need to do, and a page lists everything waiting on me.
- 5October 4: a research write-up arrived full of jargon. Now an agent that wasn’t part of the work reads anything meant for me first and flags what I wouldn’t follow.
Handling outside text
Text from outside, like written answers from people testing the product, can hide instructions aimed at an AI. This is known as prompt injection. So outside text is treated as untrusted: it’s summarized on its own, nothing in it is acted on directly, and any change it suggests comes to me as a question.
When I want a second opinion from another AI tool, it gets copies of the docs with private details removed automatically, and a check blocks the copy if it spots anything sensitive.
A record of every decision
A long AI conversation eventually condenses itself to make room, and details get lost. So the lead agent keeps a status file of what’s in progress, what’s waiting on me and what’s been decided, and rereads it after its memory has been condensed. Every plan is saved with my original request word for word, every change adds a change-log entry, and design decisions are kept as decision records with their status.
How this changed
I started the way most people do: an AI assistant in the code editor on my laptop, one prompt at a time. Monolith Ultra was built that way with OpenAI’s Codex, and so were the first six months of Safe As Houses, with Claude Code. Several chats worked in the same copy of the code, every change went straight in without a pull request, and work stopped when I closed the laptop. The August incidents above came out of that setup.
In late September I moved Safe As Houses to cloud agents, with every change going through a pull request, required checks and a preview. Aether and this site were built with cloud agents and pull requests from the start.
By the numbers
- Commits to the client portal since March
- 354
- Pull requests merged since late September
- 91
- Unit tests
- About 1,100
- Plans, each saved with my original request
- 134
- Change-log entries
- About 340
- Recorded design decisions
- 55
Side projects

My business · Client portal and website · Side project
Safe As Houses: a client portal and website for my digital security advisory
Safe As Houses helps people make their digital lives secure and recoverable. I built its client portal and public website alone with Claude Code. Since late September, every change has gone through the same review-and-test pipeline a software company would use.
354 commits since March · 91 pull requests since late September
- Next.js
- Supabase
- PostgreSQL
- Anthropic API
- Vercel

Fitness · Phone app · Side project
Aether: a strength-training app with no App Store and no subscription
Workout logging and well-known training programs in one free app. It installs from Safari, works offline and keeps its data on the phone.
12 training programs · 258 exercises · $0 to run
- React
- TypeScript
- Progressive web app
- Vitest

This website · Next.js on Vercel · Side project
This website, built in conversation with Claude Code
A portfolio built on my business’s design system: pre-rendered, fast, and ready for live demos.
Live two days after the first line of code
- Next.js
- React
- Tailwind CSS
- Vercel

Music · Spotify · Prototype
Monolith Ultra: an AI planner for a messy Spotify library
It reads a large Spotify library in stages, lets me set firm limits first, then has Claude plan new combined playlists, without ever deleting an original.
- Python
- FastAPI
- React
- Anthropic API
The eBay case studies are on the Work page.