10 KiB
hoppscotch-backend-git
A self-hosted Hoppscotch-compatible backend that syncs workspace data to a Git repository.
Hoppscotch’s official backend keeps collections, environments, and related data in a database. Bruno keeps them as files in Git, but collaboration is async (pull / push / PR) and several team-oriented Git features sit behind a paid plan. This project aims at the gap between those models: live multi-client sync with Git as the durable, reviewable source of truth.
Status: early / work in progress. Phase A (Git store + REST + CLI) and Phase B (auth + personal GraphQL) are implemented. Upstream Hoppscotch is vendored as a Git submodule at
hoppscotch-upstream(hoppscotch/hoppscotch).
Why
Teams often want:
- A shared API client workspace that updates for everyone without manual export/import
- Collections and environments versioned in Git (diff, review, branch, audit)
- Self-hosting without a proprietary cloud sync service or per-seat Git UI fees
Exporting Hoppscotch collections into a repo works for occasional backup, not continuous team sync. Bruno solves Git-native storage well, but deliberately has no live sync and gates private remotes / full in-app Git workflows on paid tiers.
hoppscotch-backend-git keeps a Hoppscotch-style backend API while persisting (and syncing) data to Git.
How collaboration works
Each teammate runs this backend on their own machine and points Hoppscotch (Desktop / CLI) at localhost. Identity comes from the local OS account. The shared Git workspace repository is what syncs collections and environments between people — not a central Hoppscotch server.
User A machine User B machine
┌─────────────────────┐ ┌─────────────────────┐
│ Hoppscotch Desktop │ │ Hoppscotch Desktop │
│ │ │ │ │ │
│ hoppscotch-backend │ │ hoppscotch-backend │
│ (local :3200) │ │ (local :3200) │
│ │ │ │ │ │
│ GIT_REPO_PATH ────────── push/pull ──────── GIT_REPO_PATH │
└─────────────────────┘ ▲ └─────────────────────┘
│
shared Git remote
(collections / environments)
Local-only state (PATs, auto-generated secrets, signing keys, meta.json) lives under a per-user state directory on each machine and is not part of the workspace Git repo:
| OS | Default state directory |
|---|---|
| macOS | ~/Library/Application Support/hoppscotch-backend-git/ |
| Linux | ${XDG_DATA_HOME:-~/.local/share}/hoppscotch-backend-git/ |
Override with HOPP_STATE_DIR if needed.
Feature comparison
| Feature | Hoppscotch (cloud / self-host) | Bruno | Hoppscotch + hoppscotch-backend-git |
|---|---|---|---|
| Live multi-client sync | ✅ | ❌ | ✅ (goal) |
| Git as primary storage | ❌ (database) | ✅ | ✅ (goal) |
| Reviewable diffs / PRs for collections | ⚠️ via export only | ✅ | ✅ (goal) |
| Offline-first | ⚠️ partial (local / desktop) | ✅ | ✅ with local backend |
| Collaboration model | Shared backend | Git (async) | Local backends + shared Git workspace |
| Private Git remotes without paid client | N/A | ❌ (Pro+ for in-app private remotes) | ✅ (your Git hosting) |
| In-app commit / push / branch / merge UI | N/A | ❌ (Pro+ for advanced Git UI) | ✅ (goal) |
| Self-hosted, you control the data plane | ✅ (Community / Enterprise) | ✅ (local files) | ✅ (goal) |
Notes:
- Bruno’s collaboration is Git collaboration, not realtime shared sessions. That is intentional; see Bruno’s pricing and product FAQ.
- Official Hoppscotch self-hosting stores data in a database, not a Git repo.
- Rows marked “(goal)” describe the intended behavior of this project and are not all implemented yet.
Architecture (intended)
Hoppscotch clients (web / desktop / CLI) on each user's machine
│
▼
hoppscotch-backend-git (local) ←── Hoppscotch-compatible API
│
├── serve that user's Desktop / CLI session
└── commit / push / pull workspace state to the shared Git repository
Git is the team sync plane and review surface. Each local backend is what that user's clients talk to.
Repository layout
| Path | Role |
|---|---|
hoppscotch-upstream/ |
Git submodule of official Hoppscotch |
src/ |
Bun + TypeScript backend (REST, auth, GraphQL) |
tests/ |
axios + Hoppscotch CLI integration tests |
fixtures/ |
Sample collection / environment helpers |
Development
Clone with submodules:
git clone --recurse-submodules ssh://git@git.kaki87.net:3021/KaKi87/hoppscotch-backend-git.git
cd hoppscotch-backend-git
If you already cloned without submodules:
git submodule update --init --recursive
Install and run:
bun install
bun run prepare:webapp # extracts official selfhost-web UI + points it at this backend
export GIT_REPO_PATH=./.data/workspace-git # clone of the shared workspace repo
bun run start
On first start, JWT / webapp signing secrets are generated under the state directory (secrets.json). Optional env overrides still work for tests and special setups.
Type-check and test:
bun run typecheck
bun test
Configuration
| Variable | Required | Description |
|---|---|---|
GIT_REPO_PATH |
yes | Local checkout of the shared Git repo storing collections/ and environments/ |
HOPP_STATE_DIR |
no | Local state root for meta.json, secrets.json, signing.key (see defaults above) |
META_PATH |
no | Override path for users / PATs (default $HOPP_STATE_DIR/meta.json) |
JWT_SECRET |
no | Override JWT/PAT pepper (default: auto-generated in $HOPP_STATE_DIR/secrets.json) |
PORT |
no | Listen port (default 3200) |
GIT_AUTO_PUSH |
no | true to git push after each commit (default false) |
WEBAPP_FRONTEND_PATH |
no | Frontend files bundled for Hoppscotch Desktop (default ./webapp-frontend) |
WEBAPP_SERVER_SIGNING_SECRET |
no | Override ed25519 seed for desktop bundle signatures (default: auto-generated in secrets.json) |
WEBAPP_SERVER_SIGNING_KEY_FILE |
no | Override signing key path (default $HOPP_STATE_DIR/signing.key) |
DEV_USER_OVERRIDE |
no | Dev-only JSON { "email", "displayName", "uid"? } to override local identity (ignored/rejected in compiled builds) |
Each user runs their own server. Authentication is the local macOS account via dscl (RecordName, EMailAddress, RealName), unless DEV_USER_OVERRIDE is set. Hoppscotch-compatible /v1/auth/* routes remain as stubs (empty providers, desktop token exchange).
Git workspace layout
$GIT_REPO_PATH/
collections/<id>.json # Hoppscotch HoppCollection (v12)
environments/<id>.json # Hoppscotch Environment (v2)
Useful endpoints
GET /health- Desktop instance:
GET /api/v1/key,/api/v1/manifest,/api/v1/bundle - REST CRUD:
/v1/collections,/v1/environments - CLI:
GET /v1/access-tokens/collection/:id,GET /v1/access-tokens/environment/:id(Bearerpat-…) - Auth:
/v1/auth/providers,/signin,/verify,/refresh,/logout,/verify-token - GraphQL:
POST /graphql(personal workspace ops + subscriptions)
Example CLI run against a local server:
hopp test <collection-id> --token pat-… --server http://127.0.0.1:3200
License
This project is licensed under the MIT License, the same as Hoppscotch.
Upstream Hoppscotch code under hoppscotch-upstream/ retains its own MIT license and copyright.