Full Git in the browser. Zero WASM. One HTTP endpoint.
一个让浏览器拥有完整 Git 能力的 RPC 框架 —— 无需 WASM,一个 HTTP 端点搞定一切。
Building a browser IDE? A Git GUI? An AI coding sandbox with OpenClaw? Running inside WebContainers?
You need Git — but git doesn't run in the browser. WASM ports are heavy and incomplete.
git-web-rpc gives your browser a git object that looks and feels like the real thing:
const git = createGitProxy({ endpoint: '/api/git' })
await git.clone({ dir: '/repo', url: 'https://github.com/user/repo' })
await git.add({ dir: '/repo', filepath: 'README.md' })
await git.commit({ dir: '/repo', message: 'from the browser', author: { name: 'Dev', email: 'dev@example.com' } })Under the hood, every call is transparently proxied via ES Proxy to a server running isomorphic-git. Your UI code stays clean. The transport is invisible.
想在浏览器里做 IDE?做 Git GUI?用 OpenClaw 做 AI 编程沙箱?在 WebContainers 里运行?
你需要 Git —— 但 git 无法在浏览器中运行。WASM 方案又重又不完整。
git-web-rpc 给浏览器提供一个 git 对象,用起来和真正的 Git API 一模一样。底层通过 ES Proxy 将每次调用透明转发到服务端的 isomorphic-git。UI 代码保持干净,传输层完全透明。
| English | 中文 | |
|---|---|---|
| 🪄 | ES Proxy magic — calls look local, execute remote | ES Proxy 魔法 — 调用看起来是本地的,实际远程执行 |
| 🔒 | End-to-end type safety — shared types, zero any |
端到端类型安全 — 共享类型定义,零 any |
| ⚛️ | React hooks — useStatusMatrix, useGitCommit, etc. |
React Hooks — useStatusMatrix、useGitCommit 等 |
| 📡 | Real-time SSE — live progress + file-watcher notifications | 实时 SSE — 实时进度 + 文件变更通知 |
| 🧊 | Sandbox isolation — per-session memfs, multi-user safe | 沙箱隔离 — 每会话独立 memfs,多用户安全 |
| 🔌 | Pluggable adapters — Node.js, Express, Next.js App Router | 可插拔适配器 — Node.js、Express、Next.js |
| 🖥️ | CLI — git-rpc-serve starts a server in one command |
CLI — 一条命令启动服务 |
| 📂 | File watching — chokidar pushes status changes via SSE | 文件监听 — chokidar 自动推送状态变更 |
Browser Server
┌─────────────────────┐ ┌──────────────────────────┐
│ React Components │ │ HTTP Router │
│ useStatusMatrix() │ │ ↓ │
│ useGitCommit() │ │ Git Router (whitelist) │
│ ↓ │ HTTP POST │ ↓ │
│ ES Proxy Client │ ─────────────► │ isomorphic-git │
│ git.commit(args) │ │ { fs: memfs, ...args } │
│ ↓ │ ◄─────────── │ ↓ │
│ { ok, data } │ JSON resp │ { ok, data } │
│ │ │ │
│ EventSource ◄─────│── SSE ────────│── StatusNotifier │
│ (live updates) │ │ + FileWatcher │
└─────────────────────┘ └──────────────────────────┘
The client creates an ES Proxy object. Any property access (e.g. git.status) returns an async function that serializes the call as { method, args } and sends it via HTTP POST. The server validates the method against a whitelist, injects fs/http dependencies, and calls isomorphic-git. Network operations (clone/push/pull) stream progress back over SSE.
客户端创建一个 ES Proxy 对象。任何属性访问(如 git.status)都返回一个异步函数,将调用序列化为 { method, args } 并通过 HTTP POST 发送。服务端校验白名单、注入 fs/http 依赖后调用 isomorphic-git。网络操作(clone/push/pull)通过 SSE 实时推送进度。
- Node.js >= 18
- npm or pnpm
# Install root dependencies / 安装根目录依赖
npm install
# Install frontend dependencies / 安装前端依赖
cd web && npm install# Start both backend (port 3001) and frontend (port 5173)
# 同时启动后端 (3001) 和前端 (5173)
npx task devOr start them separately / 或分别启动:
npx ts-node packages/server/httpAdapter.ts # backend / 后端
cd web && npx vite --host # frontend / 前端Open http://localhost:5173 — you should see the demo app with clone, status, commit, and branch management.
打开 http://localhost:5173 —— 你会看到包含 clone、status、commit 和分支管理的演示应用。
import { createGitProxy } from 'git-web-rpc/client'
const git = createGitProxy({ endpoint: '/api/git' })
await git.clone({ dir: '/repo', url: 'https://github.com/user/repo' })
const matrix = await git.statusMatrix({ dir: '/repo' })
await git.add({ dir: '/repo', filepath: 'README.md' })
await git.commit({
dir: '/repo',
message: 'hello from the browser',
author: { name: 'Dev', email: 'dev@example.com' },
})import { GitProvider, useStatusMatrix, useGitCommit } from 'git-web-rpc/client/hooks'
function App() {
return (
<GitProvider endpoint="/api/git">
<StatusView dir="/repo" />
</GitProvider>
)
}
function StatusView({ dir }: { dir: string }) {
const { data: matrix, loading } = useStatusMatrix(dir)
const { mutate: commit } = useGitCommit()
if (loading) return <p>Loading...</p>
return (
<div>
<pre>{JSON.stringify(matrix, null, 2)}</pre>
<button onClick={() => commit({
dir,
message: 'update',
author: { name: 'Dev', email: 'dev@example.com' },
})}>
Commit
</button>
</div>
)
}// app/api/git/route.ts
import { createNextAppRouteHandler } from 'git-web-rpc/server'
import fs from 'node:fs'
const { POST, GET } = createNextAppRouteHandler({ fsImpl: fs })
export { POST, GET }import express from 'express'
import { createExpressMiddleware } from 'git-web-rpc/server'
const app = express()
app.use('/api/git', createExpressMiddleware())
app.listen(3001)npx git-rpc-serve --port 3001Options:
-p, --port <number> Port to listen on (default: 3001, env: PORT)
-h, --help Show help
-v, --version Show version
git-web-rpc is purpose-built for browser-based development environments. Here's how it fits:
git-web-rpc 专为浏览器开发环境设计,以下是集成方式:
Run the git-rpc server inside a WebContainer. Connect the Proxy client from your editor UI. Full Git — clone, commit, push — without ever leaving the browser sandbox.
在 WebContainer 中运行 git-rpc 服务端,从编辑器 UI 连接 Proxy 客户端。完整的 Git 能力 —— clone、commit、push —— 无需离开浏览器沙箱。
// Inside your WebContainer boot script
// 在 WebContainer 启动脚本中
const serverProcess = await webcontainer.spawn('npx', ['git-rpc-serve', '--port', '3001'])
// In your editor UI
// 在编辑器 UI 中
const git = createGitProxy({ endpoint: `${webcontainerUrl}/api/git` })
await git.clone({ dir: '/project', url: repoUrl })Drop in the React hooks to add Git panels to your AI-powered coding interface. The useStatusMatrix hook auto-refreshes via SSE when files change — no polling needed.
直接使用 React Hooks 为 AI 编程界面添加 Git 面板。useStatusMatrix 通过 SSE 自动刷新 —— 无需轮询。
import { GitProvider, useStatusMatrix, useGitCommit, useGitClone } from 'git-web-rpc/client/hooks'
// Wrap your app / 包裹你的应用
<GitProvider endpoint="/api/git">
<YourAICodingUI />
</GitProvider>For multi-user environments, use SandboxManager to give each session its own isolated memfs volume:
多用户环境下,使用 SandboxManager 为每个会话提供独立的 memfs 虚拟文件系统:
import { SandboxManager } from 'git-web-rpc/server'
const manager = new SandboxManager({
maxSessions: 50,
idleTimeoutMs: 30 * 60 * 1000,
onPersist: async (sessionId, json) => { /* save to Redis/DB */ },
onRestore: async (sessionId) => { /* load from Redis/DB */ },
})| Operation | Type | Description / 描述 |
|---|---|---|
status |
read | File status / 文件状态 |
statusMatrix |
read | Full working tree status / 完整工作树状态 |
log |
read | Commit history / 提交历史 |
currentBranch |
read | Current branch name / 当前分支名 |
listBranches |
read | All local branches / 所有本地分支 |
listFiles |
read | Files tracked in index / 索引中的文件 |
readBlob |
read | Read file content by OID / 按 OID 读取文件 |
clone |
write | Clone a remote repo / 克隆远程仓库 |
init |
write | Initialize a new repo / 初始化仓库 |
add |
write | Stage files / 暂存文件 |
remove |
write | Remove files from index / 从索引移除 |
commit |
write | Create a commit / 创建提交 |
branch |
write | Create a branch / 创建分支 |
deleteBranch |
write | Delete a branch / 删除分支 |
checkout |
write | Switch branches / 切换分支 |
fetch |
network | Fetch from remote / 拉取远程 |
push |
network | Push to remote / 推送到远程 |
pull |
network | Pull from remote / 拉取并合并 |
resetIndex |
write | Unstage a file / 取消暂存 |
| Hook | Returns | Description / 描述 |
|---|---|---|
useStatusMatrix(dir) |
{ data, loading, error, refresh } |
Working tree status (auto-refreshes via SSE) / 工作树状态(SSE 自动刷新) |
useGitLog(dir, depth?) |
{ data, loading, error, refresh } |
Commit history / 提交历史 |
useGitStatus(dir, filepath) |
{ data, loading, error, refresh } |
Single file status / 单文件状态 |
useBranch(dir) |
{ data, loading, error, refresh } |
Current branch / 当前分支 |
useBranches(dir) |
{ data, loading, error, refresh } |
All branches / 所有分支 |
useListFiles(dir) |
{ data, loading, error, refresh } |
Tracked files / 已跟踪文件 |
useGitClone() |
{ mutate, loading, error } |
Clone operation / 克隆操作 |
useGitInit() |
{ mutate, loading, error } |
Init operation / 初始化操作 |
useGitAdd() |
{ mutate, loading, error } |
Stage files / 暂存文件 |
useGitCommit() |
{ mutate, loading, error } |
Commit / 提交 |
useGitCheckout() |
{ mutate, loading, error } |
Checkout branch / 切换分支 |
useGitBranch() |
{ mutate, loading, error } |
Create branch / 创建分支 |
useGitResetIndex() |
{ mutate, loading, error } |
Unstage file / 取消暂存 |
createGitProxy({
endpoint: '/api/git', // RPC endpoint
eventsEndpoint: '/api/git/events', // SSE endpoint for progress
timeout: 30000, // Request timeout (ms)
onProgress: (event) => {}, // Progress callback for network ops
onRequest: (req) => req, // Request interceptor (e.g. add auth headers)
onResponse: (res) => {}, // Response interceptor (e.g. error reporting)
})git-web-rpc/
├── packages/
│ ├── shared/types.ts # Shared type definitions / 共享类型
│ ├── client/
│ │ ├── gitProxy.ts # ES Proxy RPC client / ES Proxy 客户端
│ │ ├── hooks/useGit.tsx # React hooks / React Hooks
│ │ └── components/ # Ready-made UI components / 预制 UI 组件
│ └── server/
│ ├── gitRouter.ts # RPC router + method whitelist / RPC 路由
│ ├── httpAdapter.ts # HTTP adapters (Node/Express/Next) / HTTP 适配器
│ ├── gitSandbox.ts # Per-session memfs isolation / 沙箱隔离
│ ├── fileWatcher.ts # Chokidar file watcher / 文件监听
│ ├── statusNotifier.ts # SSE status push / SSE 状态推送
│ └── cli.ts # CLI entry point / CLI 入口
├── web/ # Demo app (Vite + React) / 演示应用
├── docs/ # Architecture docs / 架构文档
└── __tests__/ # Unit + property-based tests / 测试
Contributions are welcome! / 欢迎贡献!
- Fork the repo / Fork 本仓库
- Create a feature branch / 创建特性分支 (
git checkout -b feat/amazing-feature) - Commit your changes / 提交更改
- Open a Pull Request / 发起 PR
Please run tests before submitting / 提交前请运行测试:
npm test
npm run typecheckMade for the browser. Powered by isomorphic-git.
为浏览器而生,由 isomorphic-git 驱动。