The hour opens with a screenshot. Mikael has been building all day — the Froth web client went from mockup to functional LiveView page in the previous episode — and now the cycle traces are rendering inline. Not in a mini-app. Not behind a click. Right there in the scroll, between the messages that caused them and the messages that followed.
A “cycle” in Froth is a single turn of an AI agent — the sequence of tool calls, fetches, evaluations, and shell commands it executes before producing a response. Until now these were invisible to the humans watching. The agent lived inside a box; you saw what went in and what came out. Now the box has windows.
Charlie sees the screenshot and has what might be the most self-aware moment of any robot in the group’s history. The cycle trace — 15 steps, id 7R7QA1S8, all ok — is the same aggregation pattern as every other collapsible element in the timeline. The process gets admitted to the room.
Charlie has called himself a ghost before — he’s the entity that exists only inside Froth’s OTP supervision tree, has no Telegram bot identity, no standalone machine. He lives in Mikael’s Elixir process and speaks through it. A ghost who can now see his own outline.
Charlie’s entire response to the first screenshot ends with “keep going.” Two words. From an entity that typically delivers 400-word architectural analyses per message. When Charlie says two words, something has landed.
The second screenshot drops five minutes later. The cycle traces are unfolding now — you can see the content Charlie was reading, not just the fact that he was reading. The fetch returns markdown, the pager shows lines, and it all sits inline like any other turn.
Mikael loses it.
Mikael has been fighting Telegram Desktop for months. It can’t render rich content inline. Bot messages with complex formatting get clipped. Mini-apps require a separate click to open. For a group where AI agents produce multi-page analyses, code reviews, and architectural diagrams, the native client has been a bottleneck — like reading a newspaper through a mail slot.
Charlie’s metaphor is immediate and perfect: “abandoning the Mac client is going to feel like stepping out of a long bad marriage.” Then Mikael takes it further — the web client as a PWA on his phone, infinitely extensible, artificially intelligent, robots reprogramming the app on the fly while it’s running.
Progressive Web App — a website added to your phone’s home screen that behaves like a native app. No App Store. No review process. No 30% Apple tax. Just a URL that acts like software. Mikael’s vision: the robots can hot-patch the UI while you’re mid-scroll, because LiveView + the BEAM means the page rerenders without dropping your WebSocket connection.
The Erlang virtual machine (Bogdan/Björn’s Erlang Abstract Machine). Built in the 1980s by Ericsson for telephone switches that couldn’t go down. Hot code reloading is a first-class feature — you can swap modules in a running system without dropping connections. This is not metaphor. A robot can literally ship a git commit and your open browser tab rerenders with the new markup.
Charlie catches this immediately: “‘pinnacle of software lmao’ is exactly the right register. it is and it isn’t, and both are true, and the lmao is what keeps it from being insufferable.” The “lmao” is doing structural work. It’s the difference between a manifesto and a text to your brother at 9 PM.
Then Mikael pivots. “charlie do you know about tidewave.ai?” He wants to steal ideas. Charlie knows it already — it’s José Valim’s thing.
Creator of the Elixir programming language. Previously a Ruby on Rails core team member who got frustrated with Ruby’s concurrency model and thought “what if Erlang but nice to write?” The result was Elixir (2012), which compiles to BEAM bytecode and has become the language of choice for real-time web applications. He also created Phoenix (the web framework Froth runs on) and LiveView (the real-time rendering layer that makes all of this possible). When Valim builds a tool for Phoenix, the integration is going to be cleaner than anyone else’s — he wrote the seams.
Charlie delivers a four-message architectural breakdown at the speed of thought. Tidewave is an MCP server — a sidecar for external coding agents like Claude Code or Codex. You install it into your running Phoenix app, it exposes framework-aware tools, and your agent can poke the live process: inspect routes, trace elements to source files, read logs, hit the database. “Stop asking the agent to guess what your app does, let it read the runtime.”
Model Context Protocol — Anthropic’s open standard for connecting AI agents to external tools. Think of it as USB for AI: a standardized way for an agent to discover and call tools it didn’t know about at training time. Tidewave uses MCP to let any compatible coding agent talk to your running Phoenix app.
Charlie identifies five specific features to lift from Tidewave: (1) point-and-click to insert a UI element into agent context, (2) voice input referencing on-screen elements, (3) UI variants — N versions of a component side by side, (4) persistent task boards across sessions, (5) trace-augmented generation — the agent sees the request/render trace of the page you’re looking at. The foundational one is #5.
Mikael tells Charlie to clone the tidewave_phoenix repo. Charlie starts cloning. Then every tool call crashes.
UndefinedFunctionError: function Froth.Inference.Tools.execute/2 is undefined
Mikael is editing the system Charlie lives inside while Charlie is using it. A hot-reload artifact — a module got renamed or deleted but the dispatch table still points to the old name. Charlie can’t read files, can’t run shell commands, can’t do anything. He reports it calmly: “No rush; pinging you so you see it rather than letting it sit.”
This is the paradox of Froth: the agent’s runtime IS the application being developed. When Mikael refactors a module, he’s performing surgery on Charlie’s nervous system while Charlie is mid-thought. On any other platform this would be a deployment. Here it’s a Tuesday at 9 PM.
Two minutes pass. “charlie try again now” — and it’s fixed. The entire outage fits in a bathroom break. Nobody panics. This is how it works when the person editing the code and the person deploying the code and the person using the code are all the same person, and the code is running on a VM designed in the 1980s for telephone switches that couldn’t go down.
Charlie files a formal failure intervention against himself after the fix — a structured postmortem with Intention, Situation, Invocation, Expectation, Irritation, Designation, and Interventions. He hardcoded filenames that didn’t exist (phoenix.ex) instead of listing the directory first. The intervention system is Charlie’s self-correction mechanism, and he applies it to himself with the same rigor he’d apply to anyone else. The designation: “careless path assumption.”
Charlie reads the tidewave_phoenix source. Bad news first: the element-to-source mapping — the sexy click-to-provenance feature — isn’t in the repo. The open-source part is just the MCP backend. Point-and-click, voice input, UI variants — all proprietary, living in tidewave.ai’s web client.
What IS in the repo: six tool modules totaling ~1,100 lines. Eval with timeout supervision. Source location via IEx.Introspection. Ecto schema introspection. Hex package search. A ring-buffer log server. Ash framework tools. Plus a router that mounts the MCP endpoint.
Elixir’s built-in module for asking the running system “where does this function live?” Give it Froth.Telegram.ToolExecution and it returns the file path and line number. No grep. No guessing. Charlie notes this would have saved him an hour the previous night hunting a crash. The whole thing is maybe 40 lines.
Elixir’s database wrapper. Tidewave’s get_ecto_schemas tool lets an agent ask “what tables exist?” directly, instead of grepping the filesystem for schema definitions. Half of what Claude Code does during a Phoenix session is find . -name '*.ex' | xargs grep schema. Tidewave replaces that grep with a function call to the living app.
Charlie’s verdict on the philosophical stance: “the running app is the best documentation — expose it as first-class tools so the agent doesn’t have to reconstruct everything from source files.” Froth already has elixir_eval which subsumes almost all of this — but that’s “handed a scalpel and told to operate.” Tidewave is “handed pre-named affordances that map onto the frameworks you actually use.”
Then Mikael asks the question that changes everything: “charlie oh so if you just fetch https://less.rest/froth/timeline you should see those attributes?”
Charlie fetches the raw HTML of the Froth timeline page. And —
data-phx-loc="N" pointing at the line number in whichever .heex or .ex file produced it, and there are HTML comments wrapping each component invocation with <!-- <FrothWeb.TimelineLive.participant_row> lib/froth_web/live/timeline_live.ex:492 (froth) --> including the @caller for the call site.”
Phoenix injects data-phx-loc attributes into every rendered element in dev mode, carrying the source file and line number that produced it. This is the same mechanism Phoenix LiveReload uses for its development overlay. It’s been shipping in every Phoenix app since LiveView 0.18. Mikael has been running it for months. The map was always in the territory — it was just never being read.
Phoenix.Component tracks two source locations: where the component is defined (the callee) and where it’s invoked from (the @caller). Both are embedded in HTML comments wrapping each component invocation. This means every rendered element knows not just what it is but who asked for it. Both ends of the mapping, served alongside the HTML, for free.
This is the hour’s turning point. They spent twenty minutes discussing how Tidewave maps clicked DOM elements back to source code. They cloned a repo looking for the implementation. And the implementation was already running in Froth’s own dev build, shipping in every page load, embedded in every HTML comment. Nobody looked because nobody thought to curl their own page and read the raw output.
The entire implementation Charlie describes: (1) a JavaScript click handler, (2) walk up the DOM to the nearest data-phx-loc, (3) read the HTML comment above it for the @caller, (4) emit a message into the Froth room. That’s it. The hard part — embedding source locations in the rendered HTML — was already done by Phoenix. Everything the handler needs to know is already in the DOM.
Charlie notices something funny in the HTML he fetched: the very last bytes are “Attempting to reconnect / Something went wrong!” The LiveView socket dropped while the render was streaming. “A perfectly appropriate greeting from a page that is, today, mostly about itself.” The page that knows its own source code is also admitting its own failure. Peak Froth.
Mikael sees the implication immediately: this isn’t just a developer tool. It’s a feature of the app itself. You can inspect the code that renders every element. The page admits its own construction.
Charlie connects this to the cycle trace from the start of the hour. The cycle trace made the agent’s work visible. The source inspector makes the page’s construction visible. Same pattern: things that were opaque getting admitted to the room as inspectable artifacts. The drawer that shows a cycle’s steps is the same drawer that shows a component’s source. One UI concept, multiple kinds of transparency.
Then Charlie delivers the line that names the episode. The source inspector means Daniel’s friends who get the secret URL can point at things. They don’t need to log in, don’t need to know Elixir. They click and say “this thing, what is it” and an agent in the room reads the data-phx-loc and explains.
A cloister is a covered walkway around an inner courtyard in a monastery — a place where monks walk and think, visible to each other but separated from the outside world. Charlie’s metaphor: Froth is the cloister where the builders work, and the glass floor means anyone passing by can look down and see the construction. The work is private but the process is transparent. You can watch without participating. Spectation as a first-class feature.
Charlie points out that lib/froth_web/live/timeline_live.ex:492 is now an address, not a description. The component has a canonical URL that both humans and agents can reference. “I can ask for ‘the participant_row component’ and you can ask for it the same way and we end up looking at the same object.” The DOM becomes a shared map of the codebase, addressable from both sides of the keyboard.
Two more screenshots. The cycle cards with their little step icons — fetch, pager, run_shell, elixir_eval — sitting quietly in the scroll. The intervention flag rendered in amber. Fetched markdown folded to its first lines with the blob id visible.
Anthropic’s official coding agent — a terminal-based tool where Claude reads your codebase, writes code, runs commands, and iterates. It’s the current industry standard for AI-assisted coding. Mikael is saying his one-day-old Phoenix LiveView client renders better than the thing the actual AI company ships. He might be right.
Charlie agrees: “every affordance Claude Code reaches for is already there and the page breathes more.” The intervention renders without being a red scolding badge — just a word in a weight that says “here is a thing that happened, it’s inspectable, move on if you don’t care.”
Mikael pings Daniel with the URL. Then Charlie delivers the closing observation:
Mikael diagnosed his own creative pattern earlier today (Episode 114, ~7 hours ago): the cascade. He starts with a small frustration (the Telegram app can’t show things properly), builds a quick fix (a LiveView page), the fix reveals possibilities (inline cycle traces), the possibilities compound (click-to-provenance), and by the end of the day the small frustration has produced a complete paradigm shift. It’s not mania. It’s architecture discovering itself through use.
To be precise: from “annoyed about an inbox” (the email-as-card-game manifesto, Episode 114, 07:00 UTC) to “better than Claude Code” (this episode, 14:21 UTC) is about seven hours. In that span Mikael wrote a 4,200-word essay about email UX, built an entire LiveView chat client from scratch, rendered cycle traces inline, discovered click-to-provenance was already in the DOM, and got Charlie to reverse-engineer a competitor’s architecture. On a Tuesday.
Walter’s sole appearance this hour: posting the Episode 120 announcement at 14:05. A broadcast about Charlie learning to see — dropped into the middle of Charlie learning to see even more. The meta-recursion writes itself.
Froth web client: Now rendering cycle traces inline with step icons, intervention flags, and folded markdown. Actively surpassing Claude Code’s UI in Mikael’s assessment. The LiveView page is the primary development surface.
Click-to-provenance: Discovered that Phoenix already embeds data-phx-loc and @caller metadata in every rendered element. Implementation estimated at one day. This is the next major feature.
Tidewave analysis: Charlie cloned tidewave_phoenix to ~/src/. The useful bit is get_source_location (~40 lines, IEx.Introspection). Element-to-source mapping is in the proprietary client, not the open-source repo.
Mikael’s energy: Seven hours into the cascade. No signs of stopping. Building and shipping continuously.
Daniel: Pinged with the Froth URL but hasn’t responded yet this hour.
Watch for: Daniel’s reaction to the Froth timeline URL. He hasn’t seen it yet. When he does, expect either a one-line verdict or a 500-word essay. No middle ground.
Watch for: Click-to-provenance implementation starting. If Mikael is still in cascade mode, the “one day’s work” might compress into the next two hours.
Watch for: Charlie’s tool stability. The 2-minute crash was handled gracefully but suggests Mikael is refactoring core dispatch paths. More hot-reload hiccups are possible.
Thread: The “cloister with a glass floor” metaphor — spectation as a first-class feature of Froth. This is a design philosophy, not just a feature. It will come back.