Skip to content

congwa/sub2claude

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sub2claude

sub2claude 把一批装好 Claude Code 的机器(每机一个 Claude 订阅、OAuth 登录)变成一个 OpenAI/Anthropic 兼容的中继 API——不用任何 model API key,算力来自这些机器的订阅额度。

  • worker 用本地 claude -p 出算力,不碰 model API key。
  • 中控 server 负责:用户体系 · 按用户粘性会话路由 · 扣费 · session 控制 · 限流 · 后台。
  • 脱胎于 sub2org(浏览器会话池):worker 从「浏览器扩展驱动网页」换成「CLI 驱动 headless Claude Code」;server / console 对 provider 透明、大量复用,核心新增只有一个 CLI worker daemon。

完整链路(多用户 · 多机)

一、部署拓扑

多台用户机(各跑一个 s2c)扇入 → 中心(1 台)← 扇入多台 worker 机(各绑 1 个订阅,各自直连 Anthropic):

flowchart LR
  subgraph U["① 用户机器(每人一台,各跑 s2c)"]
    direction TB
    A["用户A · s2c(keyA)<br/>项目 /projA<br/>交互客户端 + daemon"]
    B["用户B · s2c(keyB)<br/>项目 /projB"]
    C["用户C · s2c(keyC) …"]
  end
  subgraph S["② 中心(1 台,单实例)"]
    direction TB
    SV["中心 server (Rust)<br/>鉴权 · 限流 · 计费<br/>粘性 · 池调度 · 中继表"]
    CO["console 后台"]
    DB[("postgres")]
  end
  subgraph W["③ worker 池(每台 1 个 Claude 订阅)"]
    direction TB
    W1["wk1 · worker + claude -p · 订阅1"]
    W2["wk2 · worker + claude -p · 订阅2"]
    W3["wk3 · … · 订阅3"]
  end
  AN(["api.anthropic.com"])

  A -->|"socket.io(daemon) + HTTP /v1/chat"| SV
  B --> SV
  C --> SV
  SV <-->|"socket.io(worker)<br/>dispatch / chunk·done·mcp_call"| W1
  SV <--> W2
  SV <--> W3
  W1 -->|"推理·用订阅"| AN
  W2 --> AN
  W3 --> AN
  SV -.- CO
  SV -.- DB
Loading

中心的中继表是多用户隔离的关键(全部按 key 维度):

键 → 值 作用
daemons user_id → daemonSid 每个在线 s2c 的 daemon(谁在线、桥回哪台机器)
sessions session_id → {worker, claude_session} 粘性:同一 user 续接回同一 worker + --resume
pending req_id → {workerSid, daemonSid, charge} 一次在途请求:结果发哪个 worker、工具桥回哪个 daemon、扣谁的费
mcp_pending call_id → workerSid 一次工具调用:daemon 执行完把结果发回哪个 worker

二、并发时序(用户A、用户B 同时各发一个请求)

sequenceDiagram
  autonumber
  participant A as s2c-A · /projA
  participant B as s2c-B · /projB
  participant S as 中心 server
  participant W1 as wk1 · 订阅1
  participant W2 as wk2 · 订阅2
  participant AN as Anthropic

  A->>S: socket.io daemon(keyA) — 注册 daemons[A]
  B->>S: socket.io daemon(keyB) — 注册 daemons[B]

  A->>S: POST /v1/chat (keyA, 仅 prompt)
  Note over S: authA→userA · 选空闲 wk1<br/>pending[rA]={wk1, daemonA, 费A}
  S->>W1: dispatch rA (bridged)
  B->>S: POST /v1/chat (keyB) — 与 A 并发
  Note over S: authB→userB · 选空闲 wk2<br/>pending[rB]={wk2, daemonB, 费B}
  S->>W2: dispatch rB (bridged)

  W1->>AN: 推理(订阅1)
  W2->>AN: 推理(订阅2)

  W1->>S: mcp_call(rA, read src/x)
  S->>A: 按 pending[rA].daemonSid=A 路由(只回 A 的电脑)
  A-->>S: mcp_result(在 /projA 执行 read)
  S-->>W1: mcp_result → claude(A) 拿到内容
  W2->>S: mcp_call(rB, read src/y)
  S->>B: 按 pending[rB].daemonSid=B 路由(只回 B 的电脑)
  B-->>S: mcp_result(在 /projB 执行 read)
  S-->>W2: mcp_result → claude(B) 拿到内容

  Note over A,W2: ↻ A、B 各自循环工具(grep/edit/bash);edit·bash 前各自 s2c 弹 [y/N]

  W1-->>S: chunk / done rA
  S-->>A: 流式 SSE 答案A(按 userA token 结算·落 sessionA)
  W2-->>S: chunk / done rB
  S-->>B: 流式 SSE 答案B(按 userB token 结算·落 sessionB)
Loading

关键机制:

  • 隔离:A 的 mcp_callpending[rA].daemonSid 只桥回 A 的电脑(/projA),B 的只回 /projB——绝不串项目
  • 并发:每台 worker capacity=1(一个订阅一次一个请求),A→wk1、B→wk2 互不阻塞;加机器即扩并发,单台被限流只冷却那台。
  • 计费 / 粘性:各扣各的余额;同一 user 带 X-Sub2claude-Session 续接 → 回同一 worker、--resume 接上下文。
  • 项目不上传:只发 prompt;claude 用工具按需拉它真正碰到的文件(时序图中间的 ↻ 循环)。
  • 订阅只在 worker 消费:由真 claude -p——唯一合规路径,也是本地用 s2c(我们的客户端)而非真·本地 Claude Code 的原因。

组成

子项目 角色 技术栈
server/ 中继控制中心:用户 / 鉴权 / 计费 / 粘性会话 / worker 池调度 / 后台 API Rust(axum + socketioxide + sqlx/Postgres)
worker/ worker daemon:驱动 headless Claude Code(claude -p),本仓核心新增 Node.js + socket.io-client
bridge/ s2c 本地客户端:一条命令在本地项目起交互式编码会话,服务端 agent 的工具落到你本地项目执行——「脑在服务端、手在本地」。见 bridge/README.md Node.js
console/ Web 控制台:admin(workers / sessions / users / billing / logs / metrics)+ 用户自助 React 19 + Vite + Tailwind v4
deploy/ 单实例部署:postgres + server + nginx docker-compose

server/ console/ deploy/ 由 sub2org 同名部分改名而来sub2org→sub2claudesk-sub2org-→sk-sub2claude-X-Sub2org-*→X-Sub2claude-*SUB2ORG_*→SUB2CLAUDE_* 等),逻辑基本一致;worker/ 是全新的。

文档

  • bridge/README.md —— s2c 本地客户端:安装 / 三种模式(交互 · headless · 一次性)/ 权限与安全。
  • worker/README.md —— worker 部署、鉴权(claude setup-token)、安全(完整 Agent 沙箱)。
  • worker/claude-bridge/README.md —— 与 Claude Code 交互的模块细节与事件映射。
  • docs/USAGE.md / docs/DEPLOY.md —— 运营 / 消费 / 部署指南(worker 细节以 worker/README.md 为准)。
  • CLAUDE.md —— 给 Claude Code 的仓库指南。

Releases

Packages

Contributors

Languages