78 lines
3.7 KiB
Markdown
78 lines
3.7 KiB
Markdown
# claude-bridge
|
|
|
|
A **subscription-safe bridge** that lets a primary **Claude Code (Opus 4.8, on Pro/Max)**
|
|
session drive a **secondary Claude agent running a different model** via its own
|
|
`ANTHROPIC_BASE_URL` — without ever putting a proxy on the primary session.
|
|
|
|
Sibling of [`crush-bridge`](https://git.ltms.dev/systems/vms) (which drives a headless
|
|
**Crush** worker on GX10 DeepSeek). `claude-bridge` keeps the worker a *real Claude Code
|
|
process*, so it inherits `CLAUDE.md`, hooks, skills, and MCP — just pointed at a
|
|
cheaper/local model.
|
|
|
|
## Leading approach — herdr-centric message server (`bridged`)
|
|
|
|
A small always-on message server, **`bridged`**, controls
|
|
[herdr](https://herdr.dev) (an agent multiplexer) over its Unix-socket API and exposes a
|
|
clean 2-way messaging API (HTTP/SSE + optional broker). herdr owns the PTYs, multiplexing,
|
|
persistence, and **agent-status events**; `bridged` owns policy (subscription boundary,
|
|
session lifecycle, status-gated delivery) and the client contract. The worker `claude`
|
|
launches with `ANTHROPIC_BASE_URL=https://ollama.ltms.dev` + a bearer token; the primary
|
|
Opus stays env-clean and talks to `bridged` over HTTP.
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
OPUS["Opus — primary<br/>(Claude Code, env CLEAN)"]
|
|
BD["bridged<br/>message server<br/>(not a claude process)"]
|
|
HERDR["herdr<br/>panes · agent-status"]
|
|
W["worker claude<br/>ANTHROPIC_BASE_URL set"]
|
|
M["ollama.ltms.dev<br/>(worker model)"]
|
|
|
|
OPUS -->|"blocking POST /message"| BD
|
|
BD -->|"Unix socket<br/>send_text · events.subscribe"| HERDR
|
|
HERDR -->|"drives PTY"| W
|
|
W -->|"inference"| M
|
|
|
|
classDef ext fill:#2b6cb0,stroke:#1a365d,color:#ffffff;
|
|
classDef core fill:#2f855a,stroke:#22543d,color:#ffffff;
|
|
class OPUS ext
|
|
class BD,HERDR core
|
|
```
|
|
|
|
- **Subscription boundary:** the *primary* never sets `ANTHROPIC_BASE_URL` (stays on
|
|
Pro/Max). Only the *secondary* process is off-subscription — and `bridged` itself is a
|
|
plain daemon (no Anthropic quota), so it may poll/subscribe freely.
|
|
- **How the primary consumes a reply:** a single **blocking request** (`bridged` holds the
|
|
HTTP call open until the worker's turn completes, then returns the reply as the body). No
|
|
cross-turn busy-poll, so no quota burn. SSE is an optional side-channel for humans/dashboards
|
|
watching status, not how the primary gets its answer. Long/detached work uses the async
|
|
broker path instead.
|
|
- **Worker → primary:** *single-host only*, herdr can also type into the primary pane (typing
|
|
keystrokes is subscription-safe). When the primary runs off-herdr (e.g. on a Mac,
|
|
split-host), that direction goes via the **broker + the primary's own `Stop`-hook** —
|
|
`bridged` cannot inject into a primary it doesn't host. See the wiki for the two topologies.
|
|
- **Different model per process** sidesteps Claude Code's lack of per-subagent provider
|
|
routing — the worker isn't a subagent, it's its own configured process.
|
|
- **AgentAPI** ([`coder/agentapi`](https://github.com/coder/agentapi)) is retained only as a
|
|
swappable *fallback injector* behind the same interface. See the wiki for the full
|
|
design, comparison, and rationale.
|
|
|
|
## Docs
|
|
|
|
Full design, setup, and operations live in the **[wiki](https://git.ltms.dev/lms/claude-bridge/wiki)**,
|
|
vendored here as a submodule under [`wiki/`](./wiki):
|
|
|
|
```bash
|
|
git clone --recurse-submodules ssh://git@git.ltms.dev:2224/lms/claude-bridge.git
|
|
# or, after a plain clone:
|
|
git submodule update --init
|
|
```
|
|
|
|
Edit docs in `wiki/`, then `cd wiki && git commit && git push` to publish them to the
|
|
Gitea wiki.
|
|
|
|
## Status
|
|
|
|
🟢 Design — herdr-centric **`bridged`** message server selected as the primary approach
|
|
(2026-07-11), superseding the AgentAPI plan (2026-07-08). AgentAPI retained as fallback
|
|
injector.
|