::ep0ch · architecture + the last four weeks How ep0ch works A BBS-style terminal door into a programmable outline, and the outline host it calls. One SQLite file per outline; people and agents read and write it through the same actions, always attributed. Read from main at 11e6722 and the live pie and gurgle outlines, Oct 22, 2026, 4:43 AM ET. 26 days, 780 landings, one protocol number 780 landed on main Sep 27 – Oct 22 (#6 → #850) 270 landed Oct 15–21 busiest day: 59, Oct 18 582 roadmap items done 227 queued · 90 in validate 256 wire PROTOCOL schema v7 · no version negotiation §1 ::stack Many clients, one outline host per machine Every client is thin: it calls the host, parses with outline-core, and draws with a renderer that already exists. The host answers resolution, search, backlinks, views, drafts and revisions, so no client implements them again. who calls in You, at a terminal Local, or ssh ep0ch straight into the door. Claude Code agents loki, kitty, cowboy, builders: each writes as its persona. claude.ai and other apps daddy, Codex, ChatGPT, Grok, over MCP with OAuth. Readers on the web Public notes, share links, the signed-in web client. keys · clicks · act · MCP tools · page views clients the door ep0ch The board people call into: screens built from tiles over one note surface. Runs as a session you attach to. packages/door Tree · Detail · Preview The sysop console in Herdr: find any block and fix it. packages/outliner the CLI ep0ch find, show, act, install --apply, doctor. door + outliner the Claude mod Outline and workboard tools, reference links and Recent Mentions in every Claude session. packages/claude-mod MCP gateway OAuth resource server; each outline's mcp access decides read, propose or full. mcp.ep0ch.sh the publisher [publish::…] notes as pages, share links, the browser door. pie.ep0ch.sh · my.ep0ch.sh unix socket · requests + change events · ping checks PROTOCOL 256 outline-core: both sides import it, nobody copies it Pure code, no I/O: the property, header, link and code-fence grammars, the block record, the search matcher, PROTOCOL and the wire types. Change what it matches and the protocol number goes up. one shared vocabulary on both ends of the socket the service outline host, one per machine Serves every ~/outlines/<name>.sqlite by name. It owns the answers, so clients only draw. blocks + propertieslinks + backlinksqueries + facetssearch (Jev ranking)drafts + draft.patchrevisions + undoproposalscomment threadsattributionchange feedEchoNet tosser machine link (outbound HTTPS) · ssh forward · netmail queue for an away machine where it lives float-2 · VPS The outlines and their services: host, MCP gateway, publishers, Litestream. piegurglerotfieldpie-holeecho-* laptop · MacBook Its own host under launchd. float-2 reads it live, or from a read-only mirror while it sleeps; writes queue until it pulls. float-hubsysops-logreadwise float-box · the crew Agents, builders and their worktrees, test runs, and the door behind ssh ep0ch. lokibuildersbox-test Outlines are backed up continuously (Litestream), nightly (restic), and before every ep0ch install --apply. The service and the door are about the same size; the shared core is small on purpose outliner 121k source · 94k tests door 100k source · 71k tests outline-core 14k source · 4k tests claude-mod 7k source · 4k tests sourcetests Lines of TypeScript in tracked files, comments included, at 11e6722. §2 ::consent · ADR 0005 Agents act, nodes mail, readers read Three things reach an outline from outside its own clients. They look alike from far away, so they kept collapsing into one system; ADR 0005 gives each its own gate. Agents act who an agent, as your delegate, now gate ep0ch mcp access: none · read · propose · full lift yolo, only while your own door says so Nodes mail who this outline's own tosser, importing a packet gate its subscription notes: [subscribe::…] never writes another outline's blocks Readers read who nobody writes; a reader only sees gate [publish::…], share links, sign-in never reads the MCP access level Shared: how a change is recorded (attribution, [from::], revisions, undo). Never shared: what permits it. §3 ::act A key, a click and an agent's act take the same path Input arrives A key, a mouse click, a note's button, or ep0ch act from an agent. Mouse and agents are first-class. One dispatcher per screen host The key table names the action (PIE-1173: keys are data, and every hint is drawn from the same table). It also settles standing: a press acts fully as you; a run nobody pressed keeps the agent rules and never takes your focus or keys. The action runs An ActionDef from the screen's ActionSet, with declared arguments and tile= in one grammar everywhere. layout changethrough the screen-layout module's apply: one transaction, a new state or a refusal with its reason note writeto the outline host: the raw text lands first, then references resolve; anything unresolved is a warning with a did-you-mean Recorded Author and actor id (author: agent, loki/claude-code@float-box), a new revision, undo, an event on the change feed. Every client redraws Door tiles, Tree and Detail, MCP readers and the web: each follows the feed, and an agent's change is said on screen. Capture over interpretation: saving a note never depends on every reference, property or component being valid. A refused action keeps your text in front of you, with why and what to do. §4 ::grammar · UI-GRAMMAR.md Inside the door: block, tile, container, screen 1block: content in the outline. Data, never UI. Written in Blockdown: Markdown-adjacent plus [key::value], ((id)), [[page]], ::component. 2tile: a UI leaf that shows one thing (a note, a query, a terminal, a tree). Its kind comes from one registry; extensions register the same way. 3container: split, tabs, columns, dock or flow, each with a policy (locked, accepts, opens-into, agents). 4screen: a screen spec on the desk. Board, river, brief and welcome are all specs, plain data a note can hold. 5host layer: your drawer, kept across every screen; a tile put in it travels with you. 6wire: a tile's select, ⏎ and alt routes to other tiles. As of the one-desk wave, wires point at tile ids, not paths. "Pane" isn't a door word: it means Herdr's or tmux's box. §5 ::identity · doctrine candidate, Oct 22 ep0ch is a postal system: names are addresses, ids are residents [[page]] An address A name you can write before anyone lives there: a reserved lot. It may dangle; it's looked up whenever someone moves in. ((block id)) A resident Identity, not a place. It has to exist, and it keeps pointing at the same block wherever that block moves. tiles The trailer park The path is the lot, the tile id is the registration, and wires are mail to the trailer, never the lot. The test for any new primitive: is this an address or a resident? Wires, embeds, held readers and anything stored should be addressed to residents. §6 ::git log Recent changes: about 30 merges a day, and the door takes most of them Landings on main per day, peaking at 59 on Oct 18 First-parent commits on main by author date, through Oct 21 (Oct 22 had 5 by 3:26 AM ET). Squash merges until Oct 16, merge commits since. Commits touching each package, Oct 8–22: the door leads by almost 2 to 1 door718 outliner370 docs & agent rules256 outline-core248 claude-mod70 Non-merge commits; one commit touching two packages counts for both. §7 ::shipped · Oct 18–22 The last five days, by what changed for you 1Oct 18 A tile can hold a note from another outline, and notes link across outlines (PIE-1056). Select, open and alt-open each get their own wire. 2Oct 19 The laptop reaches its outline over outbound HTTPS (PIE-1058). Runbooks run step by step from a note. Calm frames and x-ray: a tile says what it can do on demand. Big outlines scroll in 2 ms frames, down from 37 ms. 3Oct 20 Deploys reach the Mac over the machine link (PIE-1124). An agent edit that cannot apply is refused like a stale file edit, so the proposal pile stops. The power bar forgives typos. 4Oct 21 Your status bar is a note, with ::button items. Scripts live as named fences beside their button, and a button runs a sequence with one undo. ADR 0007: Sources joins the comment box as one attached surface. Typing :: completes from the component schema. 5Oct 22 Keys are said once, from the tables that bind them (PIE-1173). Ranked search reads its Jev key again (PIE-1195). Review now names the hydra (#846). The one-desk wave (#850): tiles by id across screen, drawer and groups; a press acts as you. §8 ::now · the one-desk wave One button found five bugs; the fix is four owners neat, a status-bar button that arranges tiles, was ruled a probe, not a feature: every failure gets a ticket, and the script is never bent around a bug. Its builder hit the same "is this an agent?" check in three places, so loki paused for root cause. The answer: four questions, one owner each. which tile? Address Tile ids and keys follow tiles through groups and the drawer. ✓ PIE-1192 · #849 who acts? Standing A pressed script acts with your standing, even while you type. ✓ PIE-1186 · #847 where does it land? Placement An open swaps the note in place; the replaced one is born a spine. ◐ PIE-1187 · doing what does it accept? Contract Allowed values and argument rules checked in one place. ○ PIE-1194 · queued The nvim test (Evan, Oct 22): "would nvim bother locking this down?" The invocation carries the authority. The line is who started it, not whether you're typing. §9 ::workboard · pie 582 done, 227 queued, and only five in hand at once unprioritized→queued→doing→review→validate→done Roadmap items by stage, Oct 22 done582 queued227 validate90 unprioritized35 doing4 review1 Validate means merged, with a named verification gap that an agent owns. Done needs linked proof. §10 ::crew How a change gets made TicketPIE-n with a Parts-it-uses table, a "New (glue only)" row and a Sketch Builderits own worktree, test-first, a kitchen-sink demo box-testwhole suites on float-box, never on float-2 ReviewCodex second opinion, bot reviews, the hydra check Merge--merge, so each session's commits stay in history Deployloki runs ep0ch install --apply, outlines backed up first Validate → donereal-app proof, then Evan's daily use ddaddyclaude.ai · eyes in the sky, writes in gurgle Llokideployer and coordinator for ep0ch kkittyruns the gurgle: watch logs, tidy passes ccowboyrent-due work, across devices bbuildersone ticket or slice each, end to end §11 ::next Up next: search that says how sure it is Ticket What Stage PIE-1187 Placement: an open lands in place, no make-then-fold reflow doing PIE-1194 Contract: the action contract checked in one place queued PIE-1196 A capability that fell back says so in the status bar ("ranking off") queued PIE-1197–1200 Jev search: evals, confidence, structured candidates, deep search queued PIE-1181 A tile something opened into stays lit; door events as rule triggers queued PIE-1201 A hydra lint in CI: does this diff decide what an owner already decides? unprioritized ADR 0007 The glass and the strip, the two surfaces still to build designed Sources git: float-ritual-stack/ep0ch main at 11e6722 (Oct 22, 3:26 AM ET), first-parent history Sep 27 – Oct 22; line counts from tracked .ts/.tsx files. Repo docs: README.md, AGENTS.md, packages/door/docs/UI-GRAMMAR.md (TL;DR, glossary), docs/adr/0005-agents-act-nodes-mail.md, docs/adr/0007-surfaces-about-the-current-thing.md, packages/outline-core/src/protocol.ts, packages/door/src/mcp-gateway.ts. pie (live, float-2): How this workboard works (d5b3e557), Infrastructure hub (50fe932d), Evan's briefing (aca85598), stage counts by outline_query, PIE-1173 to PIE-1201. gurgle (live, float-2): Kitty's watch, Oct 22 (65f6d8de); neat is a probe, not a feature (87a98a6e); ep0ch is a postal system (a896f749); Week check, Oct 15–21 (74598ca4). Made by desktop daddy from the ep0ch MCP and the git log. Counts are as of the time above; the workboard moves