walgit
Git server that stores repositories in an object bucket
TLDR
SYNOPSIS
walgit [--config PATH] [command] [args]
DESCRIPTION
walgit hosts Git repositories as one binary in front of an S3-compatible bucket or Google Cloud Storage. The bucket is a write-ahead log. A push is stored as immutable pack objects and becomes visible only when a small manifest is replaced with a compare-and-swap. That swap is the only commit point, so any instance pointed at the same bucket serves the same history. There is no database and no elected primary. Local disk is a cache.Upstream `git` still runs upload-pack, repack, and bundle creation. walgit implements receive-pack, the log, and the storage plumbing. Fresh clones can download bundle-uri bundles as static objects from the bucket or a CDN and ask the server only for the remainder. Repositories larger than the machine are served with HTTP range reads: refs and the web UI do not need every pack on local disk.Clients authenticate with a bearer token, or with OpenID Connect (browser sign-in, then a walgit access token for Git). A push to a new name creates the repository when `autocreateon_push` is set.The walgit-server binary is walgit serve under the name a standalone deployment expects. It accepts --config and nothing else.Every key in the config file can also be set from the environment as `WALGIT_SECTIONKEY` using TOML value syntax. A missing config file exits 2. **--config /dev/null** is the explicit way to run on built-in defaults plus `WALGIT_` variables, so a typo in the path does not silently open whatever bucket the ambient credentials can see.The layout follows the write-ahead-log-on-object-storage design Cursor published as Continuity. The repository keeps that write-up in `docs/reference/cursor-git-at-any-scale.md`.
PARAMETERS
--config PATH
Configuration file. Default `walgit.toml`. The environment variable WALGIT_CONFIG sets the same path. The flag is global and applies to every subcommand.serve
Run the HTTP server: Git smart HTTP (protocol v0 and v2), Git LFS, bundle-uri, the JSON API, and the web UI. Checkpoints, compaction, bundle builds, and the webhook bridge run in this process only when `server.roles` includes them. With no subcommand, walgit does this.repo create owner/name
Create an empty repository. --object-format is `sha1` (the default) or `sha256`.repo list
List repositories in the bucket.repo info owner/name
Show one repository.repo policy get owner/name
Print `policy.json` (protected refs, fast-forward rules). An empty document means allow-all.repo policy set --file PATH owner/name
Replace the push policy from a JSON file.repo policy clear owner/name
Delete the policy.repo settings show owner/name
Print the per-repository settings document stored in the log. --effective prints the host config merged with those overrides.repo settings set --file PATH owner/name
Replace settings (bundle, maintenance, and compaction overrides). `-` reads stdin. --message records a reason. An invalid document is not published.repo settings clear owner/name
Drop per-repository settings and return to the host config.repo settings history owner/name
List settings changes from the log.import --from PATH owner/name
Copy an existing Git repository into the bucket. --refs GLOB (repeatable) chooses refs; the default is `refs/heads/*` and `refs/tags/*`, and the target of HEAD is always kept. --reuse-packs copies the source packfiles instead of repacking. --direct uploads into the bucket without a local walgit checkout. With --direct, --replace supersedes a non-empty repository and --force restarts an interrupted import after the target manifest has moved.mirror --from URL --to URL --dir PATH
Keep selected refs on a walgit host equal to the same refs on another Git host, through a local bare buffer in PATH. --ref (repeatable) defaults to `refs/heads/main`. --interval defaults to 30s between fetch-and-push ticks. --once does a single tick and exits non-zero if the push failed. --force updates the destination even when that is not a fast-forward. --identity is `token` (the default, from `$WALGIT_TOKEN`), `gcloud`, or `gce`.compact [owner/name]
Geometric repack. --all selects every repository. --once runs one pass and exits. --base rebuilds the tier-2 base pack with `git repack` and needs the whole pack set on local disk.bundle run
Build bundle-uri slots that are due. --repo and --strategy restrict the work.bundle plan owner/name
Print each strategy's slots: built, missing, unavailable, or assigned to another host.bundle compose owner/name
Publish a full bundle by composing a header with the tier-2 base pack inside the bucket, so the bytes do not pass through this machine. Run it after compact --base.bundle rm owner/name id ...
Remove bundle ids (`strategy-token`, as printed by bundle plan) from the list and delete their objects.wal ls owner/name
List log entries. --from and --to bound the sequence numbers.wal show owner/name seq
Print one log entry.wal materialize --at-seq N --out PATH owner/name
Write the repository as it was at sequence N into a new directory.config check
Parse the config and print OK or the error. --env-file PATH (repeatable) also applies `WALGIT__` overrides from a `KEY=VALUE` file. --strict exits 3 when this build ignores an override.config dump
Print the effective configuration as TOML.synth --out PATH --size PRESET
Generate a deterministic synthetic repository with `git fast-import`. PRESET is `s`, `m`, or `l`. --seed, --commits, and --files override the preset. PATH must be missing or empty.
CONFIGURATION
`walgit.toml` is TOML. `walgit.example.toml` documents every key. `walgit.standalone.toml` is a one-machine setup with its own TLS certificate and a local S3-compatible store.
listen = "0.0.0.0:8080"
public_url = "https://git.example.com"
auto_create_on_push = true
[server.auth]
mode = "token"
anonymous_read = false
tokens = [{ principal = "me", token_env = "WALGIT_TOKEN_ME", write = true }]
[store]
backend = "s3"
bucket = "my-walgit"
[store.s3]
endpoint = "https://s3.us-east-1.amazonaws.com"
region = "us-east-1"
CAVEATS
`server.auth.mode = "none"` treats every caller as an anonymous writer and is refused unless the listen address is loopback. The optional GitHub Enterprise facade (`[github] enabled = true`) is auth-free on purpose and is for local development: turning it on requires `mode = "none"` and then allows that mode to bind beyond loopback. The network is the trust boundary.`accel_redirect` answers bundle and LFS downloads with `X-Accel-Redirect` so nginx streams the bytes from the bucket. Enable it only behind that edge. The response carries a store credential.Two instances can accept pushes to the same repository at once. Only one manifest swap wins; the other re-reads and retries. The client is told `ok` only after the bucket accepts the swap.Base-pack rebuilds and some bundle builds need a host that can hold the packs. A machine that only has a small cache can still advertise refs and serve objects by range.
