Skip to main content
This page is for users who want to understand what DocWriter is doing under the hood. You do not need any of this to use DocWriter.

The data model

The editor state for every open tab is a Yjs CRDT. The authoritative copy lives on the DocWriter server; the browser is a synced client connected over WebSocket via Hocuspocus. When you type, your keystroke is a local CRDT operation that streams to the server and back to every other connected client (typically just you, in another browser tab). When the agent edits, it does the same thing: its tools open a direct connection to the live document and apply CRDT operations tagged with an agent origin. The browser receives those operations the same way it receives any other remote update. This is what makes the agent feel like a concurrent editor instead of a chat that operates on the document externally.

Persistence

DocWriter stores work in two places in your workspace:
  • Your tab files. Whatever files you open (essay.md, chapter-1.tex, notes/todo.txt) are the durable record of your writing. DocWriter flushes the live CRDT for each tab back to its source file about one second after the last edit, so the file on disk is always a current copy you can open in any other editor or commit to git.
  • .docwriter/. DocWriter’s own state, kept in your workspace:
    • .docwriter/docwriter.db. SQLite. Holds the full Yjs CRDT update log for every tab (so undo, comment threads, and pending agent reviews survive restarts), plus tables for rules, hooks, comment threads, recent actions, and session key-value state.
    • .docwriter/state.json. A human-readable copy of rules, hooks, and agent settings. Updated alongside the database so you can read or edit it in any text editor and so it diffs cleanly under git.
The SQLite database is the source of truth for everything DocWriter itself needs to reload (CRDT history, pending reviews, comments). Your tab files are the source of truth for the writing.

The agent loop

DocWriter is built directly on the Claude Agent SDK — the same runtime that powers Claude Code. The agent therefore has the same built-in tool set Claude Code has: On top of those, DocWriter mounts two MCP servers with writing-specific tools:
  • docwriterpropose_rule, propose_hook (surface review cards in the UI before committing anything).
  • docwriter-docedit_doc, read_doc, write_doc, post_comment, list_threads (operate on the live CRDT documents rather than raw files, so edits appear as reviewable rounds).
When you send a prompt, /api/render streams a single query() call over SSE. (For how the SDK’s agent loop works in general, see How the agent loop works.) Each tool call is logged to the history pane as it happens.

Further reading

For contributors and integrators: