Skip to content

What happens when you and your AI agent edit the same note

An agent's write merges into a static.md note like a second person typing. Here's the one case that lost text, how I fixed it, and a test with 500 editors.

On launch day someone on Reddit asked the question I’d been half-avoiding: “If I’m typing in a note on my phone while Claude writes to it over MCP, does its write merge in like a second person typing, or does it replace the note?”

The short answer was “it merges”. The honest answer had one exception. This post is about that exception, how I closed it, and the test I ran to check that nothing gets lost when people and agents write into one note at the same time.

How a note merges

Every static.md note is a Yjs document, a CRDT. Each character you type has its own identity: who typed it, and which character it was typed after. Your keystrokes travel as small updates, and so do an agent’s. Updates can arrive in any order, from any number of people, and every copy of the note still ends up the same.

So when Claude appends a line while you’re typing in the middle of the note, nothing clashes. Its text lands at the end, yours stays where you put it.

The one way an agent could lose your text

Agents edit notes with one tool, update_note, in two modes. “Append” adds text at the end. “Replace” sends the whole note as the agent wants it to be, and the server turns that into the smallest set of changes.

Replace is where it went wrong. Picture this:

  1. 10:00, Claude reads your plan.
  2. 10:01, you add a line on your phone: “Call the bank first.”
  3. 10:02, Claude sends back the whole plan with one step reworded.

The server compared Claude’s text with the note as it was at 10:02. Your new line wasn’t in Claude’s text, because Claude never saw it, so the server took it as something Claude wanted gone. Your line was deleted.

Nothing else could do this. Appends, edits in the browser and edits from the encrypted-notes bridge all merge. But “rewrite the whole note” is exactly what an agent does when you ask it to tidy up a plan, so it mattered.

The fix: merge against what the agent read

A commenter in the same thread suggested the fix: do what git does in a three-way merge. Compare the agent’s text with the version it read, not the version that exists now.

That’s what static.md does now:

  • When an agent reads a note, it gets a short version code, and static.md keeps the exact Yjs state of that version for a week.
  • When the agent replaces the note, it sends that version code back. static.md rebuilds the note as the agent saw it and makes the agent’s change on that copy. Its edits are then anchored to the characters it actually saw, and merge into the live note like an edit made offline. Your 10:01 line is untouched, because the agent’s change never mentioned it.
  • If you and the agent changed the same lines, there’s no safe guess. The write is refused, nothing changes, and the agent is told to read the note again and redo its edit on the new text.
  • Some agents don’t send the version code, for example apps whose tool list is fixed for a while. For them static.md remembers the version that connection last read, so they get the same protection.

Before writing a merge, the server checks that it matches the plain-text three-way merge of the same three versions. If they ever disagree, it refuses rather than writes.

A smaller bug the test found

The big test turned up something subtler. The server’s diff worked character by character. To change f38e into f38 with a space before it, it could delete the characters e f38 instead of f38e. The text comes out the same. But if someone was typing right next to that word at that moment, their letters could end up inside the neighbouring word.

Server-side diffs now work on whole words, so an agent’s edit only touches the words it actually changed.

The test

I wanted to answer the Reddit question with numbers. The test simulates people as Yjs editors that save their changes exactly the way the static.md editor does. Many of them type on slightly stale copies, so their edits really are concurrent with the agents. The agents are real MCP clients talking to the server over HTTP, ChatGPT among them. At the end, every word anyone wrote has to be in the note exactly once, every word anyone deleted has to stay deleted, and every copy has to match.

Run Edits Lost
20 rounds, old replace 67 by people, 20 by agents 20 of 60
20 rounds, now 67 by people, 20 by agents 0
100 people 330 by people, 120 by agents 0 of 450
500 people 1,650 by people, 600 by agents 0 of 2,250

Each run includes agents rewriting the note from old copies: 10 in the 20-round runs, 20 with 100 people and 100 with 500. Now most of those rewrites merge, and the rest are refused because they clashed with a person’s edit, then redone on the new text.

In every run, all copies of the note ended up identical. The 100-person run takes about a second and runs with the rest of static.md’s tests before every release. The 500-person run takes about 20 seconds.

What this means when you use it

  • Let your agent write while you edit. Its appends and edits merge like a colleague’s.
  • If you both rewrite the same paragraph at once, the agent is stopped, not you. It re-reads the note and tries again on your version.
  • Every change an agent makes is kept for 30 days, with a before-and-after view and a one-click restore, if you still want to undo something.

You can connect Claude, ChatGPT, Cursor or VS Code in a minute on the agents page. If you find a way to lose text, tell me at salut@static.md. I’d rather hear it than have someone discover it.