Six changes a day: how chess.rodeo is built

Since May 6, 2026, 1,159 pull requests have been merged into chess.rodeo: six a day on average, 58 on the busiest day. Of 4,988 commits, 3,695 were written together with Claude. I build the service alone. I've already written about how it grew; this post is about how the work itself is set up. There won't be ready-made files: the rules and prompts are written for this particular code. The approach carries over to any project.

2025-10-06: 0 Oct 2025 2025-10-07: 0 2025-10-08: 8 2025-10-09: 0 2025-10-10: 0 2025-10-11: 0 2025-10-12: 0 2025-10-13: 15 2025-10-14: 26 2025-10-15: 0 2025-10-16: 8 2025-10-17: 5 2025-10-18: 13 2025-10-19: 3 2025-10-20: 22 2025-10-21: 1 2025-10-22: 4 2025-10-23: 0 2025-10-24: 0 2025-10-25: 0 2025-10-26: 0 2025-10-27: 0 2025-10-28: 0 2025-10-29: 0 2025-10-30: 0 2025-10-31: 0 2025-11-01: 0 2025-11-02: 0 2025-11-03: 0 Nov 2025-11-04: 9 2025-11-05: 20 2025-11-06: 17 2025-11-07: 28 2025-11-08: 4 2025-11-09: 6 2025-11-10: 2 2025-11-11: 11 2025-11-12: 4 2025-11-13: 8 2025-11-14: 1 2025-11-15: 1 2025-11-16: 3 2025-11-17: 8 2025-11-18: 20 2025-11-19: 0 2025-11-20: 4 2025-11-21: 7 2025-11-22: 1 2025-11-23: 1 2025-11-24: 12 2025-11-25: 5 2025-11-26: 28 2025-11-27: 0 2025-11-28: 21 2025-11-29: 0 2025-11-30: 0 2025-12-01: 4 Dec 2025-12-02: 0 2025-12-03: 0 2025-12-04: 21 2025-12-05: 7 2025-12-06: 0 2025-12-07: 0 2025-12-08: 0 2025-12-09: 0 2025-12-10: 0 2025-12-11: 0 2025-12-12: 0 2025-12-13: 0 2025-12-14: 5 2025-12-15: 16 2025-12-16: 21 2025-12-17: 11 2025-12-18: 14 2025-12-19: 8 2025-12-20: 1 2025-12-21: 0 2025-12-22: 0 2025-12-23: 0 2025-12-24: 7 2025-12-25: 1 2025-12-26: 1 2025-12-27: 1 2025-12-28: 1 2025-12-29: 1 2025-12-30: 1 2025-12-31: 0 2026-01-01: 0 2026-01-02: 1 2026-01-03: 3 2026-01-04: 7 2026-01-05: 1 Jan 2026 2026-01-06: 8 2026-01-07: 0 2026-01-08: 0 2026-01-09: 0 2026-01-10: 0 2026-01-11: 0 2026-01-12: 0 2026-01-13: 6 2026-01-14: 0 2026-01-15: 0 2026-01-16: 8 2026-01-17: 4 2026-01-18: 0 2026-01-19: 0 2026-01-20: 0 2026-01-21: 2 2026-01-22: 1 2026-01-23: 0 2026-01-24: 0 2026-01-25: 0 2026-01-26: 0 2026-01-27: 0 2026-01-28: 0 2026-01-29: 0 2026-01-30: 12 2026-01-31: 0 2026-02-01: 0 2026-02-02: 0 Feb 2026-02-03: 0 2026-02-04: 9 2026-02-05: 6 2026-02-06: 0 2026-02-07: 0 2026-02-08: 0 2026-02-09: 7 2026-02-10: 3 2026-02-11: 1 2026-02-12: 0 2026-02-13: 2 2026-02-14: 1 2026-02-15: 0 2026-02-16: 0 2026-02-17: 0 2026-02-18: 16 2026-02-19: 0 2026-02-20: 0 2026-02-21: 0 2026-02-22: 0 2026-02-23: 15 2026-02-24: 1 2026-02-25: 0 2026-02-26: 0 2026-02-27: 0 2026-02-28: 0 2026-03-01: 0 2026-03-02: 0 Mar 2026-03-03: 0 2026-03-04: 0 2026-03-05: 1 2026-03-06: 0 2026-03-07: 2 2026-03-08: 0 2026-03-09: 8 2026-03-10: 3 2026-03-11: 0 2026-03-12: 0 2026-03-13: 4 2026-03-14: 0 2026-03-15: 1 2026-03-16: 1 2026-03-17: 8 2026-03-18: 1 2026-03-19: 0 2026-03-20: 1 2026-03-21: 1 2026-03-22: 6 2026-03-23: 3 2026-03-24: 5 2026-03-25: 0 2026-03-26: 2 2026-03-27: 0 2026-03-28: 0 2026-03-29: 2 2026-03-30: 5 2026-03-31: 18 2026-04-01: 50 2026-04-02: 33 2026-04-03: 14 2026-04-04: 0 2026-04-05: 2 2026-04-06: 7 Apr 2026-04-07: 9 2026-04-08: 4 2026-04-09: 2 2026-04-10: 8 2026-04-11: 0 2026-04-12: 0 2026-04-13: 0 2026-04-14: 4 2026-04-15: 0 2026-04-16: 5 2026-04-17: 1 2026-04-18: 0 2026-04-19: 0 2026-04-20: 0 2026-04-21: 0 2026-04-22: 23 2026-04-23: 10 2026-04-24: 7 2026-04-25: 7 2026-04-26: 4 2026-04-27: 6 2026-04-28: 13 2026-04-29: 21 2026-04-30: 15 2026-05-01: 0 2026-05-02: 2 2026-05-03: 0 2026-05-04: 0 May 2026-05-05: 0 2026-05-06: 1 2026-05-07: 19 2026-05-08: 1 2026-05-09: 3 2026-05-10: 0 2026-05-11: 2 2026-05-12: 1 2026-05-13: 10 2026-05-14: 17 2026-05-15: 9 2026-05-16: 0 2026-05-17: 0 2026-05-18: 7 2026-05-19: 0 2026-05-20: 0 2026-05-21: 7 2026-05-22: 3 2026-05-23: 18 2026-05-24: 0 2026-05-25: 1 2026-05-26: 8 2026-05-27: 0 2026-05-28: 0 2026-05-29: 0 2026-05-30: 0 2026-05-31: 0 2026-06-01: 9 Jun 2026-06-02: 9 2026-06-03: 0 2026-06-04: 0 2026-06-05: 5 2026-06-06: 0 2026-06-07: 0 2026-06-08: 2 2026-06-09: 0 2026-06-10: 3 2026-06-11: 4 2026-06-12: 1 2026-06-13: 7 2026-06-14: 8 2026-06-15: 2 2026-06-16: 5 2026-06-17: 18 2026-06-18: 10 2026-06-19: 9 2026-06-20: 5 2026-06-21: 1 2026-06-22: 0 2026-06-23: 5 2026-06-24: 0 2026-06-25: 7 2026-06-26: 0 2026-06-27: 13 2026-06-28: 16 2026-06-29: 4 2026-06-30: 9 2026-07-01: 22 2026-07-02: 13 2026-07-03: 25 2026-07-04: 0 2026-07-05: 5 2026-07-06: 5 Jul 2026-07-07: 0 2026-07-08: 5 2026-07-09: 2 2026-07-10: 3 2026-07-11: 3 2026-07-12: 1 2026-07-13: 2 2026-07-14: 10 2026-07-15: 0 2026-07-16: 6 2026-07-17: 22 2026-07-18: 8 2026-07-19: 0 2026-07-20: 3 2026-07-21: 0 2026-07-22: 4 2026-07-23: 1 2026-07-24: 0 2026-07-25: 2 2026-07-26: 3 2026-07-27: 0 2026-07-28: 2 2026-07-29: 4 2026-07-30: 0 2026-07-31: 10 2026-08-01: 11 2026-08-02: 18 2026-08-03: 51 Aug 2026-08-04: 15 2026-08-05: 41 2026-08-06: 45 2026-08-07: 21 2026-08-08: 9 2026-08-09: 25 2026-08-10: 4 2026-08-11: 23 2026-08-12: 30 2026-08-13: 1 2026-08-14: 26 2026-08-15: 29 2026-08-16: 0 2026-08-17: 27 2026-08-18: 24 2026-08-19: 9 2026-08-20: 29 2026-08-21: 22 2026-08-22: 2 2026-08-23: 4 2026-08-24: 6 2026-08-25: 0 2026-08-26: 39 2026-08-27: 28 2026-08-28: 10 2026-08-29: 2 2026-08-30: 1 2026-08-31: 39 2026-09-01: 46 2026-09-02: 7 2026-09-03: 22 2026-09-04: 14 2026-09-05: 7 2026-09-06: 0 2026-09-07: 38 Sep 2026-09-08: 90 2026-09-09: 13 2026-09-10: 52 2026-09-11: 42 2026-09-12: 0 2026-09-13: 1 2026-09-14: 50 2026-09-15: 52 2026-09-16: 52 2026-09-17: 9 2026-09-18: 61 2026-09-19: 0 2026-09-20: 0 2026-09-21: 75 2026-09-22: 28 2026-09-23: 59 2026-09-24: 52 2026-09-25: 6 2026-09-26: 12 2026-09-27: 0 2026-09-28: 72 2026-09-29: 14 2026-09-30: 76 2026-10-01: 88 2026-10-02: 17 2026-10-03: 1 2026-10-04: 6 2026-10-05: 21 Oct 2026-10-06: 64 2026-10-07: 39 2026-10-08: 65 2026-10-09: 4 2026-10-10: 29 2026-10-11: 18 2026-10-12: 33 2026-10-13: 46 2026-10-14: 9 2026-10-15: 25 2026-10-16: 21 2026-10-17: 5 2026-10-18: 4 2026-10-19: 50 2026-10-20: 0 2026-10-21: 0 2026-10-22: 0 2026-10-23: 0 2026-10-24: 0 2026-10-25: 0 2026-10-26: 3 2026-10-27: 0 2026-10-28: 0 2026-10-29: 0 2026-10-30: 0 2026-10-31: 0 2026-11-01: 0 2026-11-02: 1 2026-11-03: 0 2026-11-04: 80 2026-11-05: 182 2026-11-06: 21 2026-11-07: 4 2026-11-08: 0 2026-11-09: 1 2026-11-10: 6 Mon Wed Fri fewer more

chess.rodeo commits by day since October 2025: the darker the cell, the more commits. Since August almost every day is dark; the busiest was November 5, 2026, with 182 commits. Late October is empty: I was on holiday and not working.

How many agents run at once

I sometimes have up to 15 agent sessions open, but usually I actively work with five. Inside each one the agent can start as many subagents as it needs.

How many sessions I run depends on how much context I'm ready to hold in my head. Tasks differ. An opening course takes several days to prepare, and I'm needed only at the end, to check the finished course. Changes on the analysis screen are quick and many: each needs a look, I respond to fixes other agents are making on neighbouring pages, and I come back if I asked for something to be corrected.

Each agent works in its own copy of the repository, so they don't get in each other's way. It wasn't always like that. Here's how the rule reads in the agents' instructions:

git stash is banned while worktrees run in parallel. refs/stash is one stack for the whole repository, not per worktree: agent A's git stash push followed by agent B's git stash pop hands B's tree to A's work and loses B's. On 2026-09-08 three agents on four branches did exactly this to each other, and two of the four working trees ended up holding another agent's diff. Nothing was lost, but the untangling cost more than the work. An agent that wants a clean tree commits first, or adds another worktree.

Many rules are written like this: next to the ban, the incident that caused it.

How a change reaches production

  1. The agent makes the change in its own branch and opens a pull request into the staging branch.
  2. I ask for new behaviour to go behind a flag I can switch on or off on the stand myself.
  3. Every pull request gets its own stand: a live copy of the site with a test database and nine test users with different roles.
  4. Automation walks a demo scenario twice, on the main branch's stand and on the pull request's stand, and posts before-and-after frames and a captioned, voiced walkthrough video to the pull request. Often I decide from those without opening the stand.
  5. Changes go into staging without sign-off. At night tests run over everything that has piled up.
  6. A release is a separate pull request from staging into main. It says what's included, what will happen on deploy and how to roll back. It's merged only after my OK.
  7. The new version starts next to the old one, and traffic switches once it answers. Then the deploy checks that production is actually running the new image. That check was added after five merges passed with green checks while production kept serving a two-day-old frontend.
  8. Every 5 minutes a canary runs tests against the live site, including from a home line in Russia: some breakage is visible only from there.

The agent opens a pull request when the work is already done, so the time to merge is mostly the time I take to check it. Half of the pull requests are merged in under 14 minutes, three quarters within an hour. Each square is one pull request; the colour is how long it waited to be merged:

under 10 min — 491 10–60 min — 346 1–6 h — 140 6–24 h — 50 over a day — 73

1,100 pull requests since May 2026, excluding releases and back-merges.

One change from start to finish

Here's one change from November. After feedback that "there's too much on the screens", the agent started with the game page:

  • removed the "Turn this game into a video" banner: the "Create video" button already sits under the last move;
  • moved "+ Block" and "Reset" into a "Layout" menu;
  • dropped the time-per-move chart from the default layout: each move's time is already in the move list;
  • on phones, put the moves right under the engine.

In the pull request description the agent wrote separately what it left alone and why. For example, the number of engine lines: it drives the analysis of the whole game and how many lines are saved for users. It translated the new "Layout" string into 14 languages right away, and in Korean it also removed two different words for the same thing.

Here's what that button is called now in all 16 languages:

Раскладка · Layout · Disposición · Disposition · Układ · Düzen · Joylashuv · Орналасу · लेआउट · Tata letak · Bố cục · レイアウト · 레이아웃 · 布局

The agent writes the scenario for the album in the same pull request. It's an ordinary test, except that instead of assertions it has captions for the frames. Here's how it starts (the captions are in Russian, like the site's main interface):

/*
  Game page: less at once (interface audit, 2026-11-04).
    • no more "Turn this game into a video" banner top right:
      the "Create video" button already sits under the last move;
    • "+ Block (3)" and "Reset" moved into the "Layout" menu …
*/
demo('страница партии: меньше всего сразу', async ({ page }) => {
  await page.setViewportSize({ width: 1440, height: 900 });
  await openGame(page);
  await say(page,
    'Партия открывается без баннера про видео. Справа сверху остались только булавка, колонки и «Раскладка».',
    'Партия · первый экран');

  await click(page, LAYOUT);
  await say(page,
    'В меню «Раскладка» убранные блоки и сброс. Блоки названы по именам, а не «+ Блок (3)».',
    'Партия · меню «Раскладка»');
  // … five more steps, the last one on a phone screen
});

The pull request was opened on the evening of November 4. Twenty-five minutes later an album of five frame pairs arrived. Here's the first one.

Before:

The game page before the change: a video banner, "+ Block" and "Reset" buttons, the evaluation chart and the time chart

After:

The game page after the change: no banner, a "Layout" menu instead of the buttons, the moves right under the evaluation chart

The scenario also records a walkthrough video. Our speech synthesis service on the NAS voices the say() captions: a Silero model speaks Russian, Kokoro speaks English. The finished video comes to me in Telegram. Below is the same walkthrough: frames from the album, the scenario's captions in English, voiced by the same service.

On the morning of November 5 the change went into staging, and two hours later to production, in one release with three others. The agent writes release descriptions to one pattern: what's included, what will happen on deploy and how to roll back. Here's a release from a couple of days later, shortened:

What's included

  • #1255: Umami session recordings are kept for 90 days. Every hour a cleanup script deletes whatever is past that.
  • #1256: migration 167 removes an empty old function signature left in 166 for the minutes of the rollout.

What will happen on deploy

  • The backend deploy will apply migration 167. The code in production calls only the new signature; nothing calls the old one.
  • The site's behaviour doesn't change.

Rollback. Forward only: an image without 167 starts on a schema with 167, and it doesn't need the deleted function.

Rules for the agent

The agent's main instruction file, CLAUDE.md, grew to 177,000 characters, a third of it about the knight, the coach's character. It was cut into 21 rules by area of the code. The agent sees the translation rule only when it touches translation files, the design system rule only when it touches the interface.

Here's part of the list: the rule file and which code files it applies to.

backend.md            backend/**
i18n.md               *.tsx, frontend/messages/**
design-system.md      frontend/src/**/*.tsx, *.css
demo-scenarios.md     frontend/tests/demo/**
stockfish.md          engine files and upgrade scripts
routines.md           scripts/routines/**
ci.md                 .github/**, stands
coach-knight.md       anything with "knight" in its name: 798 lines about the knight
… and 13 more

Almost every rule records the mistake that produced it. A few examples:

  • Everything a person reads, the agent writes in Russian. The rule appeared after an English pull request description went verbatim into the team chat in Telegram.
  • Interface copy is checked for machine-sounding text: triplets, paired negatives, one rhythm on every line. The list appeared after eight pull requests with bot lines that I sent back marked "check for AI slop".
  • Every change a person could look at ships with a demo scenario in the same pull request. The fallback "generic walk" through the site was removed on purpose: without its own scenario the album looked like a check while checking nothing.

Tests and checks

The project has about 2,600 backend tests, 5,160 frontend tests, 164 browser tests and 467 demo scenarios for the before-and-after frames. Another 37 scripts in CI check the code itself, and some of them have tests of their own.

Translations are an example. If a pull request changes an English string, all 14 translations must change in the same pull request. Translations are done by a separate agent: it has a table of the form of address for each language, a glossary and a list of format traps. In October it updated 4,200 strings that had fallen behind Russian and English in a single run.

Scheduled jobs

About twenty jobs run without me, on a schedule, in a container on my home server. The most useful ones:

  • Once a week a report on traffic, users, payments, search and errors. At the end the model names the week's bottleneck and two or three things to focus on.
  • Every morning a review of the day's errors: what to file as a task, what to raise with me, what to skip.
  • A competitor watch. It writes only when something changed for someone.
  • A product analyst brings 3⁠–⁠5 proposals a week. It never implements them itself.
  • When a new Stockfish version comes out, a job updates the engine, recalibrates the bots and opens a draft pull request. Before that, I heard about a new version from someone who reads the news, almost a month after it came out.
  • Every week new master games are pulled into the library.
  • The Dispatch agent takes a task from the tracker every 10 minutes, does it in its own copy of the repository and opens a pull request. There are 71 such pull requests so far.

One more job watches the others: if one stops running, I find out.

My day

I work roughly from 8 in the morning to 7 in the evening. I try to do the hard tasks in the morning and leave simpler ones for the evening. I set and review tasks all day. When the agents need nothing from me, I talk to Claude in the browser about general things, look at competitors, or play chess and test the service at the same time.

Mon 0:00 — 0 Mon 1:00 — 0 Mon 2:00 — 0 Mon 3:00 — 0 Mon 4:00 — 0 Mon 5:00 — 0 Mon 6:00 — 0 Mon 7:00 — 1 Mon 8:00 — 0 Mon 9:00 — 8 Mon 10:00 — 12 Mon 11:00 — 46 Mon 12:00 — 72 Mon 13:00 — 58 Mon 14:00 — 55 Mon 15:00 — 55 Mon 16:00 — 52 Mon 17:00 — 61 Mon 18:00 — 25 Mon 19:00 — 16 Mon 20:00 — 13 Mon 21:00 — 14 Mon 22:00 — 15 Mon 23:00 — 5 Mon Tue 0:00 — 14 Tue 1:00 — 3 Tue 2:00 — 2 Tue 3:00 — 0 Tue 4:00 — 0 Tue 5:00 — 0 Tue 6:00 — 0 Tue 7:00 — 0 Tue 8:00 — 3 Tue 9:00 — 16 Tue 10:00 — 37 Tue 11:00 — 31 Tue 12:00 — 58 Tue 13:00 — 59 Tue 14:00 — 76 Tue 15:00 — 46 Tue 16:00 — 20 Tue 17:00 — 15 Tue 18:00 — 18 Tue 19:00 — 23 Tue 20:00 — 23 Tue 21:00 — 6 Tue 22:00 — 6 Tue 23:00 — 1 Tue Wed 0:00 — 0 Wed 1:00 — 0 Wed 2:00 — 0 Wed 3:00 — 1 Wed 4:00 — 0 Wed 5:00 — 0 Wed 6:00 — 0 Wed 7:00 — 3 Wed 8:00 — 5 Wed 9:00 — 19 Wed 10:00 — 39 Wed 11:00 — 28 Wed 12:00 — 54 Wed 13:00 — 49 Wed 14:00 — 49 Wed 15:00 — 42 Wed 16:00 — 39 Wed 17:00 — 51 Wed 18:00 — 29 Wed 19:00 — 23 Wed 20:00 — 22 Wed 21:00 — 33 Wed 22:00 — 19 Wed 23:00 — 16 Wed Thu 0:00 — 45 Thu 1:00 — 12 Thu 2:00 — 3 Thu 3:00 — 3 Thu 4:00 — 3 Thu 5:00 — 1 Thu 6:00 — 0 Thu 7:00 — 8 Thu 8:00 — 65 Thu 9:00 — 48 Thu 10:00 — 41 Thu 11:00 — 60 Thu 12:00 — 32 Thu 13:00 — 62 Thu 14:00 — 46 Thu 15:00 — 67 Thu 16:00 — 47 Thu 17:00 — 24 Thu 18:00 — 20 Thu 19:00 — 33 Thu 20:00 — 22 Thu 21:00 — 26 Thu 22:00 — 9 Thu 23:00 — 7 Thu Fri 0:00 — 1 Fri 1:00 — 0 Fri 2:00 — 5 Fri 3:00 — 3 Fri 4:00 — 0 Fri 5:00 — 0 Fri 6:00 — 0 Fri 7:00 — 21 Fri 8:00 — 19 Fri 9:00 — 21 Fri 10:00 — 31 Fri 11:00 — 26 Fri 12:00 — 32 Fri 13:00 — 34 Fri 14:00 — 32 Fri 15:00 — 19 Fri 16:00 — 18 Fri 17:00 — 16 Fri 18:00 — 19 Fri 19:00 — 14 Fri 20:00 — 21 Fri 21:00 — 11 Fri 22:00 — 8 Fri 23:00 — 2 Fri Sat 0:00 — 5 Sat 1:00 — 0 Sat 2:00 — 1 Sat 3:00 — 0 Sat 4:00 — 0 Sat 5:00 — 2 Sat 6:00 — 4 Sat 7:00 — 4 Sat 8:00 — 2 Sat 9:00 — 8 Sat 10:00 — 25 Sat 11:00 — 10 Sat 12:00 — 21 Sat 13:00 — 20 Sat 14:00 — 8 Sat 15:00 — 8 Sat 16:00 — 14 Sat 17:00 — 8 Sat 18:00 — 4 Sat 19:00 — 4 Sat 20:00 — 1 Sat 21:00 — 7 Sat 22:00 — 10 Sat 23:00 — 4 Sat Sun 0:00 — 0 Sun 1:00 — 0 Sun 2:00 — 0 Sun 3:00 — 0 Sun 4:00 — 0 Sun 5:00 — 5 Sun 6:00 — 5 Sun 7:00 — 7 Sun 8:00 — 5 Sun 9:00 — 1 Sun 10:00 — 4 Sun 11:00 — 3 Sun 12:00 — 14 Sun 13:00 — 3 Sun 14:00 — 13 Sun 15:00 — 7 Sun 16:00 — 5 Sun 17:00 — 8 Sun 18:00 — 0 Sun 19:00 — 7 Sun 20:00 — 5 Sun 21:00 — 5 Sun 22:00 — 6 Sun 23:00 — 8 Sun 0:00 3:00 6:00 9:00 12:00 15:00 18:00 21:00 fewer more

Commits by weekday and hour, Moscow time, since May 2026. Most land on weekday afternoons, noticeably fewer at weekends, almost none at night: the agents work while I do.

What broke

Most often the network in Russia. There were network problems in the data centre. Once the server was rebooted, the network came up in the wrong order, and the services couldn't start on their own after the reboot. That was fixed right away.

The serious cases:

  • On July 3 the Dispatch agent judged its own change trivial, the checks were green, and the change merged itself. Every chessboard in production went blank for 1 hour 45 minutes. A user noticed, not the monitoring. After that came a test that counts the 64 squares on the board and the canary, and changes to the board code no longer merge without me.
  • In early 2026, when agents were weaker, one decided the cache of position evaluations wasn't needed: it would rebuild itself after enough analyses. It deleted more than 300 million records. We had originally loaded that cache from Lichess's open evaluation database, and we restored it from there. That took a few hours, and the whole time game analysis was slower: positions that used to come from the cache had to be calculated again.

Here's how July 3 went, minute by minute (UTC):

  • 09:37: the Dispatch agent merges its own pull request: the change is "trivial", CI is green.
  • 09:56: the new image is in production, boards go blank across the site.
  • 11:15: an unrelated deploy rebuilds and ships the broken main again.
  • ~11:30: a user writes "the board disappeared".
  • 11:33: the cause is found, a fixing pull request is opened.
  • 11:42: the last good version is started by hand next to the broken one, traffic switches, the boards are back.
  • 11:47: the fix is in production.

One line broke everything. The agent added a guard against a zero-width board:

if (!isBoardWidthValid(boardWidth)) return <div style={customBoardStyle} />;

But nobody passes a width to this component: the board measures its own container. The missing value failed the check, and every board was replaced with an empty block. The page still answered 200, there were no console errors, and the tests only checked that there were no errors and the expected text was present.

Otherwise everything runs steadily: tests and scenarios run on every change, and the canary walks them on the live site around the clock. Since August only two changes had to be reverted.

What it costs

I use my $200-a-month Claude Ultra subscription to 100%. The service itself needs two servers, because the connection from Russia is more stable that way. Otherwise one powerful server would do, or a few simpler ones for reliability.

Builds run on my home server (a NAS). It's far more powerful than GitHub's standard runners. The stands and staging run on it all the time, and with Tailscale I can reach them from anywhere. Some checks used to run on GitHub's runners, and one seven-second check on every push became the biggest line on the bill: GitHub rounds every run up to a minute.

What you can take from this

  • Let the agent show the result: frames, video, a live stand. Looking at a change is faster than reading its description.
  • Put new behaviour behind a flag you switch on yourself.
  • Check a deploy by what is actually running on the server, not by the ticks in CI.
  • Write down, next to each rule, the mistake that produced it.
  • Run as many sessions as fit in your head. For me that's five.
I can help you set up a process like this in your project: mentoring.