Selected outcomesIndependent product
Shoji
A desktop app where a small team of models plans, builds and checks each change, with each step given the model that suits it.

- Role
- Product, interaction and visual design, and engineering across the app, its agent runtime and its website, built with an AI coding agent
- Timeline
- Idea to first public release, 2026
- Stack
- Tauri 2, Rust, React, TypeScript, Bun, Anthropic API, MCP, Vitest
Quick read
Problem
AI coding tools put one model on every step of a change. The strong ones plan well but cost too much to spend on reading files and checking diffs; the cheap ones are fast but plan poorly.
Role
I designed and built all of it: the desktop app, the agent runtime that does the work, the design system and the launch website, directing an AI coding agent through the build.
Intervention
Shoji splits a change into steps and gives each its own model. You see every step and its cost as it runs, nothing is committed until you accept it, and every task leaves a receipt.
Result
In a test on six real tasks, it cost 55% less per accepted change than running every step on the strongest model, and all six were accepted.
A free, open-source app for macOS, Windows and Linux
Routing each step to its own model cost 55% less per accepted change than one strong model, with every change still accepted.
- Cost per accepted change, against Opus alone
- 55% less
- Real tasks accepted, the same as Opus alone
- 6 of 6
- Review verdicts right, planted bugs and clean code
- 24 of 24
Deep dive
Where it started1 of 10
Where it started
I build most of my work with an AI coding agent now, this site included. Watching where the money went, most of it paid a top model to do things a cheaper one does just as well: finding files, summing them up, reading a diff. The judgment that needs a strong model is the plan.
Shoji is the tool I wanted: describe a change, and a small team of models carries it out, each one chosen for its step. It's my biggest project so far, and the first one with a runtime, a desktop shell and a design system of its own.
One model for every step
A change is really a series of steps. Shoji names four: Scout reads the code, Plan writes the steps, Build makes the change and runs the tests, and Review reads the diff and says if it's ready. Then you decide.
| Step | What it does | Model | Cost |
|---|---|---|---|
| Scout | Finds the files that matter and sums them up | Haiku 5.5 | $0.001 |
| Plan | Writes the steps the build follows | Opus 5.5 | $0.071 |
| Build | Edits the code, runs the tests, fixes what they catch | Sonnet 5.5 | $0.025 |
| Review | Reads the diff and says if it's ready | Haiku 5.5 | $0.001 |
| You | Accept it. Nothing is committed until you do. | $0.098 |
- Give each step the model that suits it, and let me change any of them.
- Show every step as it runs, with its model, its work and its cost so far.
- Never touch my checkout or commit anything until I accept it.
- Stop before spending more than I set, not after.
- Prove the savings on real work before claiming them.
Testing the idea first
Before building an app around routing, I needed to know it held up. I took six real commits from one of my own projects and ran each task twice through the first version of the runtime: once routed, once with every step on Opus 5.5. A cheaper run only counts if its change is accepted, so I compared cost per accepted change.
| Task | Opus alone | Routed | Saved |
|---|---|---|---|
| Scroll reset | $0.128 | $0.096 | 25% |
| Folder icon | $0.215 | $0.074 | 65% |
| Title bar buttons | $0.152 | $0.047 | 69% |
| Progress bar | $0.286 | $0.143 | 50% |
| Loading screen | $0.442 | $0.182 | 59% |
| Interface polish | $0.372 | $0.171 | 54% |
| All six | $1.594 | $0.714 | 55% |
All six routed changes were accepted, the same as Opus alone. That became the Balanced stack, the default: Opus plans, Sonnet builds, Haiku scouts and reviews.
The cheapest seat worried me most. A reviewer that waves bad code through makes every saving worthless, so I wrote a check that hands the review seat diffs with planted bugs, like an annual price computed as 20% of the year instead of 80%, alongside clean controls. On Haiku at low effort it got all 24 verdicts right, catching every planted bug and approving every clean diff, for less than half a cent.
Trust you can see
Handing code to a team of models only works if you can see what they're doing and undo it. So a thread shows each step as it happens, with the model behind it and what it has cost so far, and the code opens beside it the moment a file changes. You can ask a question at any point; Scout reads the code and answers, and nothing changes.

Every thread works on its own branch, in its own copy of the project, so your checkout stays as it was and several threads can run at once. When it's done, you accept or revert file by file and commit the rest under your own git name. Shoji never pushes on its own.

Every task leaves a receipt: the model behind each step and what it cost, set against an estimate of the same task on one strong model. The estimate is checked against the spike's real Opus runs, so the savings shown are not a guess.

Your stack, your call
Models change every few months, and the right stack for one project isn't right for another. Stack lets you choose the model and effort for each role, or start from Balanced. The choice is saved to a stack.lock file with its history, so you can see what changed and when.

Changing a stack shouldn't be a leap of faith. A trial replays your latest accepted tasks on the new stack, in scratch copies of your project, and tells you what it would have cost and whether the work still passes. Watching compares each model's week with the four before it and names one that got slower, dearer or worse at its role. The list of models updates once a day from the repo, so a new model needs no new release.

Running several threads at once needs limits that hold. A role can run your project's checks at any time; any other command, like installing a package, waits for you to allow it once, always for that project, or not at all. Each thread has a spending limit, and a daily limit asks before a new thread could pass it.

Darkroom and paper
Shoji is named for the paper screens of Japanese houses: panels that divide a space and let light through. Its design system, Zone, follows that. Panes, groups and figures meet on hairlines with square joins, like a bento box. A choice sits in a shallow tray and the pick rises as a tile. White fill is kept for the one button that moves the work on.
Color carries meaning and nothing else. Red only means running or spending. Green and a softer red only say how something came out, on small marks and short words, never on surfaces. Everything else is ink on a ground, so it turns over cleanly between the two themes.

Darkroom

Paper
Three programs, one app
Shoji is a Tauri 2 app: a React and TypeScript interface in a Rust shell. The agent runtime that plans, builds and checks is a separate TypeScript program, compiled with Bun and bundled with the app, so a crashed run never takes the window down. It also runs on its own from the command line, on any git project.
- The Rust shell owns what touches the system: git worktrees, the keychain, the terminal, pushing with your own git sign-in.
- Each thread gets a git worktree on its own branch. It links to your installed packages instead of installing them again.
- Build can open your page in a headless browser at 360, 768 or 1280 px and check what it shows.
- It reads the same commands, skills, AGENTS.md and CLAUDE.md that Claude Code does, and connects to MCP servers.
- Private files such as .env and keys are off limits to every role, and no usage data leaves your computer.
Every model call goes through one meter, which costs it, logs it and holds it to the thread's limit. It checks before the call, using the most the answer could cost, so a run stops short of the limit rather than discovering afterwards that it went over.
async send(role: Role, step: string, request: ModelRequest) {
if (this.spent + worstCaseOutput(request.model, request.maxTokens) > this.cap) {
// Near the cap, a call may still answer at shorter length,
// as long as that leaves it room to work.
const room = Math.floor(((this.cap - this.spent) / worstCaseOutput(request.model, 1e6)) * 1e6);
if (room < LEAST_OUTPUT) {
throw new BudgetExceeded(
`Stopped at $${this.spent.toFixed(2)}: the next call could pass the $${this.cap.toFixed(2)} limit.`,
);
}
request = { ...request, maxTokens: room };
}
// …send, then record the call's real cost.
}Built by its own team
I built Shoji with Claude Code as my engineering pair. I set the direction, worked out each screen on a design board before it was built, and made every product and design call; it wrote and tested much of the code against that board.
Once Shoji could carry a change through, I gave it its own work. Seven of its early fixes were made by Shoji itself on the Balanced stack, from a step that should show as unfinished when a run stops to a friendlier message when Anthropic rejects a key. Each commit records the models that made it and what it cost: $1.71 for all seven.
Testing
- Over 300 tests. They replay recorded model answers for each role, so the suite never calls a model or spends money.
- A review check that hands the review seat planted bugs and clean controls, with its results kept in the repo.
- An estimate check that compares Receipts' one-model estimate with the spike's real Opus runs, without calling a model.
- Every change builds the app for macOS, Windows and Linux in CI.
- Live development runs on Haiku only, with a hard spending cap.
Outcome and next steps
Shoji 0.1 is its first public release: free, open source under the MIT license, with installers for macOS, Windows and Linux and a website with a film of one change going all the way through. You bring your own Anthropic key.
Next, I'd sign the builds so no system has to warn before opening them, add model providers beyond Anthropic, and run the routing test again on more tasks and other people's projects, since six tasks from one of mine is a start, not proof.
The lesson I'll keep: with AI doing the work, the product is the trust around it. Showing every step, keeping each thread on its own branch and putting a price on every task mattered more than any single model.