Limits
What version 0.1 does not do, and where its guarantees stop.
Platform
- macOS and Linux. CI runs every test on macOS (arm64), Linux (x86_64, plain checkouts; failures there do not fail the build), and Linux on btrfs and on XFS with copy-on-write required. The code is Unix-only (signals,
libc); there is no Windows support. - Copy-on-write needs a file system that supports it: APFS on macOS; btrfs or XFS with reflink on Linux (
FICLONEreflinks), each tested in CI with copy-on-write required. Other file systems withFICLONE, such as bcachefs, are not tested. On ext4 and others, a workspace is a plain checkout: its files are new copies, and[prepare]installs dependencies again in each one. On a CI runner, ten reflink workspaces of a 30,000-file repository added no measurable disk on btrfs, against 24 MB for worktrees; on ext4 both used 1.27 GB (Benchmarks). - Requires git 2.38 or newer (
merge-tree --write-tree); Zit checks and names the version it needs.
Semantics
- Prose merges like git. Two edits to one Markdown section are accepted when their text merges; Zit does not judge them further. Code is stricter: two edits to one function are refused even when the text merges.
- Adjacent insertions conflict. Two contributors adding different lines at the same place in a list is a text conflict, as in git. In the 50-contributor simulation this was the most common remaining rejection (Lessons).
- Inferred reads match by name. A change that mentions
Configdepends on every symbol calledConfigin any file; a methodType::methodis depended on by code that namesType. Paths are not resolved. Member calls on values (cache.get()) are not references; member calls on imported modules (lib.price(),fmt.Println) are. It cannot see dynamic dispatch, reflection, or names built from strings. - Only an interface change makes a reader stale. An inferred reader goes stale when a symbol’s interface changes (its text without function bodies and comments: signatures, fields, constants), not when only a body changes. A body change that breaks a caller’s behaviour is left to the checks. Declared reads (
zit read) still see any change. The scripted benchmark’s 21–23% false refusals were measured before this rule; not re-measured yet. - Five languages have symbol granularity: Rust, Python, JavaScript, TypeScript/TSX, Go, plus Markdown by heading. Top-level items and methods (
Type::method) are units; nested functions are part of their parent. Every other file (Java, C#, C++, Kotlin, Ruby, PHP, Swift, manifests, lockfiles) is one resource with no inferred reads, so semantic staleness is not detected for it;zit recordsays so for source files it cannot parse. - Imports are their own unit (
path#(imports)): two changes that both add imports compose when their text merges. - Renames are a delete plus an add.
- Check
inputsare trusted, not verified. - Symlinks and submodules are whole-file resources. Git LFS is untested.
Operations
-
Per-operation overhead is higher than raw git because every git operation is a process (ADR 7). Numbers in Benchmarks.
-
zit statuscomputes every speculative change’s status each time; its cost grows with their number. -
The checks of one verification run sequentially. Verification views keep ignored files between checks (ADR 10).
-
Each agent workspace is at a new path, so on a compiled project every agent rebuilds the project once, and a shared build directory accumulates output for paths that no longer exist. Measured: about 1.9 GB after ten agents on a Rust project (Lessons).
-
Claims are voluntary and local. They are not replicated, and an agent that has neither claimed nor started writing is invisible. What open workspaces are writing is reused for up to 2 seconds, so a claim may be decided on a slightly old picture.
-
TMPDIRis private per workspace; ports and other machine-wide state are shared between agents. -
Discarded changes stay in the object database until
git gcremoves them. -
A workspace orphaned by
SIGKILLis listed, not cleaned up automatically. -
Interactive
zit runsignals only the agent. Run headless (no terminal on stdin), the agent leads its own process group, and whatever it started is stopped before its work is recorded. With a terminal, the agent must stay in the terminal’s group to read it; children it leaves running are not stopped. -
zit runpasses stdin through. Some agents (Codex) wait for stdin to close when it is not a terminal; use</dev/nullin scripts. -
A workspace shares the repository’s refs. Branches, stashes or tags an agent creates with git inside a workspace appear in the real repository.
-
The terminal Ctrl-C path of
zit run(delayed forwarding) is implemented but has no automated test; the non-terminalSIGINT/SIGTERMpaths do. -
No free-space check. When the disk fills, git cannot write and agents’ work is not landed (accepted states are not damaged). Seen once, in Lesson 02.
-
[prepare]needs copy-on-write to save space. Without it, the install still runs, once per workspace. -
Sandboxed agents need Zit’s home. Agents that sandbox their commands must be allowed to write to Zit’s home (
~/.zit), and only that: Zit never needs them to write the repository’s git directory, whose hooks and config would let them run code outside the sandbox. Thecodexpreset grants this repository’s directory under it. -
The presets let agents act without asking.
clauderuns with--permission-mode acceptEdits,autohandwith--yes,codexin itsworkspace-writesandbox. They edit only their workspace, but run whatever commands their own settings allow. -
zit cleansees only what Zit can see. It refuses while a workspace has a livezit runor unrecorded edits, or a clone or verification holds its lock; an MCP agent that has not written anything yet is invisible to it. -
Liveness is a pid. A workspace whose
zit rundied may look alive if its pid is reused.
Not built
- No server, accounts or access control: whoever can write the repository’s refs can accept. Agents using MCP cannot:
zit_acceptandzit_discardare offered only byzit mcp --integrator. - No signed evidence. Check results fetched from a remote are not trusted unless you set
zit.trustFetchedEvidence(Another machine); with it set, they are trusted without proof of who produced them. - No batching: changes are verified and land one at a time (Compared).
- No CI integration beyond running
zit acceptin a job yourself (Teams and review). - No replication protocol beyond
git fetch/git pushofrefs/zit/*, and no automatic reconciliation of two machines that both moved current. - No remote, container or VM materialisers.
- No dependency tracking on build artifacts, database schemas or runtime assumptions; resources are files and symbols.
- No automatic tracking of what an agent read. Reads are inferred from written code or declared.
- Cost is what the agent reports. Claude Code reports tokens and dollars, Codex tokens only, Autohand and Pi nothing yet. No way for an agent to set the intent of the change
zit runrecords for it. - “Landed” means it composed and passed the checks, not that it was good. Quality has been scored once, by a blind model judge (Lessons), not by people.
- No shared place for a question about the task that every agent should see answered once.
- The largest run measured is in Benchmarks. Nothing larger is claimed.