The creative process is all about iteration: trying out alternatives, seeing a progression over time, or discussing changes with our collaborators. These days, those collaborators may even include AI tools proposing edits.
The value of software tools for supporting iteration is already understood by many creatives. Developers use Git to work in parallel and record history. Writers “Track Changes” in Word to suggest and review edits. Designers copy-paste artboards in Figma to explore variations.
But existing versioning tools tend to be too complicated for most computer users, or only offer support for basic workflows. And each app has its own versioning system, without a unified way to iterate and collaborate on all your data.
We believe that simple, powerful, universal version control tools could help all kinds of creators produce better work. Perhaps this is even built into the storage layer of your OS! That’s the vision for this Ink & Switch research project, codenamed Patchwork.
Over the coming months we’ll be building a series of prototypes to test this idea. This lab notebook will offer a series of short posts sharing our findings as we go.
Writing is important work: books, blog posts, news articles, science papers, and emails all share the basic need of prose editing. Sometimes creating these documents involves many stakeholders (coauthors, reviewers, editors, clients) and complex workflows.
That’s why we’ve chosen writing prose as our first domain for exploring the Patchwork vision of “version control for everything.”
Some writing tools offer basic version control capabilities: Google Docs' suggestion mode, Word’s track changes, Scrivener’s named snapshots. But these features are limited compared to the powerful capabilities that software engineers have in their version control tools.
Could prose writers make use of branches, richer history and diff visualizations, or reverting and cherry-picking of changes?
We think so, and there’s some evidence in folk practices such as some writers using Git to track their manuscripts.
Our lab’s first take on version control for writers was Upwelling. One of its core ideas was the concept of “drafts” as a form of lightweight branching, granting creative privacy to authors on multi-author documents.
In addition to this kind of explicit branching, on Patchwork we’ll try some less-formal workflows. For example, live editing one shared copy with ability to see and manipulate history. Or perhaps you may start editing and then later realize you want to move your work to a branch.
So, our first prototypes—coming up in the next post—will explore visualizations of history and change that help authors understand what’s happening on a shared doc.
On Patchwork we’re exploring dynamic history: auto-saving every change to a document, and flexibly querying that granular history.
We seek to combine the best aspects of two paradigms:
Mobile and web apps typically autosave every change.
Traditional desktop apps require the user to manually save and name files. Similarly, developer version control tools require explicit commits with a commit message.
Auto-saving requires less effort by users, supports live collaboration, and avoids accidentally losing work. But manual savepoints are useful for indicating milestones, which helps with collaboration and understanding history.
Dynamic history is thus:
Auto-save every character typed into a doc
Offer flexible views of the history depending on the task
Allow users to mark important milestones
In using this first prototype to work on real documents, we’ve found that it’s useful to have multiple ways of querying history. For example, zooming out to see a big batch of edits from many authors over the course of a few days, or zooming in to see very small edits from a single author.
In practice, though, it seems most cases can be supported by a small set of groupings, such as by author and edit time. So we plan to build default user-facing views based on these groupings, while still preserving the ability to query more flexibly in rarer situations.
One more thing: in many tech stacks, supporting dynamic history might take a lot of engineering effort. But we’re building on top of Automerge, which already tracks the full change history. In an upcoming post, we’ll share more about why Automerge gives us a strong foundation for user-facing version control.
Whenever reviewing changes to a document, it’s essential to have a way of seeing what changed: a “diff view.”
Diff views appear in source control tools, such as the red/green line-based view in the diff unix utility. Writers have seen the blue (added) and red+strikethrough (removed) syntax found in word processors.
But two common problems we’ve noticed ourselves and heard from others about existing diff views for prose:
They’re often very noisy, making it hard to review (e.g. suggested edits in Google Docs).
It can be hard to get a high-level glance of what’s changed, in addition to the details.
Here are some small experiments we tried in this area to improve legibility and utility.
First, diff visualization in the full-size document editor:
We also used the right-side gutter, traditionally used for comments, to call out additions and deletions. Most promising here was showing replaced text, which is a common operation in copyediting but can get noisy with strikethrough-based diff views.
There’s another type of diff visualization we need, which is a summary or thumbnail view. Git shows a commit summary in the style of “+added/-removed,” but no such thing exists for prose writing.
Some experiments we tried for a summary diff:
Breaking these down top to bottom:
Stats ala Git/GitHub, with characters added and removed, and comments added. We’ve found that character count isn’t the right metric for prose, but word/sentence counts are better.
Blobs as a visual representation. Several contigous paragraphs added will show as a large central circle, with small edits orbiting it. Red and green differentiate addition and deletion. We don’t love this solution, but we do think the problem of differentiating “one big edit” from “many small edits” is important.
Minibar . The horizontal bar gives a sense for where in the document changes happened, and the section headers diagonally above give further orientation clues. We found this most helpful in longer documents.
Sections stats uses the document section headers to infer the table of contents. Here we have the same +added/-deleted syntax, broken down by section.
Our team’s favorites so far are the hover-to-show-deleted (full document) and the minibar (summary). What directions do you think we should try next?
The latest Patchwork demo, which we call Edit Groups, explores lightweight tools for explaining and reviewing edits.
In our interviews with journalists and other writers, we’ve seen a huge variety of edit and review workflows. Some, like two friends writing a blog post, might be very informal. Others, like editing the front-page article on a monthly magazine, might have a lot of stakeholders and process. Often the workflow can change over the course of a project.
Thus we decided to embrace a design principle of formality on demand: choose the level of structure you want, and avoid needless ceremony.
Many writing tools let writers discuss edits with collaborators, but we think they often make this process too formal. For example, Google Docs suggestion mode requires authors to decide in advance whether or not they are “suggesting” or “editing”, and edits can’t be discussed or turned into suggestions later on. Upwelling, an earlier lab project, was even more formal, requiring authors to create an explicit “draft layer” before making any edits.
What would it look like to support discussion around edits in a very low-formality way, without any need for branching layers or suggestion mode? This prototype was our attempt. The key ideas are:
Contributors just edit directly on the doc. No branches or drafts, no suggested changes.
After an edit session, you can retroactively supply rationale for particular edits, including grouping related edits together.
The primary author of the doc doesn’t need to approve or reject edits. But the rationale and grouping, plus the diff view, makes it easy to see what changed and revert things they don’t agree with.
Although groups are often spatially colocated (for example, a section rewritten) they might also be spread out across the document (for example, a term search-and-replaced, or addition of Oxford commas throughout the doc).
From using this prototype, we’ve found that seeing recent edits and being able to easily revert them feels very useful—it’s a form of undo that’s not limited to the time order that edits happened.
We’re still figuring out what kinds of groups are useful in practice. Because writing edits often consist of many small changes that could be independently merged, it’s possible that grouping edits into atomically revertable units isn’t a common need in this domain.
Branching is a powerful concept from source control systems. The latest Patchwork experiment explores whether writers could benefit from branches:
A “branch” is a variation of a document that can be edited independently. This allows a writer to experiment without worrying about messing up the main version. And it allows multiple writers to try things in parallel without bothering each other. Eventually, any given branch can be merged back to the main doc—or discarded if it turned out to be a direction that didn’t work out.
Our previous Edit Groups prototype explored tools for editing on a single shared version of a document without branching. The simple branches experiment leans entirely in the other direction. We think that “branch” is a great name and a great concept, and if we can provide a simple, comprehensible UI and avoid footguns we belive it’s something writers can learn and benefit from.
A key attribute of this prototype is that it’s fast and low-ceremony to create branches, switch between branches, and merge or delete branches.
Users still edit on main by default, so you can send a doc to someone and they can make changes without understanding branches. You can also create a branch retroactively with your current edit session, including a mouse-over diff that shows what changes will go into the branch (and be removed from main) if you pick this.
To keep things simple:
There’s no branching from branches. You can only create branches from main, and merge back to main. (This seems sufficient for most writing use cases, although we’ve already encountered occasional cases where it’s not enough.)
You don’t need to name branches when you create them. You can rename them or allow AI to name it automatically for you later.
You can see how the branch differs from main with either a diff view or a side-by-side view.
When you merge the branch, it’s deleted. There’s no cleanup step.
We’ve been using simple branches to suggest edits on posts to the lab notebook, including this one. So far, we’re finding the prototype compelling for individual use (e.g. trying experimental directions) and for collaboration (sending a link to the branch, including edits and comments, to a coauthor). One direction we’d like to explore further is using a stronger spatial metaphor to give users a sense of how branches and the main document relate to each other.
Creative work increasingly involves using AI tools. These tools can help us improve our work, but can also give bad suggestions or make mistakes.
We think concepts from version control can help people work productively with AI, as shown in our latest Patchwork demo:
In the demo, an AI bot for a style guide makes changes as another collaborator in the document. It puts changes on a branch, which you can choose to partially or completely merge—just like you would suggestions from a human coauthor.
The changes are highlighted in a diff to help you review. Once you accept edits from a bot, the history timeline also shows which edits came from the bot.
One more thing: since the bots are simply text prompts, you can create your own by adding a bot prompt into your document collection!
Bots can be shared, edited, and versioned just like regular documents—for example, you can view the history of a prompt, or use a branch to try a new variant of a prompt.
So far, we’ve found that bots can be useful for tasks like style guide editing and voice transcript cleanup. We’ve also built variants of this system where the bot leaves comments with edit rationale, and have found that helpful for understanding whether to accept a particular edit.
In the future, we hope to determine out how bots can prove most useful in our daily workflows. We’re also planning to explore how AI tools can extend to editing other kinds of data besides writing, following our vision of universal version control.
Many types of apps—spreadsheets, writing tools, design tools—could benefit from version control features like history, branching, and diffing. But common databases (like PostgreSQL, IndexedDB, or Core Data) offer a model focused only on a current snapshot of the user’s data, with little or no knowlege of history.
On Patchwork, we’ve been able to prototype very rapidly because we’re building on top of Automerge, a JSON data storage and synchronization library developed here at Ink & Switch.
Automerge was designed to support local-first software and uses a CRDT sync algorithm to merge together edits made on different devices, without the need for a central authority server. This internal machinery is also a good fit for version control interfaces:
History: Automerge never deletes anything. It stores every change made to a document with efficient compression. This enables features like dynamic history that rely on a complete log of changes.
Diffs: Automerge can compute an exact difference between two points in history of a document. It doesn’t need to resort to heuristics because the full edit history is tracked. This enables features like diff visualizations. For text in particular, Automerge gives each character has its own ID, so it’s easy to show precisely which characters were deleted or inserted.
Branching and merging: Automerge supports cloning documents and then merging them back together in reasonable ways using the CRDT algorithm, even if there have been concurrent edits on both copies. This is the underlying capability that supports our simple branching.
It isn’t an accident that Automerge is a good fit for this domain: part of the project vision has always been supporting better versioning tools for collaborative work. It’s noteworthy how much alignment there is between the tools needed to support concurrent offline editing and version control tools—both require tracking history and support for concurrent editing.
In addition to using Automerge’s capabilities for rapid prototyping, part of the goal of Patchwork is to motivate future improvements to Automerge. We’ve tried improvements like attributing changes to authors in diffs, which was instrumental to our Edit Groups prototype. Then we’re working with the Automerge team on upstream changes to more deeply support user-facing version control features.
When collaborating on a document, the authors want a sense of what’s been changing—as we explored in dynamic history. A related need is having discussions about the editing process. This might include explaining the reasoning behind an edit, asking for feedback from others, or even just expressing appreciation for some changes by someone else on the team.
This next experiment tries to unify these by mixing a history timeline with a chat-like interface:
The timeline view tries to give structure and legibility to the document history. All edits get an AI-generated summary of the changes, and users can leave notes annotating the history in an informal way.
There are markers for significant moments: merged branches appear prominently, and users can mark significant milestones.
The chat box also features slash commands, for a command-line interface to your document. It’s possible to create and merge branches or mark milestones right from the chat box, without needing to find a button. (We also envision using this to mention collaborators or summoning AI bots to perform edits, although we haven’t tried that yet.)
We’ve been using this timeline view for several weeks to edit various
documents, including this very post.
In our use so far:
We’ve found that the brief AI summaries are a remarkably useful way to understand writing edits at a high level—more successful than any of our other diff visualizations so far.
We’ve also enjoyed using the chat metaphor for lightweight annotations—like a Git commit message but with less ceremony. But we need to do more work to figure out the relationship between comments on the history and comments in the document itself.
Branch merges shown a single item in the history encourages us to use branches as a unit to encapsulate work. We’ve enjoyed how this makes a batch of changes feel more satisfying to finish and merge.
One thing we’d like to improve in the future is evoking an intuitive sense of the branching structure of the document within the timeline view. Currently when you switch to a branch you get an entirely different timeline. We suspect there may be a way to show the relationship between branches, without resorting to a complex railroad diagram.
So far on the Patchwork project, we’ve created a prototype of version control for writers. Key features are lightweight branches, diff visualization, and a chat-like interface to document history. We’ve used this prototype for our own writing (including the posts in this lab notebook) and found it useful for coauthoring and creative iteration.
But our end goal isn’t just versioned writing! We’re pursuing the vision of universal version control: flexible versioning and collaboration tools that can work with any kind of data in your computer. As we wrap the first phase of our project, we wanted to find out: how well do these concepts generalize to other domains besides writing?
To start exploring this question, we prototyped a version-controlled diagram editor based on tldraw. This demo shows collaborative floorplan editing with branching, timeline, and visual diffs:
Overall, we found that it took minimal effort to port our existing version control prototype to support a more visual tool.
Branches apply to drawing just as in writing: they are useful for creative explorations, and for grouping units of work to share. The document timeline is mostly the same as its prose equivalent, although the grouping and description of changes needed some domain-specific logic.
Diff visualization varies a lot more by document type. Since this was a brief spike, we used the simplest thing we could think of: a green glow for added shapes, and a translucent/ghost effect for deleted shapes. Even this simple approach worked well for an at-a-glance look at where changes have happened in a document, especially when paired with side-by-side comparison views.
Comments also require deeper integration to the app. Here we needed to hook into tldraw’s selection and rendering logic in order to connect the comments to the object via a curved line. We’re enthusiastic about the idea of sharing a comments layer across all kinds of data, but we think more UI work is needed to make the experience feel natural in all contexts.
What did we learn from this attempt at generalization?
Diff view and comments are more domain specific and require more work on the part of the app developer.
Auto-generated LLM summaries work ok for visual edits, but are less obviously good than text summaries.
To push this idea even further, we tried a quick integration with a spreadsheet, made with Handsontable.
Results for porting Patchwork to a spreadsheet were similar to the diagram case:
Branching and history timeline required minimal integration effort.
We saw the value in using branches as a way to try out alternate what-if scenarios, a common scenario in spreadsheets and financial modeling.
Similar to the diagramming prototype, diff and comment views in spreadsheets are more work to get right. One challenge we encountered was diff that distinguish manually-edited cells versus recalculated formula result cells.
For each case where we’ve applied branching to a new domain (writing, diagrams, and spreadsheets), we’ve quickly found useful ideas for applying them. This suggests branching is a powerful general primitive for all kinds of creative work.
Going forward, we’re planning to refine the APIs used to integrate an application with the Patchwork infrastructure. And we’ll keep using these versioning tools in our own work to uncover which pieces are most useful in practice.
When we started on this journey, our vision was universal vision control, perhaps even built into the OS. These small experiments give us some confidence we’re on a good path towards that goal.
In our explorations of universal version control, we’ve found that it’s crucial to have good tools for explaining edits and discussing changes. One key feature for enabling these discussions is inline comments that point to a specific part of a document. Inline comments are so valuable for collaboration that every modern app has them.
Currently, dev teams need to spend time implementing inline comments specifically for their app, even though it’s not a unique differentiator. What if instead there was a universal comments layer across all apps, to save developers work and give users a more uniform experience?
We tried prototyping a universal comments system in Patchwork. It works with the Markdown writing tool we’ve shown throughout the lab notebook, as well as the drawing and spreadsheet tools we showed in our previous post.
When building this system, we aimed to find a minimal API that expresses only the app-specific parts of commenting. We realized that the basic interactions of commenting—typing a message, replying to threads, etc.—are the same for any app, so they should be handled by the Patchwork environment.
What’s unique to each app is the things you can comment on: a range of cells in a spreadsheet, a span of text in a Markdown doc, a set of shapes in a drawing. In our system, we allow developers to describe the things that can be commented on in their specific app using the concept of pointers.
Once the developer has specified a pointer type for a given type of data, all that’s left is to implement a few simple UI affordances to integrate with the Patchwork commenting UI: highlighting the pointers in their app that have comments, as well as reporting out the current user selection to support adding new comments on that selection. The generic Patchwork UI takes care of the rest: letting users enter new comments, showing the list, handling replies, storing the data, and so on. The result is a basic commenting experience with very little work from the developer.
Beyond that, developers can implement optional UI features which further improve the user experience. For example, when a user selects a comment in the sidebar, the app UI should ideally focus the area of the document pointed to by that comment. Patchwork enables this by passing the currently focused pointer to the app UI, so that it can scroll the focused pointer into view. Even implementing these optional APIs is still less work than building a whole comment system from scratch.
We’ve found that a universal commenting system provides a uniform user experience. For example, we don’t need to learn new conventions for each app; we can press “cmd + shift + m” in any document to leave a comment. In the future, we plan to try building other interfaces on top of the shared commenting layer, like a single inbox for all comments across various tools.
Beyond their usefulness for comments, we’ve found that pointers are a useful primitive in other contexts. For example, we now use the pointers API to power our diff views for version control: when a document is shown compared to a previous version, the app UI gets passed a list of pointers to sections that have changed, so it can highlight additions and deletions. We can also imagine other use cases for them, like highlighting search results across different kinds of documents, or pointing to parts of a document to prompt AI edits.
The Ink & Switch Dispatch
Keep up-to-date with the lab's latest findings, appearances, and happenings by subscribing to our newsletter. For a sneak peek, browse the archive.