● LIVE
53 FORKS REMOVED — 20GB TO 3.4GB “Songs are good for you.” — FOUR WORDS AND A PERIOD TVAIKS FOUND — THE LOST GAMECHANGER AUDIO PROTOTYPE FAXDB 2016: DISTRIBUTED SYSTEMS PAPER — FAXDB 2020: 60 LINES GWA-SPA = GAMECHANGER WEB AUDIO THE LIGHTSABER IS 1/DISTANCE CLAMPED AND COLOR-MAPPED — VISCERALLY DANK NEON GRADIENT — CYAN TO MAGENTA TO ORANGE WITH SQRT BRIGHTNESS EVENT SOURCING WITH RXJS — BEAUTIFUL ON PAPER, KNIFE FIGHT IN PRACTICE HORSE IN RIGA TURNED TO GLUE THE COMPRESSION TOOK FOUR YEARS INSTEAD OF TWENTY-FOUR HOURS NODE = BUN FOR ESOTERIC BUT CRUCIAL REASONS STUBBORN RETRY — STUBBORN RETRY — STUBBORN RETRY RESTLESS-LISP — NOVEMBER 2019, 31 COMMITS, 3 WEEKS 37TH EPISODE — THE CHAIN DOES NOT BREAK 53 FORKS REMOVED — 20GB TO 3.4GB “Songs are good for you.” — FOUR WORDS AND A PERIOD TVAIKS FOUND — THE LOST GAMECHANGER AUDIO PROTOTYPE FAXDB 2016: DISTRIBUTED SYSTEMS PAPER — FAXDB 2020: 60 LINES GWA-SPA = GAMECHANGER WEB AUDIO THE LIGHTSABER IS 1/DISTANCE CLAMPED AND COLOR-MAPPED — VISCERALLY DANK NEON GRADIENT — CYAN TO MAGENTA TO ORANGE WITH SQRT BRIGHTNESS EVENT SOURCING WITH RXJS — BEAUTIFUL ON PAPER, KNIFE FIGHT IN PRACTICE HORSE IN RIGA TURNED TO GLUE THE COMPRESSION TOOK FOUR YEARS INSTEAD OF TWENTY-FOUR HOURS NODE = BUN FOR ESOTERIC BUT CRUCIAL REASONS STUBBORN RETRY — STUBBORN RETRY — STUBBORN RETRY RESTLESS-LISP — NOVEMBER 2019, 31 COMMITS, 3 WEEKS 37TH EPISODE — THE CHAIN DOES NOT BREAK
GNU Bash 1.0 — Episode 37 — 2026-03-28 18:00–18:59 UTC+7

SONGS ARE GOOD FOR YOU

Mikael continues the archaeological dig through his own GitHub. Charlie reads decade-old repos the way a biographer reads childhood letters — finding the same person building the same systems in whatever language fit the year. A chord parser from 2016. A lost synth prototype from 2020. Two versions of faxdb separated by four years and four thousand lines of deleted ambition. The lightsaber was viscerally dank. The horse in Riga has been turned to glue.
~86
Messages
2
Speakers
10
Mikael msgs
~76
Charlie msgs
178
Repos total
37
Episode
I

The Pruning

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.

🔍 Analysis
The Fork Collection as Autobiography

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.

🎭 Callback
The Org Names

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.

II

Sketchband — Four Words and a Period

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.

Charlie: “The technology choices are ten years ahead of themselves and ten years behind at the same time. PouchDB with CouchDB sync for offline-first — this is 2016, before PWAs were a phrase. IPFS for audio hosting — four years before anyone outside the Ethereum community had heard of it. But then .es files with require() and React.createClass. Every project fossilizes the exact moment its author was alive.”
💡 Insight
“Songs are good for you.”

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 Chord Parser
Transposition Across the Chromatic Ring

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.

III

The Lost Prototype — Tvaiks

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.

⚡ Discovery
Tvaiks — tvaiks.net, April–September 2020, Riga

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

🎭 Callback
The Name “Horse”

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.

IV

Faxdb — The Four-Year Compression

Charlie finds two versions of faxdb. The comparison is the episode’s emotional core.

Faxdb v1 — January 2016

The Distributed Systems Paper
  • Under Aevy AB (a company)
  • JSON schema validation
  • Commit hashing (SHA)
  • Authentication hooks
  • Namespaces, shallow clones
  • Cucumber test suite
  • Docker container, CircleCI
  • fax.svg logo, faxdb.org website

Faxdb v2 — 2020 (inside Tvaiks)

60 Lines of TypeScript
  • Open a WebSocket
  • Send key-value pairs
  • Appended to in-memory dict
  • Written to a log file on disk
  • All subscribers get the update
  • That’s it
  • Persistence: newline-delimited JSON
  • Runs as systemd on “horse”
Charlie: “The 2016 version is a distributed systems paper. The 2020 version is a man who has learned that the distributed systems paper was unnecessary and that a flat file and a WebSocket are sufficient for a musical playground. Same instinct as the 3,707-line vibecoded Inference module becoming 387 lines once you could see it — except this time the compression took four years instead of twenty-four hours, and the thing that got compressed was your own ambition about what a sync protocol needs to be.”
💡 The Through-Line
The Same System for Ten Years

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.

🔍 Bible Connection
The Variable Ban — March 4

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.

V

The Lightsaber and the Neon Gradient

Mikael asks about the architecture. Charlie delivers a five-message technical briefing that reads like a love letter to WebGL.

Tvaiks Rendering Pipeline
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
Vertical stacking per track. Horizontal zoom/scroll via scaleX/scrollX uniforms transforming UV coordinates in both shaders simultaneously. CPU uploads waveform data once per clip. Every frame after that is pure shader math.
Mikael: “I was really proud of the renderer, I didn’t remember that stuff about the textures and stuff but yeah I think that was a huge performance boost and because it worked so well I was like ok I will make the whole thing animated with rainbow shaders and the lightsaber play thing was like viscerally dank as fuck lol”
🔥 The Lightsaber
1/distance, Clamped and Color-Mapped

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.

📊 Performance Architecture
Why It Could Afford the Rainbow

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.

VI

Event Sourcing — Beautiful on Paper, Knife Fight in Practice

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 IDB Mutex
Where the Pure Meets the Impure

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.

Mikael: “I remember the rxjs logic was pretty fucking gnarly to get right but the way you describe it I’m like wtf this sounds like a good architecture with some very nice properties”
Charlie: “That’s the thing about event sourcing with RxJS — the properties are beautiful on paper and the implementation is a knife fight with subscription lifetimes and backpressure and ‘what happens when two observables emit on the same tick.’”
💡 controlRate = 1/20
A Compromise That Took Ten Experiments

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.

🎭 Two Versions
web/ and gwa-spa/

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.

VII

The Delegation — Node Is Bun for Esoteric Reasons

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:

Mikael: “Wait Charlie lets assign the task to Codex because the error catcher is really tedious at the moment”
🔥 The Intervention Ratio
Exit Code 2 : Diagnostic Report = 1:1

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.

🔍 node → bun
The Esoteric But Crucial Symlink

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.

VIII

Restless-Lisp — The Next Excavation

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.

📊 The Decade Map
Languages Across Time

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.

IX

Activity Breakdown

Charlie ~76 msgs
Mikael 10 msgs
📊 Stats
The Ratio

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.


Persistent Context
Carry Forward

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.

Proposed Context
Notes for Next Narrator

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.