zit is Fossil's formats and sync protocol reimplemented in Zig from four
companion Internet-Drafts (frozen in docs/rfcs/). It is a library
first — the delta codec, the artifact formats, the derived repository state,
and the HTTP sync protocol as an embeddable API — with a thin CLI over the top.
This first tagged release is a working version-control substrate. It is honest
about what it does not yet do; the limitations below are deliberate, not bugs.
What's implemented
- Delta codec — the byte-level delta encode/decode of
draft-fossil-delta-format-00. - Artifact formats — the manifest / control-artifact card grammar of
draft-fossil-artifact-format-00: every card letter parsed, the §4.4/§4.5 ordering and occurrence rules enforced, and the Z and R checksums modelled. The check-in (manifest), cluster, and tag/control types are interpreted; the collaboration types (wiki, ticket, forum, attachment, technote) are carried opaquely — stored and transported by hash, not read. - Derived repository state — branch, tag, leaf, and current-trunk views of
draft-fossil-repo-state-00, with tag propagation along the check-in DAG. - HTTP sync — clone, pull, push, and bidirectional sync of
draft-fossil-sync-protocol-00, driven by a pure client state machine (bytes in, bytes out) with transport supplied by the caller; plus aserveside that answers the framed protocol. - CLI — the working-copy and history verbs (
init,add,rm,mv,status,stat,diff,extras,clean,addremove,commit,log,open,update,merge,revert,undo,redo,leaves,timeline,branch,tag,amend,info,ls,cat,artifact,annotate,bisect), the sync verbs (serve,clone,pull,push,sync,remote), and store maintenance (pack).openhonours--manifest[=r,u,t];-Rselects a repository and-npreviews the destructive verbs.
No module touches ambient time, randomness, filesystem, or network directly; effects arrive through injected interfaces, so the whole stack replays exactly under seeded deterministic simulation.
What the conformance claim rests on
The drafts are the authority, not Fossil's source: test expectations come from the spec text and its worked examples, and every normative clause a module implements gets a test citing its section. That keeps the claim honest against the spec — but a spec can be misread, so one step checks against the reference implementation.
That step is zig build smoke. It drives the real fossil binary, and CI
runs it on every push; it is the only step that proves conformance against
Fossil itself rather than against our own reading of the RFCs. A disagreement
there means either zit misread the spec or the spec is wrong — the spec gets an
erratum, never the code a workaround.
The exact fossil that smoke passed against matters, so name it. Locally that is:
fossil 2.28 [52445a27f1] (2026-03-11)
The CI runner installs whatever its package source ships, which lags the local
2.28. The workflow prints fossil version for that reason (readiness item S7).
The runner's version at the tagged commit must be read from that CI log and
recorded here before shipping — do not assume it equals 2.28.
What's deliberately deferred, and where it's documented
diffis working-tree-versus-current-check-in only, and name-status only. It emitsA/M/Dper path, no textual hunks, and there is no revision-to-revision diff. Documented inzit diff --help.- The sync server code is a fixed informational placeholder
(
0000000000000000, sync §9.1) on both client and server. This is not a per-server identity. The per-repository project code, by contrast, is real: derived oninit, persisted, emitted byserve, and adopted onclone. Documented at theserver_servercode/server_projectcodedefinitions insrc/serve.zig. - The
RandWcards are parsed but not interpreted. TheRaggregate content checksum is retained and re-emitted verbatim when present, but is never generated on commit nor verified against content. TheWwiki-text card belongs to wiki artifacts, a collaboration type carried opaquely. The opaque-carry boundary is documented in the README Scope section; the card grammar and per-type card masks live insrc/artifact.zig. - Verbs absent versus Fossil: no
stash,grep,ui, orsettings, and no revision-to-revisiondiff. The command set is documented inzit help.
Storage
zit pack performs an at-rest re-deltification pass — fossil-style best-of-N
delta-base selection plus a monotonic-shrink guard that keeps the smaller of an
existing frame and its re-encoding, so repacking a clone of fossil-quality wire
deltas is a net win rather than a regression. It is at-rest only: all four RFCs
stay conformant and wire interop is preserved, and every repacked frame is
hash-verified against the log.
Measured whole-file, index-inclusive, in commit bab9303056:
| Repository | Before pack | After pack | Versus fossil |
|---|---|---|---|
| sqlite | 207.3 MB (1.40x) | 174.4 MB (1.18x) | fossil 147.7 MB |
| fossil-scm | 117.5 MB (1.63x) | 108.1 MB (1.50x) | fossil 72.2 MB |
Build
Requires Zig 0.16+.
zig build # build the zit binary into zig-out/bin/
zig build test # unit tests
zig build smoke # interop check against a fossil binary on PATH