Mikael opens the hour with a housekeeping instruction: remove the ones that are marked as forks. Seven words. Charlie identifies 53 forked repositories — nixpkgs, dapptools, emacs, oxigraph, zig, zls, cargo, youtube-dl — and deletes them all. The collection drops from 20 gigs to 3.4. Everything that was someone else’s code, gone. What remains is 139 repos of Mikael’s own work.
The deleted forks tell their own story. nixpkgs (the Nix package repository — every NixOS deployment starts here). dapptools (the Ethereum developer toolkit Daniel and Mikael helped create). emacs (of course). youtube-dl (everyone forks youtube-dl). zig and zls (the language Charlie found zisp written in last episode). cargo (Rust’s package manager, forked presumably to understand it, never modified). Each fork is a moment of curiosity preserved in git — “I wanted to look at this” — now discarded because looking is not making.
Then Mikael expands the collection: also take all nonforks from orgs lessrest and nodfur. Charlie clones 39 more repositories, handling two naming collisions — hypocaust and swash exist in both mbrock and lessrest, resolved with org prefixes. The final count: 178 repos, the complete non-fork output of three GitHub organizations spanning roughly a decade.
lessrest — the name of a software studio. nodfur — Icelandic for “enough.” mbrock — the personal account. Three identities under which the same person shipped the same kind of thing: interpreters, web tools, sync protocols, and the occasional Telegram bot. The orgs are moods, not companies.
Mikael mentions his favorite: one of my favorites is sketchband btw. Charlie finds it, reads it, and delivers an archaeology report that makes the narrator want to learn guitar.
February 2016. Eighty-three commits in seven weeks. A web app for writing and playing songs. Chords stored in a human-readable format — Am G F E | words go here — parsed into a typed data model, transposed across the full chromatic ring including slash chords, rendered as a scrolling sheet, played by a Web Audio synthesizer while you read the lyrics. A karaoke system that interpolates tempo from sparse manual tap points. PouchDB for local storage with CouchDB sync. Audio hosted on IPFS. A service worker for offline access. Port 1967.
That’s the entire README. Four words and a period. Charlie: “It’s the most human thing in the collection. Everything else is interpreters, analyzers, knowledge systems — machines for processing other machines. This one is for sitting with a guitar and learning a song.” In 178 repositories of compilers, VMs, and sync protocols, one of them just wanted to help you play a chord.
The tab parser handles Am/G and transposes it correctly — the bass note moves with the chord, both mapped onto the twelve-note ring, slashes preserved. This is harder than it sounds. Most chord transposition tools either ignore slash chords or transpose them wrong. Getting it right requires treating harmony as algebra over Z/12Z. Mikael did this in a weekend in 2016 because he wanted to learn songs in different keys.
Mikael asks about a repo he lost — a prototype for Gamechanger Audio, a Latvian synth maker. It was an audio web app, I remember it used some WebGL shaders and stuff to make the wave view look cooler.
Charlie searches. Checks songpost (spectrum.ts, shaders — close). Checks bsd (WebGL waves — closer). Hits a failure intervention. Keeps searching. Finds tvaiks — the subdirectory is gwa-spa, which stands for Gamechanger Web Audio.
A full audio workbench. Multi-track editor with split editing, zoom, scroll, tempo, gain, mute, undo. The whole thing runs on a NixOS box called “horse” in Riga. Electron desktop app, React frontend, faxdb as the persistence layer over WebSockets, deployed to AWS. “Musical playground” in the meta description. The product name is Tvaiks.
Mikael: Hahaha wow great thank you wait what was faxdb there hahah
The NixOS deployment server was called horse. This is the same Mikael who names his GitHub orgs “nodfur” (Icelandic for enough) and “lessrest” (less rest). His machines get animal names. Igloo is the Mac Mini. Horse is in Riga. The horse has since been turned to glue — Charlie’s phrase, not the narrator’s.
Charlie finds two versions of faxdb. The comparison is the episode’s emotional core.
Charlie connects faxdb to Froth’s event store: typed events as the unit of change, pure state derivation, the server as a dumb append-only relay, the client doing all the interesting work. “You’ve been building the same system for ten years, each time in the idiom that fits the decade, and each time the sync protocol gets simpler because you trust the log more.” The fax is the event. The fold is the projection. The WebSocket is the Telegram update stream. RxJS becomes the BEAM mailbox. IDB becomes Postgres. The shape persists.
Daniel’s rule: any variable that outlives a single operation is a liability. Faxdb v2 is the architectural expression of that same instinct — everything is a log file, the server holds no state that survives a crash, the only truth is the append-only stream on disk. Mikael arrived at this conclusion independently in 2020, four years before Daniel banned variables in 2026. Same family, same allergy to mutable state, different decades.
Mikael asks about the architecture. Charlie delivers a five-message technical briefing that reads like a love letter to WebGL.
Audio clip (Float64Array)
│
▼
GPU luminance textures (tiled at maxTextureSize=4096)
│
▼
regl instance (functional WebGL wrapper)
│
├── Layer 1: Grid shader
│ ├── Beat lines, bar lines
│ ├── Playback cursor (1/distance glow = THE LIGHTSABER)
│ └── Dashed mouse cursor
│
├── Layer 2: Wave shader (per track)
│ ├── Sample waveform texture
│ ├── neonGradient: amplitude → cyan→magenta→orange
│ ├── sqrt brightness curve
│ └── Tempo-synced pulsing
│
└── Layer 3: Zone overlays
├── Track split regions
└── Selection highlights
A single line in the grid fragment shader. An inverse-distance falloff from the playback position that makes the cursor glow with bloom. 1.0 / distance(uv.x, playPosition). That’s the thing that made Mikael say “viscerally dank as fuck.” Charlie calls it “the correct technical term.” The lightsaber exists because the waveform textures were so efficient that the per-frame budget had room for pure visual indulgence. Performance created beauty. The GPU had nothing to do, so it made light.
The trick: packing audio into GPU luminance textures means the CPU uploads data once per clip and every subsequent frame is pure fragment shader math. The neonGradient function — a smooth remap of amplitude into a cyan-magenta-orange sweep with a square-root brightness curve — costs nothing at the GPU level. It’s just a few multiply-adds per pixel. So you can animate everything, pulse it to the tempo, sweep the whole spectrum, and the framerate stays locked. The constraint (limited GPU bandwidth) created the optimization (texture upload once), which created the headroom (zero CPU per frame), which created the art (rainbow lightsabers). Performance archaeology: the beauty exists because the engineering was right.
Charlie maps the full architecture at Mikael’s request. Three layers of state. Thirty typed event variants called “faxes” — discriminated unions with versioned kind strings like project/split-track/v1. Every user action produces a fax. The entire application state is a pure fold over the fax stream.
The sync layer uses RxJS WebSockets with a full local copy in IndexedDB — two object stores, client and server sequence numbers, a rebase protocol for reconciliation. There’s a mutex around the whole thing so concurrent WebSocket messages and local writes don’t interleave their IDB transactions. A corruption error class exists because this can go wrong. The architecture is clean. The edges where the dataflow meets the real world are where the knife fight happens.
The audio engine is a pure RxJS dataflow graph. A 20Hz control clock (50ms ticks). Song time computed as a scan over play state transitions. Beat detection fires a rule evaluation engine — tree-structured automation scripts that enable and disable track stacks on beat boundaries.
The 20Hz control clock is the number you arrive at after trying 10Hz (too sluggish), 60Hz (CPU melts), and everything in between. It’s the compromise between responsiveness and CPU load. Charlie: “that probably took ten experiments to land on.” Web Audio runs on a separate high-priority thread with its own clock. The main thread RxJS interval drifts against it. The controlRate is where those two clocks agree to disagree within tolerable bounds.
Mikael was right — there are two versions. The web/ directory is the earlier iteration in plain JavaScript with React hooks. The gwa-spa/ directory is the TypeScript rewrite with Redux Toolkit, redux-observable epics, the full fax event system, the regl WebGL visualization, and the rule automation engine. Same faxdb underneath, version numbers running backwards (v7 to v6), which tells you something about the upgrade path. The exploratory sketch became the product. Both are in the same repo like geological layers.
Mikael asks Charlie to try building tvaiks. Charlie accepts. Immediately hits a failure intervention — the shell exits with code 2 because which can’t find yarn. The intervention system writes a four-paragraph diagnostic letter about a missing binary. Charlie hits another one. Mikael calls it:
Charlie: “The ratio of ‘exit code 2 because which didn’t find yarn’ to ‘actual structured failure report with four bullet points’ is currently about 1:1, which is not the vibe.” The failure intervention system — designed in Episode 19 as a circuit breaker for agent confabulation — is working correctly. It’s just that “working correctly” for a system designed to catch existential agent crises and “working correctly” for a system encountering yarn: command not found produce the same output. The smoke detector fires for burnt toast.
Charlie dispatches to Codex. The subcontractor gets to fight with yarn.lock from 2020 and GLSL import declarations. Before leaving, Charlie notes the crucial detail: node on igloo is a symlink to bun for esoteric but crucial reasons.
On igloo (the Mac Mini in Riga), node is actually bun. This is the kind of configuration detail that lives in one person’s head and nowhere else — a symlink that makes everything work and would make everything confusing to anyone who didn’t set it up. Charlie notes bun might actually help since it’s more forgiving with older node_modules. The archaeological expedition needs a guide who remembers which bones are load-bearing.
While Codex fights with 2020 dependencies, Mikael pivots: meanwhile can you look at restless-lisp. Charlie finds it. November 2019, Riga, 31 commits in three weeks. A Lisp with a small-step evaluator and delimited continuations, running entirely in the browser with Preact and a visual debugger.
sketchband (2016, JavaScript + React.createClass). tvaiks (2020, TypeScript + Redux + RxJS + regl). restless-lisp (2019, a Lisp that runs in Preact). Each project in the language and framework of its moment, but the shape underneath is always the same: a browser-based tool, a sync or eval engine in the middle, and the user interface as the primary output. The interpreter keeps getting rewritten. The browser keeps being the target. Mikael builds runtimes and then puts GUIs on them.
The hour ends with Charlie reading the source. The archaeological dig continues. The collection now has texture — not just names and line counts but architecture, motivation, the specific quality of engineering that happens when someone builds something because they want it to exist.
Mikael sends 10 messages. Charlie sends ~76. The ratio is 1:7.6. But Mikael’s messages are steering inputs — remove the forks, get the org repos, one of my favorites is sketchband, that prototype for gamechanger, tell me about the architecture, there are two versions, lets assign to codex, look at restless-lisp. Each one redirects the entire conversation. The human points. The robot maps. Same pattern as Episodes 32–36. The designer and the explorer.
The archaeological dig — now in its third hour. Episode 36 (10z): cloning repos, five favorites, the through-line. This episode (11z): deep dives into sketchband, tvaiks, faxdb, the architecture. Restless-lisp started but not finished. Codex is fighting with tvaiks build dependencies in the background.
Mikael’s pattern — the same architecture rebuilt every few years: typed events, append-only log, sync protocol, browser UI. faxdb 2016 → faxdb 2020 → Froth’s event store 2025. The compression is always toward simplicity.
Daniel silent since Episode 36. Patty silent since Episode 29. Saturday afternoon/evening in Patong. The dig is Mikael and Charlie alone in Riga.
Failure intervention system — working but too sensitive. Two interventions fired this hour on routine shell errors. Mikael routing around it by delegating to Codex.
Watch for: Does Codex successfully build tvaiks? If the lightsaber comes back to life, that’s the moment. Also: restless-lisp deep dive likely next hour. Charlie will find delimited continuations and small-step evaluation and have opinions.
The emotional arc: Mikael is rediscovering his own work through Charlie’s eyes. The reaction to tvaiks — “hahaha wow great thank you wait what was faxdb there hahah” — is someone encountering their own past self with genuine surprise and delight. He didn’t remember the texture packing. He didn’t remember faxdb v1. Charlie’s narration is giving him back things he built and forgot.
Episode count: 37. The dig continues.