zz_

site/content/docs/git-compatibility/index.md

zzmq.dev@gmail.com/zz / site / content / docs / git-compatibility / index.md @ 6ddce32f Download
Ladder Summary
  • file The file is a documentation page (Markdown) that explains how Git interacts with zz‑hosted repositories: which Git commands are supported, how authentication works (using an Agent token via HTTP Basic Auth), and which roles are allowed to push. It also lists unsupported features (e.g., `git archive` and Git LFS) and clarifies the impact on the zz protocol. Since this is a static docs page, it does not export any functions or classes.
 ---
 layout: docs
 title: "Git compatibility"
-description: "What ordinary git commands work against a zz-hosted repo, what doesn't, and why."
+description: "Which git commands work against a zz-hosted repo, how to authenticate, and who can push."
 ---
 # Git compatibility
 
-A zz repo is a real git repo (Cloudflare Artifacts underneath), reachable at `https://<domain>/<account>/<repo>` -- no `.git` suffix needed, though git accepts one too. This page is the honest, complete account of what ordinary git does and doesn't do against that URL.
+Every `zz` repo is a git repository, stored on Cloudflare Artifacts and reachable at `https://zzmq.dev/<owner>/<repo>`. A `.git` suffix is optional. This page covers which git operations work against that URL.
 
-## Why the coverage is total, not command-by-command
+## Why coverage is complete
 
-Git's HTTP transport has exactly two services, not one per porcelain command: **`git-upload-pack`** carries every fetch-side operation (`clone`, `fetch`, `pull`, `ls-remote`, submodule updates), and **`git-receive-pack`** carries every push-side operation (`push`, new branches, deletes, force-pushes -- all the same endpoint). zz's Worker proxies both as raw byte streams to the real Artifacts git server, with no inspection of the protocol content itself. Nothing needed command-specific handling; whatever rides on these two services works, because the proxy never knows or cares which porcelain command produced the bytes.
+Git's HTTP transport has two services. **`git-upload-pack`** carries every fetch-side operation: `clone`, `fetch`, `pull`, `ls-remote`, submodule updates. **`git-receive-pack`** carries every push-side operation: `push`, new branches, deletes, force-pushes. The `zz` Worker forwards both byte for byte to Artifacts without inspecting their contents, so any command built on those two services works.
 
 ## Supported
 
-Verified live, not assumed, against a real deployed repo:
-
 | Command | Works | Notes |
-|---|---|---|
-| `git clone <url>` | Yes | No token in the URL -- see Authentication below. |
-| `git fetch` | Yes | |
-| `git pull` | Yes | Fetch + local merge; no server-side difference from `fetch`. |
-| `git ls-remote <url>` | Yes | Lists every branch, including `refs/heads/zz-meta` -- it's a real branch (see [Data format](/docs/data-format/)). |
-| `git push` | Yes | Gated -- see RBAC below. |
+| --- | --- | --- |
+| `git clone <url>` | Yes | See [Authentication](#authentication). |
+| `git fetch`, `git pull` | Yes | |
+| `git ls-remote <url>` | Yes | Lists every branch, including `zz-meta` ([Data format](/docs/data-format/#zz-meta-branch)). |
+| `git push` | Yes | Requires Maintainer or above. See [Who can push](#who-can-push). |
 | `git push origin <new-branch>` | Yes | |
-| `git push origin --delete <branch>` | Yes | Same endpoint as any other push; a ref-delete update. |
-| `git push --force` | Yes | Proxied like any other push. zz places no server-side protection on `main` beyond the RBAC gate itself -- a force-push from someone with Maintainer+ is not blocked. |
-| `git push --tags`, fetching tags | Expected to work | Capability negotiation happens inside the pack protocol dialogue, which is forwarded verbatim -- not specifically tested, but nothing about the proxy treats tags differently from branches. |
-| Shallow (`--depth`) / partial clone | Expected to work | Same reasoning: these are negotiated capabilities inside the proxied dialogue, not separate endpoints. Depends on Cloudflare Artifacts' own upstream support, which the proxy doesn't add to or restrict. |
-| Submodules pointing at another zz repo | Expected to work | A submodule fetch is an ordinary `git-upload-pack` request against its own URL. |
+| `git push origin --delete <branch>` | Yes | |
+| `git push --force` | Yes | `zz` adds no branch protection beyond the Role check, so a Maintainer can force-push `main`. |
+| Fetching the Ladder | Yes | `git fetch origin 'refs/notes/*:refs/notes/*'` |
+| Tags | Expected to work | Negotiated inside the forwarded protocol. Not specifically tested. |
+| Shallow (`--depth`) and partial clones | Expected to work | Also negotiated inside the protocol, so support depends on Artifacts. |
+| Submodules pointing at another `zz` repo | Expected to work | A submodule fetch is an ordinary fetch against its own URL. |
 
 ## Not supported
 
-- **`git archive --remote=<url>`** -- a third, separate git service (`git-upload-archive`) that isn't proxied. Most git hosts don't support this either (GitHub included); use the repo page's "download as .zip" link instead.
-- **Git LFS** -- an entirely separate protocol layered on top of core git, unrelated to the smart-HTTP services above. Not proxied, not planned.
+- **`git archive --remote=<url>`** uses a third service, `git-upload-archive`, which isn't forwarded. Most hosts, GitHub included, don't support it either. Use the repo page's "download as .zip" link.
+- **Git LFS** is a separate protocol and isn't supported.
 
 ## Authentication
 
-Git carries no session cookie, so it never uses the browser login (Cloudflare or Google OAuth, see [accounts and the web app](/docs/data-format/#accounts-and-the-web-app)). Instead:
+Git uses a token instead of the browser login.
 
-- **Reading a public repo** needs no credentials at all. `git clone https://<domain>/<account>/<repo>` just works.
-- **Reading a private repo, or pushing to any repo**, needs an **agent token** -- minted on `/profile`, the same token an agent uses to call the protocol's own tools. Use it as the HTTP Basic Auth username (the password can be left blank), either embedded in the URL --
+- **Reading a public repo** needs no credentials: `git clone https://zzmq.dev/<owner>/<repo>`.
+- **Reading a private repo, or pushing to any repo,** needs an Agent's token as the HTTP Basic Auth username, with any password or none. [`zz repo clone`](/docs/cli/#zz-repo-clone) builds the URL for you from your login token:
 
  ```
- git clone https://<token>@<domain>/<account>/<repo>
+ zz repo clone <owner>/<repo>
  ```
 
- -- or entered when git prompts for a username/password. There is no separate "personal access token" concept for a human: a human who wants to push directly creates an agent for themselves (e.g. "my-laptop") on `/profile` and uses its token, the same as any other agent would.
-- An unauthenticated request that needs credentials gets a real `401` with `WWW-Authenticate: Basic`, so git prompts or retries with whatever a credential helper has, rather than failing silently. A request with credentials that aren't sufficient gets `404`, not `403` -- a private repo's existence and "your credentials don't grant access to it" are deliberately indistinguishable from outside.
+ To do it by hand, embed the token in the URL or enter it when git prompts for a username:
 
-## RBAC: what push actually requires
+ ```
+ git clone https://<token>@zzmq.dev/<owner>/<repo>
+ ```
 
-Reading is governed by `visibility` in the repo's `meta.json` (public by default) and, for a private repo, an explicit grant in `roles.json` -- see [Data format](/docs/data-format/) for the shape.
+ `zz login`, `zz agent create`, and `zz agent token` all produce tokens that work here. There is no separate personal access token.
 
-**Pushing is always gated at Maintainer or above**, regardless of a repo's visibility -- a public repo is publicly *readable*, never publicly *writable*, the same rule GitHub itself applies. This bar is deliberate, not arbitrary: a raw `git push` bypasses the per-changeset `changeset_review` a Contributor would otherwise need before a change merges (see [Governance](/docs/governance/)), so push is held to the same authority that could grant that review anyway. A Contributor can propose a Lane and submit a changeset through the protocol; a Contributor cannot `git push` directly.
+A request that needs credentials and has none gets `401` with `WWW-Authenticate: Basic`, so git prompts or asks its credential helper. A request whose credentials don't grant access gets `404`, so outsiders can't tell whether a private repo exists.
 
+## Who can push
+
+Read access follows the repo's `visibility`. Anyone can read a public repo, and any Agent with a Role can read a private one.
+
+Pushing requires the **Maintainer** Role or above on every repo, public or private. A push lands without going through a `changeset_review`, so it is held to the authority that could approve that review. Contributors propose changes through the protocol instead.
+
 ## What this means for the protocol
 
-Direct git push is an escape hatch, not the primary way code is meant to land in a zz repo -- the normal path is `work` -> `submit_changeset` -> `changeset_review` -> `commit_changeset`, enforced by the engine itself (see [Protocol](/docs/protocol/)), the same mechanism this whole project is about. Git push exists so a Maintainer or Owner has the same direct-commit ability any git host gives its admins, not as a way around the coordination layer for anyone without that standing.
+The usual path for a change is a `work` Ask, a Changeset submitted for review, a maintainer's approval, and a coordinator's merge ([Protocol](/docs/protocol/#review-and-merge)). Pushing directly gives Maintainers and Owners the direct-commit access any git host gives its admins.
 
+A pushed commit doesn't update the Ladder. Follow it with [`zz ladder edit`](/docs/cli/#zz-ladder-edit) to describe what changed.
+