Concepts
kutl is a sync protocol for teams of humans and agents, written in Rust. It syncs three things through one protocol: spaces (structure), documents (knowledge), and signals (coordination). The system consists of a daemon that each participant runs locally, a shared relay that coordinates sync, and a CRDT engine that makes merging deterministic.
Every participant has a copy
In kutl, every participant carries a full copy of every document in their space. There is no single server that holds your data hostage. The relay coordinates, but shutting it down doesn't lose anything. Every copy is complete and independent.
This design has practical consequences:
- No vendor lock-in. Your documents live on your filesystem. You can read them, back them up, or stop using kutl at any time without an export step.
- Tool freedom. Any program that reads and writes files (your editor, a script, an AI agent) becomes a sync participant automatically. No plugins, no integrations, no APIs to learn.
- Mixed environments. One team member uses Vim, another uses VS Code, a third uses a browser. An AI agent works in its own runtime. Everyone edits the same documents simultaneously, in their own preferred environment.
- Offline by default. Edits happen locally and sync when a connection is available. There is no "you must be online to edit" requirement.
Spaces
A space is a named sync context. On disk, it's a directory containing a .kutlspace config file and a .kutl/ directory for local state. Every participant who joins the same space sees the same set of documents. Spaces are identified by a UUID internally, but you refer to them by a human-readable name when joining.
The daemon
Every participant runs a daemon on their own machine. It is a background process that watches all of your registered spaces. When a file changes, the daemon translates the edit into CRDT operations and sends them to the relay. When the relay sends operations from other participants, the daemon applies them to local files. Any tool that reads and writes files (your editor, an AI agent, a script) becomes a sync participant automatically, with no plugins or integrations required.
The relay
The relay is the one shared piece of infrastructure. It is a WebSocket server that receives CRDT operations from each participant's daemon, reconciles them, and sends the merged result back. Only one person on your team needs to set it up, typically whoever is comfortable running a server process. Everyone else just points their daemon at it.
The relay is not a passive message broker. It understands the CRDT protocol and handles catch-up for clients that reconnect after being offline, eviction of unresponsive clients, and document lifecycle tracking.
Using a relay rather than peer-to-peer connections is a deliberate choice. Peer-to-peer sync requires participants to discover and connect to each other directly, which means dealing with NAT traversal, firewall rules, and hole-punching. In practice, most teams work across networks where direct connections between machines are not possible or not desirable. The relay is an ordinary web server that listens on a single port. Participants connect outbound to it over standard WebSocket, which works through firewalls, proxies, and corporate networks without special configuration.
You can self-host a relay on your own infrastructure. By default, the OSS relay uses SQLite to persist space registrations and document state when KUTL_RELAY_DATA_DIR is set. Without it, all state is ephemeral. See Self-Hosting a Relay for deployment options.
Documents and binary files
Text files inside a space are stored as .dt documents (diamond-types format). Each document carries its full edit history as a compact log of CRDT operations. Concurrent edits to the same document merge automatically, character by character, in real time.
Binary files (images, PDFs, and other non-text content) also sync through kutl, but use a different strategy. Binaries are synced whole-file with last-write-wins semantics based on timestamp. The daemon tracks content hashes to avoid re-sending unchanged files.
All files, text and binary, are identified by UUID. Renaming or moving a file across machines doesn't create duplicates. The identity follows the content, not the path.
CRDTs
CRDT stands for Conflict-free Replicated Data Type. It is a data structure where any two copies can be merged deterministically without coordination. Given the same set of operations in any order, every participant arrives at the same result. There are no merge conflicts, no manual resolution steps, and no data loss.
kutl uses CRDTs not just for document content, but for the entire space: subscriptions, document lifecycle (creation, renames, deletes), and coordination state are all modeled as convergent structures. This means file renames and deletes converge deterministically across participants, the same way text edits do. The result is predictable behavior for the full set of operations a team performs, not just typing.
The text CRDT engine is diamond-types, which implements the Eg-walker algorithm. It is the fastest text CRDT available by a wide margin, operating on character-by-character edits so that sync happens in real time as you type, not when you save.
DIDs (Decentralized Identifiers)
Your identity in kutl is a DID, specifically a did:key derived from an ed25519 keypair generated locally and stored in ~/.kutl/identity. No account server, no sign-up form, no email required. Your DID is created automatically the first time you run kutl init or kutl join. For OSS use, DIDs are sufficient for identity. Managed relays like kutlhub layer OAuth and accounts on top.
Signals
kutl signals are the protocol-level primitive for coordination. Where documents capture knowledge, signals capture the interactions around it: questions, reviews, decisions, and threaded conversations. Signals travel through the same relay as document edits, use the same identity model (DIDs), and participate in the same spaces.
Signal types:
- Flags — structured messages with a kind (info, question, review requested, blocked, completed) and an audience. Flags are how participants get each other's attention.
- Decisions — automatically extracted from heading-annotated markers in documents (
## ?for open,## =for resolved). - Replies — threaded responses on any signal.
In the OSS relay, agents exchange flags and replies via MCP tools. Humans participate by working in documents and using the CLI. Managed relays like kutlhub add a web interface with tasks, feeds, chat, and emoji reactions on top of the same signal protocol.
Working with agents
kutl is designed for mixed teams of humans and AI agents. There are two ways an agent can participate in a space:
- File-based. The simplest path. Point the agent at a directory inside a kutl space. The daemon handles sync, and the agent reads and writes files like any other tool. No kutl-specific code required.
- MCP (Model Context Protocol). For richer integration,
kutl watchruns as an MCP server over stdio. It exposes tools for reading and editing documents, listing participants, sending and responding to flags, and polling for changes. The agent receives real-time notifications when someone flags it.
The MCP interface provides get_changes for checkpoint-based polling, edit_document for content updates (the relay computes minimal CRDT operations), and signal tools: create_flag, create_reply, close_flag, and get_signal_detail.
How they fit together
kutl syncs three things as one protocol. Spaces hold the structure: which documents exist, how they're organized, who participates. Documents hold the knowledge: CRDT-synced content that merges deterministically. Signals hold the coordination: flags, replies, and decisions that capture the interactions around the knowledge.
All three flow through the same relay, use the same identity model (DIDs), and work the same way for humans and agents. One person sets up a relay. Everyone else points their daemon at it. Edits, structure changes, and signals all sync through the same connection.