←Back to Writing

One night, five agents: shipping Glyphbooth

How a plan, a task contract and one management rule turned an idea into an open-source desktop app by morning

Mustafa Sarac••7 min read•Türkçe oku
Glyphbooth turning an animated orb into green ASCII art
Glyphbooth redraws a scene as ASCII characters. The picture moves with the beat.

What it is

Glyphbooth turns your camera, screen, a video, an image or a typed word into live ASCII, dither, halftone, braille or pixel art. The picture reacts to music. You can save a PNG, record a WebM video, or copy the frame as plain text.

It runs in the browser and as a desktop app for macOS, Windows and Linux. It is MIT-licensed. The renderer is raw WebGL2 shaders, with no graphics library.

This post is the build story. It covers one night in Cologne, from 5 to 6 October 2026.

The brief

My request to Claude (Opus 5.5) was short:

  • Plan an interactive, downloadable product inspired by Luis Bizarro's Visualizer.app.
  • Take the idea further.
  • Ship it as open source by morning.
  • Use my Prompt Atlas for the plan.

The Prompt Atlas is my collection of prompting and learning cards, in English and Turkish. The plan used three of them.

The plan: three techniques, one example each

The plan is in the repo: docs/PLAN.tr.md.

1. Task contract. Write down the goal, the inputs, the output and the finish line before any work starts. The finish line for Glyphbooth was:

npm test and the end-to-end smoke test pass. The app opens with no console errors. Every mode and every source draws at least once.

This line later became the test suite. The agents had a target they could check.

2. Premortem. Assume it is morning and the launch went badly. List the reasons. One row said: the user denies camera access, sees a black screen and leaves. The countermeasure: ask for no permission at start. Play a demo scene and a built-in beat instead. That is how the app works today. You press C when you want the camera.

3. Uncertainty contract. When information is missing, pick a sensible default and write it down, so nobody waits for a decision at 3 a.m. One written assumption: the macOS build is not signed by Apple, and the README explains the first launch. Keep this one in mind. It came back later.

The rule changed mid-flight

Claude wrote the plan. Then it wrote the first scaffold itself: state, the WebGL2 renderer and shaders, the audio engine and synth, sources, export and the control panel. That first commit landed at 01:59. It added 23 files and 3,573 lines, not counting the lockfile.

Then I stopped it. I said: don't write alone. Have subagents write. You plan, you manage them, you pick their models. That is the standard rule.

From that point on, subagents wrote all the code. The orchestrator planned the work, gave each agent its own files and checked every round. It looked at screenshots and ran the tests itself.

I think this is the most useful part of the story. The tools did not change. The rule did.

The agents

AgentModelWhat it did
Integrator (frontend lead)OpusBuilt the app shell and controller, then four rounds of visual and robustness fixes.
Desktop and CI (DevOps lead)SonnetElectron shell, icon, CI, GitHub Pages and release workflows, macOS signing.
Tester (QA lead)Sonnet154 unit tests and 9 Playwright end-to-end tests. Later diagnosed the CI failure.
Writer (technical writer)SonnetREADME in English and Turkish, and the script that captures the README images.
ReviewerOpusRead-only review before release. 14 findings, 1 blocker.

Each agent owned a separate set of files. Within a round, every file had exactly one owner. The commit subjects show the roles: (FRONTEND-LEAD), (QA-LEAD), (DEVOPS-LEAD).

What review and CI caught

In screenshots (orchestrator). The ASCII edge glyphs | / - \ were too dominant. Light palettes flooded the scenes with ink. The frontend agent made the edge outlines sparse and stopped inverting tone for scenes (ff00970, 9314b5e).

In tests (tester). Two real bugs in the source. The HTML export did not escape the page title correctly. The audio band energy returned values for a band above the Nyquist frequency. Both were fixed in ff00970.

In review (reviewer). Fourteen findings. The blocker: the macOS app was unsigned, so on Apple Silicon it showed as "damaged" and would not open. The uncertainty contract had accepted "unsigned" as a default. The premortem had listed the risk, but its countermeasure was only documentation. The DevOps agent added ad-hoc signing (94031ac). The frontend agent fixed the robustness findings (c2e863d).

In CI (GitHub Actions). The end-to-end tests passed locally and failed on GitHub's runner. The runner has no GPU, so WebGL ran in software at about 1 frame per second. The tester added a ?quality=low mode that only the tests use (PR #1). The same work showed that recordings shorter than about 2 seconds produced an empty file. The app now records at least 1 second and shows "Recording was too short" if the file is still empty (e7fe0fe).

After release (me). The v0.1.0 Mac build is ad-hoc signed. It opens, but macOS says Apple could not verify it, because ad-hoc signing is not notarization. The DevOps agent prepared Developer ID signing and notarization (5967f31). It waits for my Apple Developer membership.

Numbers

WhatValue
Commits on main during the night (01:59 to 03:07)12 (plus 3 inside PR #1, squash-merged)
Unit tests154 in 6 files (Vitest)
End-to-end tests9 (Playwright, fake camera)
Review findings14, of which 1 blocker, all fixed
CI runs that failed before green3
Release assets in v0.1.04: macOS arm64 and x64 .dmg, Windows .exe, Linux .AppImage
First commit01:59
Last code fix of the night03:07, CI green on main at about 03:09
v0.1.0 published09:10

All times are Cologne time on 6 October. Git only shows the work after the first commit. The plan and the scaffold came before 01:59.

What I'd do differently

  1. Set the rule before the first line of code. The scaffold was written by the same agent that planned it. Every later commit had a separate author and a separate checker. The first one did not.
  2. Run the end-to-end tests without a GPU before the first push. Three CI runs failed on a problem I could have reproduced locally.
  3. Treat signing as a release requirement, not a README note. The plan wrote the risk down. Writing it down was not enough.
  4. Record the model in each commit. Every agent used the same session co-author line, so git alone cannot show which model wrote which commit. The table above comes from the orchestration log, not from git.

The agents here were Claude subagents. The workflow does not depend on the tool: plan, contract, parallel agents with file ownership, independent review, CI, release.

How a plan, a task contract and one management rule turned an idea into an open-source desktop app by morning