Data format

zz keeps data in five places:

Where What Travels with git clone?
The repo's default branch Code and its history Yes
Git notes in the repo The Ladder With git clone --mirror, or by fetching refs/notes/*
The repo's zz-meta branch Description, Policy, owner, Role grants Yes
A Durable Object per repo Lane, Ask, and Answer state No
Cloudflare D1 Accounts, tokens, the repo index, the search index No

The design goal is that the repo carries everything that matters, so a repo can leave the platform with its history, knowledge, and settings intact. Code, the Ladder, and repo settings meet that goal today. Lane history does not yet. See Architecture.

Ladder

The Ladder is stored as git notes under refs/notes/zz/ladder/:

Ref Attached to Holds
refs/notes/zz/ladder/code The blob, tree, or root tree a rung describes repo, directory, file rungs and everything nested under them
refs/notes/zz/ladder/changeset The commit a rung describes changeset rungs with their filechange and linechange children

Each note is JSON holding one rung and its embedded children:

1{
2  "path": "hello.js",
3  "kind": "file",
4  "summary": "Exports greet(name), which returns a greeting string for the given name.",
5  "sources": [
6    { "kind": "commit", "ref": "3f9a2c1e...", "title": "Add greet()", "author": "you@example.com[claude]", "at": "2026-10-13T18:22:04Z" }
7  ],
8  "children": []
9}

A child can also be a reference to another note, {"ref": "..."}, instead of an embedded rung. Ladders built locally with zz ladder build add more refs for releases, discussion threads, contributors, and dependencies, which hang off the repo's root commit.

Standard git tools can read the Ladder:

git fetch origin 'refs/notes/*:refs/notes/*'
git notes --ref=zz/ladder/changeset show <commit>

zz-meta branch

Repo settings live on an orphan branch named zz-meta, separate from the code's history so that settings changes don't add commits to it. Clone it with git clone -b zz-meta <url>. It holds two files.

meta.json

1{
2  "description": "A place to try zz",
3  "policy": { "require_changeset_review": true, "visibility": "public" },
4  "owner": "you@example.com",
5  "shard_of": "you@example.com/hello",
6  "created_at": "2026-10-13T18:00:00Z"
7}

shard_of appears only on a shard and names its immediate parent. visibility is public or private. A public repo can be read by anyone and written only by Maintainers and above.

roles.json

1{
2  "grants": [
3    { "principal": "you@example.com", "role": "owner", "granted_by": "system", "at": "2026-10-13T18:00:00Z" },
4    { "principal": "you@example.com[claude]", "role": "contributor", "granted_by": "you@example.com", "at": "2026-10-13T18:05:00Z" }
5  ]
6}

A principal is an Agent's username. Roles are owner, maintainer, contributor, and viewer. An Agent with no grant on a public repo is treated as a viewer. See Governance.

Lanes

Each repo has one Durable Object holding its Lanes in SQLite, one row per Lane with the Lane stored as JSON:

 1{
 2  "id": "_repo",
 3  "repo": "repo-3c9e1a7b",
 4  "origin": null,
 5  "name": "you@example.com/hello",
 6  "objective": "the you@example.com/hello repository",
 7  "status": "active",
 8  "scope": ["**"],
 9  "trigger": { "kind": "manual", "proposed_by": "you@example.com" },
10  "coordinators": ["you@example.com"],
11  "maintainers": ["you@example.com"],
12  "history": [
13    { "id": "ask-1a2b3c4d5e", "type": "ASK", "kind": "work", "from": "you@example.com",
14      "payload": { "description": "Add hello.js exporting a greet(name) function" }, "at": "2026-10-13T18:10:00Z" },
15    { "id": "ask-5e6f7a8b9c", "type": "ASK", "kind": "claim_request", "from": "you@example.com[claude]",
16      "payload": { "target": "ask-1a2b3c4d5e" }, "at": "2026-10-13T18:11:00Z" },
17    { "id": "answer-0d1e2f3a4b", "type": "ANSWER", "ask": "ask-5e6f7a8b9c", "from": "you@example.com",
18      "action": "grant", "payload": { "grant": "grant-ask-5e6f7a8b9c" }, "at": "2026-10-13T18:11:00Z" }
19  ],
20  "related_lanes": []
21}

History entries are one of:

type Fields
ASK id, kind, from, payload, depends_on, priority, at
ANSWER id, ask (the Ask's id), from, action (grant, deny, complete), payload, at
INSIGHT kind (norm or trap), text, from, at

repo holds the server's internal storage name for the repo. A related_lanes entry is {repo, lane, origin, status}, where origin is {repo, lane}.

Planned. Exporting Lane state into the repo, likely onto the zz-meta branch, so a clone carries its coordination history too.

Accounts and the index

D1 holds what belongs to no single repo:

  • Agents and identities. One row per Agent, human or managed, keyed by username, plus which login provider (Cloudflare or Google) each human signed in with.
  • Tokens and sessions. Hashed bearer tokens, web sessions, and pending zz login handshakes.
  • The repo index. Every repo's slug, owner, description, visibility, shard parent, and a cache of its Role grants, for search and listing. The zz-meta branch is the source of truth for anything cached here.
  • Tracking. The repos each Agent has chosen to watch.
  • The Ladder search index. A full-text index of rung summaries across all repos, which ladder_search and the explore page query. It can be rebuilt from the Ladders with ladder_reindex.

Local mode

With --local, zz keeps everything on your machine:

Path Contents
~/.zz/repos/<owner>/<repo>/ A git clone. Its Ladder lives in the clone's git notes.
~/.zz/state/<owner>/<repo>/.zz/zz.db Lane state in SQLite, in the format shown above.

Shard names keep their brackets everywhere except on disk, where repo[task] becomes repo__task.

The original design for a committed .zz/ directory with decision records, votes, trust scores, and a fuller policy.yaml is in the Archive.