API
Every gitcask instance serves git, LFS and a JSON API for every repository under that repository's own path.
One prefix per repository
Everything for a repository starts with /{owner}/{repo}, so a proxy routes on the first two path segments alone.
| Lane | Prefix | For |
|---|---|---|
| Direct | /{owner}/{repo}/api | Servers and CLIs |
| Browser | /{owner}/{repo}/api-browser | Same handlers; CORS only for server.cors_origins |
| Reference | /docs | Scalar UI over /openapi.json |
| Discovery | /api/v1 | Not tied to a repository |
Git and LFS
Standard git and git-lfs clients work unchanged. Paths are relative to the repository prefix.
| Route | Purpose |
|---|---|
GET /info/refs | Ref advertisement |
POST /git-upload-pack | Clone and fetch |
POST /git-receive-pack | Push |
POST /info/lfs/objects/batch | LFS batch |
GET HEAD PUT /info/lfs/objects/{oid} | LFS basic transfer |
POST /info/lfs/verify | LFS verify |
| Surface | Supported |
|---|---|
| Protocol | Smart HTTP v0 and v2 |
| Fetch | ls-refs with prefixes, filter, shallow, deepen, sideband-all |
| Push | atomic, delete, tags, push options, report-status-v2 |
Reads
Reads need the read scope. Paths are relative to the repository prefix.
| Route | Purpose |
|---|---|
GET /api | Repository summary |
GET /api/refs | Get the default ref |
GET /api/refs/{kind} | List branches or tags; query prefix, q, after, n |
GET /api/resolve | Resolve the default ref |
GET /api/resolve/{rest} | Resolve a revision and optional path |
GET /api/tree/{rest} | Browse a tree |
GET /api/blob/{rest} | Read a blob; inline up to 2 MiB, raw for text/plain |
GET /api/commits | List commits |
GET /api/commit/{sha} | Get commit details |
GET /api/compare/{base}...{head} | Compare two revisions |
GET HEAD /api/archive/{archive_ref} | Download an immutable repository archive |
Writes
Writes need the write scope. A stale expected_old_oid, expected_head_oid or expected_base_oid returns 409.
| Route | Purpose |
|---|---|
PUT /api/refs/heads/{name} | Create or move a branch; body target, optional expected_old_oid |
DELETE /api/refs/heads/{name} | Delete a branch; optional ?expected_old_oid= |
PUT /api/refs/tags/{name} | Create or move a lightweight tag |
DELETE /api/refs/tags/{name} | Delete a tag |
POST /api/tags | Create an annotated tag |
POST /api/commits | Commit a batch of file changes |
POST /api/merges | Merge one revision into a branch: merge, squash or fast-forward-only; expected_base_oid required |
POST /api/initialize | Initialize a pristine repository from a pinned Gitcask tree |
POST /api/import/resolve | Pin a full-history import source |
POST /api/import | Import pinned complete history into a pristine repository |
GET /api/import/receipt | Read a committed import receipt |
Commit without a clone
One request writes blobs, trees and a commit, then moves the branch through the WAL. Replace expected_head_oid with the branch's current oid; content is standard base64.
curl -fsS -X POST http://127.0.0.1:8080/acme/web/api/commits \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d @- <<'JSON'
{
"branch": "main",
"message": "Update the readme",
"expected_head_oid": "<current oid of main>",
"committer": { "name": "CI", "email": "ci@example.com", "when": "2026-10-07T09:00:00Z" },
"changes": [
{ "op": "upsert", "path": "README.md", "content": "IyBXZWIK", "mode": "100644" },
{ "op": "rename", "from": "docs/old.md", "to": "docs/new.md" },
{ "op": "delete", "path": "tmp/scratch.txt" }
]
}
JSON| Field | Value |
|---|---|
changes[].op | upsert (path, content, mode), delete (path), rename (from, to) |
mode | 100644, 100755 or 120000 |
when | RFC 3339 with an explicit offset or Z |
author | Optional; defaults to committer |
expected_head_oid | Optional; omitted means the branch is force-updated |
allow_empty | Optional; defaults to false |
A 201 answer names what moved.
- ref
- The full ref name, such as
refs/heads/main. - oid, commit_oid
- The new commit.
- seq
- The WAL sequence that published it.
Repository and tasks
Long work runs as a task. Send Accept: text/event-stream to follow it live.
| Route | Purpose |
|---|---|
PUT /{owner}/{repo} | Create a repository |
DELETE /{owner}/{repo} | Delete a repository |
GET /api/overview | Repository operational status |
GET /api/ops | List repository operations |
POST /api/ops/{op} | Run an operation as a task; needs write |
GET /api/tasks | List repository tasks |
GET /api/tasks/{id} | Get or attach to a task |