Skip to main content

Ready to get started?

Book a call

PJ

Manuscript

  • Jan – Nov 2026
  • Product Therapy
  • Proof of Concept
  • Build
The Manuscript app on macOS: a short draft with alternative phrasings shown in purple, above a history map of checkpoints.
The native app, September 2026. Purple text marks a line that holds more than one take; the map below keeps every checkpoint.

Overview

Manuscript is a prose editor where any word, sentence or paragraph can hold more than one version. We call them takes. One take shows at a time, so the draft always reads as a single text, and the alternatives live in the file instead of a folder of copies.

It is part of Workroom, our suite of tools, and stands on its own as a desktop app.

Timeline
January – November 2026
Platforms
macOS, Linux and Windows
Stack
Rust, GPUI, Loro

The problem

Writing is rewriting. A UX writer weighs “declined” against “refused”. A novelist tries a chapter’s opening three ways. A speechwriter needs the long version and the short one.

Every editor keeps exactly one text, so the alternatives go somewhere awkward: ALT 2 and ALT 3 pasted under the line, strikethroughs, comments, or a folder of files ending in -v2-FINAL. The comparison that matters, reading the whole piece one way and then the other, is the one those workarounds make hardest.

The data structure

In January, after studying how Lexical, ProseMirror, Zed and Apple’s text system represent text, we designed the document before any interface. A manuscript is a tree of four node types: text, markers for paragraph and section breaks, sequences that run their children in order, and alternatives that hold several versions of the same span. Both containers nest without limit, so a take can sit inside a take, at the level of a word, a sentence or a whole section.

Which alternative is showing is not stored in the tree. A separate configuration maps each alternative to its chosen child by ULID, and rendering walks the tree consulting it. Choosing a take never edits the text. Every node keeps a stable ID through every operation, and the same tree can render any of its versions on demand.

The spec defines every operation (fork, collapse, select, insert, delete, split, join, wrap, move and copy) with its preconditions and invariants: IDs are unique and stable, and an alternative is never empty. History is a tree of checkpoints rather than a line, so going back and writing on starts a branch instead of erasing what came after. A Rust core and command-line tool implemented the spec in three days, with property tests holding the invariants.

Diagram: a sequence holding text and two alternatives, a separate configuration choosing one child of each, and the rendered sentence “The young man walked home.”
The January model. Structure and choice are kept apart: every combination of takes is a manuscript, and the configuration picks which one renders.

Finding the feel

A model on paper does not say how working with takes should feel. In July a web prototype, built in two days on React and Lexical, worked that out: select a phrase, draft an alternative, cycle through takes in place, nest one inside another, and settle back to a single line.

Its versions view made the data structure tangible. One short paragraph with a handful of takes already holds more manuscripts than anyone would keep as files, each one a different configuration of the same tree.

Going native

The prototype proved the interaction. The product had to be fast on long drafts and work offline, so in September we moved Manuscript to Rust and GPUI, the UI framework behind the Zed editor. Lexical had been the prototype’s editor, so the editing surface became a custom GPUI element written from scratch.

The January tree moved onto Loro, a CRDT with a movable tree, branching history and per-peer undo; Automerge and Yjs each lacked at least one of the three. The mapping is one Loro node per manuscript node, with the ULID in the node’s data. The configuration map moved onto the alternatives themselves, so two people choosing different takes converge on each alternative separately. A spike confirmed that every ID survives fork, select and collapse, and that a fork made while someone else types in the same text loses no characters.

History is recorded as steps, checkpoints and paths. Continuing from an old checkpoint starts a path instead of throwing work away, and a layout rule decides which line is the trunk of the map.

The port was feature-complete in ten days. Version 0.1 launched on October 2 for macOS and Linux, and Windows followed with 0.3. Takes, side-by-side compare, a branching history map, find, spelling, comments, autosave, and import from Word, RTF, Markdown and plain text all shipped.

Built for the desktop

The canvas draws every paragraph itself from GPUI’s text primitives, because a take needs hit regions a platform text field cannot give it. That choice had costs we decided one at a time and wrote up as decision records. Spelling comes free with a text field, so the canvas defines the question and each operating system’s own checker answers it; the canvas crate builds and tests on Linux without a window.

Save makes a checkpoint before it writes, and autosave keeps the file current. A crash or a dead battery cannot take an hour of work, and closing a window never asks whether to save, because the software can answer that itself. The take commands live in a context bar that floats over the page only when the caret is somewhere they apply. Calls into macOS, Linux and Windows sit in one module, so a new platform shows what it owes in one place, and the app updates itself by replacing whatever the platform’s own installer put down.

The file format

The first file format was a zip bundle, and it stored the text three times, so opening a long draft spent most of its time parsing JSON. Version 0.2 replaced it with a purpose-built .manuscript format: a header and typed chunks, compressed with zstd, with the history stored as columns.

Export follows the same idea of keeping every version. Export All writes one file for each combination of takes, and each file carries a code, so when an editor sends one back with “this one”, the manuscript can show exactly the takes it was made from. The same Rust core also compiles to WebAssembly for the editor inside Workroom.

Outcomes

A document model for alternatives, specified, built and property-tested in three days

Ten days from the first native commit to a complete port of the prototype

Shipped as a native app on macOS, Linux and Windows

A custom GPUI editing surface with takes, compare and a branching history

Autosave with checkpoints, so closing a window never asks to save

Project artifacts

Manuscript product page

Web wkrm.ai Visit

Manuscript documentation

Web wkrm.ai Read the docs

Get started today.

Book a call