FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

HernandoR/ripgit: A fast, searchable, self-hosted Git remote built with Durable Objects · GitHub

 
 

Repository files navigation

ripgit

A self-hostable git remote backed by Cloudflare Durable Objects. One DO per repo, SQLite storage, FTS5 search, delta compression via xpatch. Built in Rust with workers-rs.

Live example: git.theagents.company — deathbyknowledge's repos including agents (~1k commits) and curl (~40k commits)

git remote add origin https://your-worker.workers.dev/username/myproject
git push origin main

Features

  • Standard git remote — git push, git clone, git fetch with any git client
  • Auth via Service Binding — sits behind an auth worker; public read, owner-only write. GitHub OAuth example in examples/github-oauth/
  • Agent-first UI — browsable pages also negotiate text/markdown and text/plain, with explicit actions and curl-friendly paths
  • Web UI — file browser, commit history, diffs, code search, syntax highlighting, branch selector, markdown README, repo settings
  • Full-text search — FTS5 over file content and commit messages. Supports @author:, @message:, @path:, @ext:, @content: query prefixes
  • Raw file serving — /:owner/:repo/raw/:ref/*path
  • Read API — refs, commits, trees, files, diffs, search, stats
  • Repo registry — repos listed on the owner profile page after first push
  • Delta compression — 5–20x compression on real repos depending on file churn
  • One DO per repo — strict isolation, scales horizontally

URLs

/:owner/                   owner profile — lists your repos
/:owner/:repo/             repo home — file tree, README, recent commits
/:owner/:repo/commits      commit history
/:owner/:repo/commit/:sha  commit detail with diff
/:owner/:repo/tree/:ref/*  directory browser
/:owner/:repo/blob/:ref/*  file viewer
/:owner/:repo/raw/:ref/*   raw file bytes
/:owner/:repo/search-ui    full-text search
/:owner/:repo/settings     stats, index rebuilds, config, delete (owner only)

API

All endpoints under /:owner/:repo/.

Endpoint Description
GET /refs List branches and tags
GET /log?ref=main&limit=50 Commit history
GET /commit/:hash Single commit
GET /tree/:hash Directory listing
GET /blob/:hash File content
GET /file?ref=main&path=src/lib.rs File at ref + path
GET /search?q=TODO Code search
GET /search?q=fix&scope=commits Commit message search
GET /diff/:sha Commit diff
GET /compare/base...head Two-commit comparison
GET /stats Compression and storage stats

Text Mode For Agents

Browsable pages support negotiated text mode for curl, scripts, and agents.

curl -H 'Accept: text/markdown' https://your-worker.workers.dev/alice/repo/
curl -H 'Accept: text/plain' https://your-worker.workers.dev/alice/repo/commits
curl 'https://your-worker.workers.dev/alice/repo/tree/main/src?format=md'
  • Accept: text/markdown returns a markdown view
  • Accept: text/plain returns the same content as plain text
  • ?format=md or ?format=text works when you can't keep headers attached while following links
  • Text pages list bare GET paths under headings like Files (GET paths) and spell out POST actions, fields, and requirements in an Actions section

Authentication

ripgit reads identity from trusted X-Ripgit-Actor-* headers, which are only settable by an upstream auth worker via Service Binding (not from the public internet).

  • Anonymous — read access to all repos
  • Authenticated — read + write to repos under your username

GitHub OAuth example

examples/github-oauth/ is a TypeScript Cloudflare Worker that authenticates with GitHub, issues session cookies for browsers and long-lived tokens for agents/scripts, and forwards requests to ripgit via Service Binding. Its landing page and /settings also support the same text-mode negotiation for curl-driven agents.

See examples/github-oauth/README.md for a focused deploy/setup guide.

Local dev:

cd examples/github-oauth
npm install
npm run dev:full   # auth worker on :8787, ripgit as service binding

Visit http://localhost:8787 → sign in → go to /settings → create a token → push:

git remote add origin http://username:TOKEN@localhost:8787/username/myrepo
git push origin main

First-time setup:

  1. Create a GitHub OAuth App — callback URL: http://localhost:8787/oauth/callback
  2. Set GITHUB_CLIENT_ID in examples/github-oauth/cloudflare.config.ts
  3. cf workers secrets update GITHUB_CLIENT_SECRET --worker ripgit-auth
  4. cf workers secrets update SESSION_SECRET --worker ripgit-auth
  5. cf kv namespaces create --title OAUTH_KV → fill the ID into examples/github-oauth/cloudflare.config.ts

Deploy:

cf deploy                          # ripgit worker
cd examples/github-oauth && cf deploy   # auth worker

Update the GitHub OAuth App's callback URL to your deployed auth worker URL.

Push test script

./scripts/push-test.sh -u username -t TOKEN -w https://your-worker.dev -r /path/to/repo

Setup (ripgit only, no auth)

Prerequisites: Rust, the cf CLI, LLVM (for zstd-sys).

The cf version this repo is pinned to is declared in mise.toml, so mise users get it with mise install:

brew install llvm
git clone https://github.com/your-org/ripgit
cd ripgit
mise install                            # installs the pinned cf CLI
npm install                             # installs JavaScript dependencies used by cf's build pipeline
cf kv namespaces create --title REGISTRY   # fill the ID into cloudflare.config.ts
cf deploy

Without the auth worker in front, all repos are publicly readable and writable by anyone with the URL.

Cloudflare CLI (cf)

This project uses Cloudflare's cf CLI for local development and deployment. The version is pinned in mise.toml; install it with mise install or use the version from package.json through npm. Worker settings belong in cloudflare.config.ts.

# Start the ripgit Worker locally
cf dev

# Create the registry KV namespace once, then add its ID to cloudflare.config.ts
cf kv namespaces create --title REGISTRY

# Deploy the ripgit Worker
cf deploy

The repository still contains wrangler.config.ts because cf currently uses Wrangler's build backend. Wrangler is an implementation detail here; use cf for the Worker lifecycle and resource management commands.

Architecture

browser / git client / agent
  │
  ▼
Auth Worker  (examples/github-oauth — optional, recommended)
  │  validates session/token, sets X-Ripgit-Actor-* headers
  │  Service Binding
  ▼
ripgit Worker  (entry, routing)
  │  /:owner/:repo/* → DO named "{owner}/{repo}"
  │  /:owner/        → profile page (queries REGISTRY KV)
  ▼
Repository Durable Object  (one per repo)
  ├── schema.rs   11 tables + 3 FTS5 virtual tables
  ├── pack.rs     streaming pack parser + pack generator
  ├── git.rs      smart HTTP protocol (receive-pack, upload-pack)
  ├── store.rs    delta compression, commit graph, FTS rebuild
  ├── api.rs      read API
  ├── diff.rs     tree diff + line-level diffs
  └── web.rs      server-rendered HTML (9 pages)
  ▼
SQLite  (up to 10 GB per DO)

KV namespaces:
  REGISTRY  — "repo:{owner}/{repo}" written on first push
  OAUTH_KV  — tokens, sessions (auth worker only)

Pushing large repos

Cloudflare Workers has a 100 MB request body limit. Push large repos incrementally:

./scripts/push-test.sh -u username -t TOKEN -r /path/to/repo -s 200

Or manually in checkpoints:

STEP=250
for FP in $(seq $STEP $STEP $(git rev-list --first-parent --count main)); do
  SHA=$(git rev-list --reverse --first-parent main | sed -n "${FP}p")
  git push origin "${SHA}:refs/heads/main"
done
git push origin main

Known limitations

  • DO storage timeout — pushes with >~10K objects per push can exceed the 30 s timeout; push incrementally
  • 100 MB request body limit — hard Workers platform constraint
  • No force push — may produce inconsistent state
  • No annotated tags — silently dropped; lightweight tags work

License

AGPL-3.0. See LICENSE.

Acknowledgments

Inspired by pgit and the xpatch delta compression library.

About

A fast, searchable, self-hosted Git remote built with Durable Objects

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages


Back | FazBrowse Home | New Git URL