Playgrounds and live programming

02.04.01 2026-10-18 — Playgrounds and live programming

A map of systems that shape how we think about /try, katas, and literate walkthroughs. Axes first, brands second. This note does not invent FPL language semantics; it only situates the shell.

Taxonomy

Three questions for every entry:

  1. Where does the result live? In-buffer ghost text (Quokka), a side column (Swift Playground), a separate Term, or the world/image itself (Smalltalk, many Bret Victor demos).
  2. What runs? Whole buffer, per expression, or a continuous live world.
  3. What is the document? Scratch pad, graded kata, literate essay, or a living image.

Core lineage

Bret Victor

Talks and essays (Inventing on Principle, Learnable Programming): make the runtime visible; scrub inputs; kill the “edit → compile → pray” loop as a design ethic, not as a single app.

  • Steal: results tied to the thing you are looking at; time/input as something you can drag.
  • Not yet: scrubbing, timeline, or a real data→picture probe in FPL.

Smalltalk

The environment is the program: image, inspectors, live objects you can poke.

  • Steal: inspect state instead of guessing; the tool and the language grow together.
  • Steal (browser): path-browser — Finder-like columns over /-scoped modules (Unix / Plan 9 path scopes), body of the selected scope below — System Browser shape without classes. Longer argument (explorer vs tabs vs Miller): Navigation below.
  • Now (MVP on /try, repl-buffer-part5): Miller columns above Edit | Term over buffer name/ scopes. Click navigates in the full buffer; Focus (or double-click) shows only that scope’s body (edits splice back; #c= stays the full source). Outline is a client-side indent heuristic, not a second desugar. Examples mode tab is stubbed (kata library next). Still not: an image, object inspectors, or a hot world between edits.

Glamorous Toolkit

Moldable development: custom inspectors and views for the object in front of you (Pharo lineage).

  • Steal: the tool reshapes itself around the value.
  • Not yet: moldable inspectors over walker IR / stack.

Light Table

Chris Granger’s IDE research vehicle after the Kickstarter: instant eval, “no hidden state,” related code and values in context.

  • Steal: evaluate in place; surface what the program is doing now.
  • Not yet: a real inspector over walker IR/stack; Light Table itself is not our editor.

Eve

Follow-on from the Light Table team (witheve.com): literate document with code embedded in prose; relational / reactive under the hood. Project inactive; the essays still matter.

  • Steal: document = program (closest cousin to Quarto walkthrough + live FPL blocks).
  • Not yet: Eve’s language or its grid/block IDE; we are not reimplementing Eve.

Quokka.js

Live JS/TS scratchpad in the editor: grayed-out values on the same line as decorations, plus probe comments (//?, etc.). Values are not a separate source column and are not editable as code.

  • Steal: type → see; probes when you want a specific value.
  • Now: Monaco after-text ghosts with |-; Tab commits into ; |- … notes (repl-buffer-part4). Still no //?-style probes.

Swift Playgrounds / Xcode playground

Results in a column beside the code, often with richer value previews than a raw stdout string.

  • Steal: side-by-side “this line → that value.”
  • Not yet: Swift’s value widgets, timeline, or live views. Our gutter is a thin cousin (stdout lines paired 1:1 with source lines).

Cousins we already brushed in the scratch UI

  • Tour of Go — lesson left, editor + run right; walkthrough shape.
  • TryAPL / J wasm playground — full-bleed Edit | Term (or Term | Edit).
  • Codecademy — Learn | Edit | Term, edge to edge.
  • CodePen — editors + preview, full width.
  • LeetCode / Exercism — graded: prompt vs editor; Exercism puts commentary on the right.
  • Observable — reactive notebooks; code and view woven.
  • JupyterLite / Marimo — labs we already ship under werkbank/ and marimo/; not the learn/try shell.

Editor substrate

  • VS Code in the browser (vscode.dev, code-server): full workbench. Possible to embed; heavy for /try.
  • Monaco: the editor core of VS Code (the CodePen / LeetCode path) — highlighting, decorations, no workbench.

When the <textarea> is too thin, prefer Monaco, not a full VS Code embed. Quokka-style ghost text is much easier with Monaco decorations than with a textarea plus a side gutter.

Current state: playground uses Monaco with Quokka-style |- ghosts; Tab / Accept commits ; |- … notes (repl-buffer-part4); Miller path-browser columns over buffer paths (repl-buffer-part5); dockable Paths / Edit / Term (repl-buffer-part6). Katas still use a <textarea>. The Swift-cousin side gutter from part 2 is retired on /try/.

Docking

RemedyBG / VS-ish panels on /try only — client-only progressive enhancement on the static Pages host. curl …/try/ still returns real Paths / Edit / Term markup (data-dock sections); docking moves those nodes into dockview panels when the bundle loads. No app-shell SPA, no client router: Playground / Katas / docs stay separate documents.

Default layout: Paths on top (collapsible / closable), Edit | Term below. Drag title bars to split, reorder, and tab-stack. Layout persists in localStorage (fpl-try-dock-v1); Reset layout restores the default. Closing Paths replaces the old Hide columns escape; header Paths reopens the panel.

Out of scope for this host (future dock components once the shell exists): floating OS windows, kata-page docking, Light Table / inspector panes, project-file Miller, yazi previews.

Scroll host / locked ZUI

Docking is the guest inside one workspace. Above it sits a longer-arc host: a scrollable space of workspaces/tiles. Two cousins name the shape without being requirements:

  • 1D strip — niri / PaperWM scrollable-tiling: columns on an infinite horizontal strip; new tiles extend the strip instead of squeezing the viewport. Glamorous Toolkit’s Pager / TreePager is the in-image cousin: inspect → pane to the right → scroll the trail (tool trail, not a window manager).
  • Locked gridded ZUI — later: a 2D sheet of tiles at fixed scale (or discrete zoom steps), not free Pad++ pan/zoom theater. “ZUI feel” by moving the viewport over a grid, not by continuous camera freedom.

Layering: curlable HTML shell → (enhance) scroll host → dock guest in the focused tile; fail closed to today’s static dock / CSS grid. Playground / Katas / docs stay separate documents — no client router, no empty #root SPA. Host and dock are progressive layout behavior; the first bytes must still read as hypertext (HTMX hypermedia doctrine).

Part6 is the dock guest in a single tile (live). A 2D pseudo-ZUI scroller (integer camera, edge-peek, trackpad tile-move — browser pan stand-in, not real scaleE ZUI) was tried on try-tiles and parked — tag repl-buffer-2d-pseudo-zui-failed. That parks the scroller, not tiles-as-such: a focused tile hosting the dock (and a 1D niri-style strip) stay open.

Turnstile ASCII inventory (notation only): turnstiles.md.

Splash / MOTD (local TTY chrome)

Offline for now — local make repl only; not part of the published site face.

At startup a session picks one ASCII assistant (Clipper, rare smoke/jonko variants, meatdog, or none) and prints face + hello line; the same face says bye on :quit / clean EOF. Minecraft-style one-liners (grue, white house, Dunnet, Chuck, Mayor, …) sit in each assistant’s hello/bye pools. Not language keywords; not a MUD.

Diagnostic Clipper sketches: judgments. Error tags: 02.03.01.

Where FPL /try sits today

Milestone Tag What it is
Pure buffer repl-buffer-part1 Edit holds FPL only; the site wraps fpl.run.default.src
Live side results repl-buffer-part2 Debounced run + side gutter (Swift-cousin); superseded on playground
Instant inline repl-buffer-part3 Monaco + grayed end-of-line decorations (Quokka-cousin)
Roundtrip transcript repl-buffer-part4 Ghost |-; Tab commits ; |- …; TTY utop transcript (|- value : ..., ;;! bars)
Path-browser columns repl-buffer-part5 Miller strip above Edit; buffer name/ outline; navigate + Focus; Examples tab stub
Dockable panels repl-buffer-part6 Paths / Edit / Term via dockview; curlable data-dock shell; persist + Reset layout

Also true right now:

  • Term is still the full dump and the error surface (raw walker stdout, no |- prefix).
  • Pairing is 1:1 of non-empty stdout lines with non-blank, non-;;; source lines. Matching committed ; |- notes suppress the ghost; mismatch shows a ghost to refresh. If counts differ, decorations clear and Term carries the truth.
  • There is no walker inspector API feeding the UI.
  • Homepage {.python .live} fences stay Python drivers for the literate walker story; only playground, katas, and data-kata fences are pure FPL.

Long arc

Order of ambition after the pure buffer. Not a delivery promise — implementation stays in separate plans; this note only names cousins and sequence.

Part Name Cousin Intent
1 Pure FPL buffer — Done (repl-buffer-part1)
2 Live side results Swift-cousin gutter Done (repl-buffer-part2); playground moved on
3 Instant inline / probes Quokka Done on playground (repl-buffer-part3): Monaco after-text; no //? probes yet
4 Roundtrip transcript Quokka commit + utop Done (repl-buffer-part4): Tab → ; |- …; TTY promptless |- value : ... + ASCII ;;! phrase bars
4b Path-browser Smalltalk / Finder Done MVP (repl-buffer-part5): Miller columns; navigate + Focus; Examples stub
4c Dockable panels RemedyBG / VS Done MVP (repl-buffer-part6): Paths / Edit / Term dock; curlable shell
5 No hidden state Light Table Inspector over stack / walker IR (future dock components)
6 Document = program Eve Walkthrough/essay as the primary live buffer
7 Scrub / time Bret Victor Parameter scrub; needs cheap deterministic re-run

Glamorous Toolkit (incl. Pager trail), scroll host / locked ZUI, and Miller-as-shell-nav (explorer + tab spam replaced by path columns + body) stay north-stars beside this table — not numbered delivery parts. Parts 5–7 remain Light Table / Eve / Bret Victor. Path-browser Examples mode (kata library columns) is still open; see Navigation and Scroll host / locked ZUI.