A stone cottage in west Wales, a newer slate-roofed wing built onto the older building, solar panels on the main roof and a weathered bench by the door

or, a question I couldn't answer for a year

The journey to eta

One idea, carried from the first project to the last: the thing you see on screen is a document — a composed shape — and keeping it truthful against relational tables is the whole problem.

Every one after the first is a clean rewrite rather than a refactor of the one before. Eight of them. I know how that reads — I've read enough post-mortems to know how that reads. But nothing survived a rewrite that hadn't earned the trip, and each was an attempt to say the same thing more exactly than the last.

That is the first line. A second began in March beside it: pears, then pips, now shinko. The same graph of values that watch each other, built by talking to it, and held by people rather than by an app. It has its own sections below, in their dates, and it is the line that ends where the work is now.

Each stage names the Claude model it was built with, read off the commit trailers rather than from memory — except the first two, which predate the trailers recording it. The run from Opus 4.5 to Fable 5.1 is part of this history, not a footnote to it. The work got more ambitious as the collaborator did.

dzql — the problem is named

September 2025 – January 2026 · Claude Opus 4.5

A database-first compiler: declare a domain, compile it to Postgres stored functions, a typed client and generated stores. "Document" meant the denormalised read shape the client holds — a get returned a rich document, and the client patched it in place through a compiled map from tables to paths.

It named the crux and didn't solve it: the view maintenance problem. A write lands. Which of the documents your clients are holding did it just make untrue? I wrote the client side — a compiled map from tables to paths, patching in place. The server side, the part that works out which documents, I never finished.

Everything below is that loose end, being pulled.

A write lands in the tables; two client documents hold copies of it; the dashed arrows asking which of them it touched meet a question mark.

Code: blueshed/dzql

seiro — the thesis is written down

January – February 2026 · Claude Opus 4.6

Commands and events over a single WebSocket. The runtime had no document at all — but the modelling database did, as its hub. Its schema header was the manifesto: documents are central — they're what clients get and update.

The method arrived with it: start from "what does the user see?", sketch the document, and derive the entities from it. Design the screen; let the tables follow. It is the exact opposite of how I had been taught, and of how I had done it for twenty years.

Start from what the user sees, sketch the document, and derive the entities from it — not the other way round.

Code: blueshed/seiro

easy and simple — documents become screens

February – April 2026 · Claude Opus 4.6

A pair of tools: easy to model with, simple to build with. Easy held the domain in a small database behind a CLI and a browsable site, and its entry point was the story — a use case, an actor and an action, linked to the entities and documents that serve it. Design started from what people do.

In simple, documents are screens — one per screen, declared as a root entity plus an expansion tree, compiled into a single database function. And dzql's unfinished question got a declarative answer: which documents a write targets is derived from the expansion trees, carried with the change, merged by the client. The rule of the house: never re-fetch. If you find yourself reaching for a refresh, you have given up on the whole architecture — and it is a very easy thing to reach for.

A screen is one document. Its expansion tree is read to find which documents a write targets, and those are carried with the change.

Code: blueshed/easy · blueshed/simple

railroad and delta — the document becomes a runtime object

March – June 2026 · Claude Opus 4.6, then 4.7

Railroad is a small UI library — signals, JSX compiled to real DOM, no virtual DOM and no build step. It grew a module where a document is a named, patch-synced tree whose identity on the client is a signal: open it by name, get a signal, send changes as three verbs — add, replace, remove — on paths.

Then the deliberate split: railroad gave the module up. It had been the proving ground; delta was the finished thing. Delta made the document the unit of everything — the subscription, the version, the write path, the permission boundary — and composed it in the database from relational tables. Document names became data. And it refused optimistic writes: the echo renders the write. What you see is what actually happened, not what we hoped would happen and would quietly correct later. That round trip is designed, not hidden.

A sequence: the client sends one op and changes nothing; the server composes it from the tables and echoes it back; only then does the client render.

Code: blueshed/railroad · blueshed/delta, both published as @blueshed/railroad and @blueshed/delta

pears and pips — the graph you talk to

March – June 2026 · Claude Opus 4.6, then 4.8, and Fable 5 · beside everything above

A second line began in March and ran beside the first, and for a while it was the livelier one.

pears is a reactive tree. Every path holds a value or code, and a change cascades to whatever is subscribed to it: a cell holds data, a function transforms it in a worker, a bag collects a stream, a cron ticks. The clients were an infinite canvas of cards and a tree browser, and Claude sat in a chat panel that could edit the graph through tool calls. 127 commits, 17 March to 10 June.

pips is the same model rebuilt around the chat — a small reactive compute graph you build by talking to it. It added ai nodes, and a command line that could export a graph and replay it anywhere. 35 commits, 3 April to 10 June.

Both worked, and neither kept what it claimed. When I read them again on 29 September the faults were specific. A function that returned null did not stop the cascade, and the test that claimed to cover it passed vacuously. Each hop of a cascade was its own write, so a crash left a half-updated graph. Undo was a per-path flip-flop that could revert other people's later writes. Identity was a name in the query string. And functions ran as new Function in a worker with fetch, Bun and the filesystem in reach. They went dormant in June; the ideas carried on into the apples and pears specifications.

A cell, a function and a bag wired by subscription, a cron feeding the cell, and a chat panel that writes nodes through the same verbs as any other client.

hjeli — the method gets a proof engine

May – June 2026 · Claude Opus 4.7, then 4.8

The modelling line rebuilt, and sharpened into a thesis: a document is not a view of an entity; it is what an actor sees in order to do a job. Design lives at document altitude — actor and task — and resists the constant pull down to tables and CRUD mirrors.

Where the earlier tool drew diagrams to browse, hjeli runs predicates after every change: is everything reachable; does every write an actor can make echo back into something they watch; does every story have the permissions it needs. Completeness became the product. One proven model lowers onto several different runtimes, and what a target can't express is routed to a named stub rather than half-built. The pull, always, is back down to tables and CRUD mirrors — it is where we are comfortable, and it is where the interesting questions go to die.

Stories make a model; six predicates run after every change; only a model that closes is exported, and then onto three different runtimes.

epsilon — the document totalised

July – August 2026 · Claude Fable 5, with Opus 5

Not a library: a few thousand lines that live in your app. It merged the two halves — the delta is the signal — and deleted the seam that delta and railroad had both kept.

The registry moved into the database itself: one table of documents, one log of changes serving as event log, audit trail and undo log at once. One read path, where the composition function is the permit: if you can't compose it, you can't see it. And dzql's original question finally dissolved rather than being answered — the commit that records a change also bumps, logs and notifies in one place, so nothing needs to work out afterwards which documents were affected.

Anything you render is a document — live, permitted, versioned, because there is no other door.

A JSONB blob tier existed for a while, and was taken out again: in six releases, no app had ever used it.

A read-only view, a list and presence all reach the page through one read path, doc_open, where the composition function is itself the permit.

Code: blueshed/epsilon

zeta — the browser as a terminal

August – September 2026 · Claude Fable 5.1

Epsilon, plus the screen. A screen is itself a document, composed on the server from the app's document by a pure function, sent once whole and thereafter as the same three verbs. The client opens the screen and nothing else.

A gesture is one verb on one path: a node you can touch carries the write it would make, the executor sends exactly that, and the echo recomposes the screen. Nothing that reaches the browser names a function — so there is nothing to call that the declaration didn't already allow.

A pure function composes the app's document into a screen, which is a document as well; a node you can touch carries the write it would make.

apples and pears — drawn and touched

September 2026 · Claude Fable 5.1

Two specifications, written as documents rather than code, and tested in the only way that seems honest: hand the words to a fresh session, see whether the app comes out, and treat every ambiguity, silence and outright error as a finding. Twenty-odd such builds, each cutting a new edition. It is a humbling exercise. Sentences you were rather pleased with turn out to mean nothing at all.

Pears says how a change travels — a graph of nodes that watch each other, with a stated order, and a notification framed by the deepest thing that contains the change. It was devised at iChat in Austin, Texas, in 1995, and written down properly for the first time here. Apples says how a document is drawn and touched: a collection projected onto space, time or colour gives a reading — lanes, calendar, timeline, map, tally — and each reading implies the one gesture it offers. Every row gets the same panel, derived from the declaration, so no reading has to draw a form.

One collection projected onto space, time or colour gives lanes, a calendar, a map or a tally — each offering the one gesture its axis implies.

eta — the kernel

14–17 September 2026 · Claude Fable 5.1 and Sonnet 5

A kernel for live, multi-person apps, made of three things that compose.

Documents. The whole app is documents, each with one read and one patch. A write is a patch: a document, a path, a value.

Render. The server is the only renderer. It turns a document into HTML for one person, and the browser keeps that HTML alive by morphing it, so a re-render never disturbs what someone is in the middle of doing — and a render can be as small as the change.

Applets. Where a page needs behaviour of its own — a figure being dressed, a price board moving — an applet takes its data as props and answers with writes.

What that buys:

It is for small teams and solo builders making live apps where reversibility and legibility matter more than scale. It is not a consumer product at CDN scale, and does not try to be.

How eta was made — four days, sixty-four releases, one dependency, and a review that graded it D.

Three layers — the browser, the server, and documents in SQLite — with a write going down and the echo coming back as HTML.

shinko — the graph that belongs to a person

29 September – 1 October 2026 · Claude Sonnet 5.5 · where the work is now

The plan I wrote on 29 September proposed pears as a package on delta. What was started that night was smaller, and has no tables behind it: a library for a tree of values and formulas that people share. A person is a document that only they can write, and they share a path of it with another person by name. What the other person holds is a live copy, kept up to date, and a formula of theirs reads it as it reads anything else.

Of the faults above it takes two head on, and avoids a third:

The interface is your own Claude. An agent connects as the person, over MCP, under a policy the person ticks: read, change cells, show them. It can't read its own token, widen itself, or show a cell the person didn't.

Three examples ask things of it, as eta's do. A shared sheet in which every cell is private until its owner shows it, to everyone or to people by name. pips again, rebuilt on shinko with the original's canvas and a chat with your own Claude. And the echo, the smallest.

It is 147 commits and 16 releases in three days. The library is about 5,500 lines, the examples about 5,900 more, and there are 2,133 tests — whose rules were then broken one at a time, in a scratch copy, to see that a test failed for each (bar a few that made no difference).

Alice is a document; she shows one cell to bob by name and keeps another private. Bob holds a live copy his own formula reads. Alice's own Claude connects as her, held to what she ticked.

It is not yet what it was started for. It runs as one process on one machine, and that process holds everyone's document, which is the shape this whole exercise is meant to leave. A name is a claim, unless the sheet signs people in with an OpenID Connect provider, and that has never been tried against a real one. It has no users but me. Whether it ends the fragmentation it was started to end is the thing I don't yet know.

The through-line

dzql asked the question. seiro made documents the design centre. easy and simple designed them from use cases and made them screens. railroad and delta made them live runtime objects. hjeli made the method provable. epsilon answered the original question in the schema itself. zeta made the screen a document too. apples and pears wrote down, as documents rather than code, how a change travels and how a collection is drawn. eta made the whole thing small.

The other line is shorter. pears said how a change travels through nodes that watch each other, pips let you build them by talking, and shinko gives the graph to a person, lets people share a path of it by name, and makes the agent one of its readers.

Underneath all of it is one artifact, attempted over and over: a shared state with two faithful readers. Precise enough that regenerating the app isn't a gamble. Legible enough to scroll through with a customer and ask — is this true?

None of the tools is the product. The state is. I expect there will be a theta.

Where a project's code is public it is linked above. hjeli, zeta, eta, shinko and the apples and pears specifications are not: they are in use and not yet released.