diff --git a/1-Architecture.md b/1-Architecture.md
index e88991c..97eb1fc 100644
--- a/1-Architecture.md
+++ b/1-Architecture.md
@@ -33,11 +33,15 @@ flowchart TB
end
subgraph work["SECONDARY worker host — off-subscription"]
- BD["bridged
message server
(not a claude process)"]
- HERDR["herdr server
panes · agent-status"]
- WCC["claude (worker)
ANTHROPIC_BASE_URL set"]
+ subgraph BD["bridged — standalone daemon (not a claude process)"]
+ SRV["SERVER face
MCP server · REST/SSE · policy"]
+ CLI["CLIENT face
herdr socket client"]
+ SRV --> CLI
+ end
+ HERDR["herdr
panes · agent-status"]
+ WCC["worker pane · claude
ANTHROPIC_BASE_URL set · MCP client"]
HOOK["Stop-hook
long-poll client"]
- BD -->|"Unix socket
send_text · events.subscribe"| HERDR
+ CLI -->|"Unix socket
send_text · events.subscribe"| HERDR
HERDR -->|"drives PTY"| WCC
WCC --- HOOK
end
@@ -45,23 +49,25 @@ flowchart TB
BROKER["Broker
Redis Streams / NATS JetStream
inbox-primary · inbox-worker"]
MODEL["ollama.ltms.dev /v1
or GX10 vLLM
(worker model)"]
- OPUS -->|"MCP bridge_send → reply in tool result"| BD
- WCC -.->|"MCP bridge_reply / bridge_ask"| BD
- BD -.->|"SSE /events (status, for observers)"| OPUS
+ OPUS -->|"MCP bridge_send → reply in tool result"| SRV
+ WCC -.->|"MCP bridge_reply / bridge_ask"| SRV
+ SRV -.->|"SSE status (observers)"| OPUS
OPUS -.->|"write / long-poll (async)"| BROKER
HOOK -.->|"long-poll / write (async)"| BROKER
- BD -.->|"bridge inbox ↔ session"| BROKER
+ SRV -.->|"bridge inbox ↔ session"| BROKER
WCC -->|"inference"| MODEL
classDef sub fill:#2b6cb0,stroke:#1a365d,color:#ffffff;
classDef pick fill:#2f855a,stroke:#22543d,color:#ffffff;
classDef warn fill:#b7791f,stroke:#7b341e,color:#ffffff;
class OPUS sub
- class BD,HERDR,WCC pick
+ class SRV,CLI,HERDR,WCC pick
class BROKER warn
```
-*Figure: solid arrows = the blocking request/response `bridged`/herdr channel; dotted = the optional async
+*Figure: `bridged` is one **standalone daemon** split into a **SERVER face** (the MCP server
+the Claude sessions mount, plus REST/SSE + policy) and a **CLIENT face** (the herdr socket
+client). Solid arrows = the blocking MCP request/response channel; dotted = the optional async
broker. The primary's env stays clean; only the worker sets `ANTHROPIC_BASE_URL`, and
`bridged` — a plain daemon — enforces that boundary in code.*
diff --git a/2-Message-Server.md b/2-Message-Server.md
index a4d3cd2..3ee79db 100644
--- a/2-Message-Server.md
+++ b/2-Message-Server.md
@@ -139,58 +139,66 @@ bridge on either side is subscription-safe by construction (see
## Architecture
-`bridged` is the hub. Its **south side** speaks herdr's Unix-socket JSON-RPC; its **north
-side** speaks HTTP/SSE to synchronous clients and (optionally) a broker for async duplex.
-herdr, `bridged`, the worker panes, and the model endpoint are colocated on the
-off-subscription **worker host**; the primary reaches in over HTTP and/or the broker.
+`bridged` is a **standalone daemon** — one component, two faces:
+
+- a **SERVER (north face)** — an **MCP server** the Claude Code sessions mount, plus REST/SSE
+ for non-Claude clients, sitting over the session tracker, subscription guard, and reply
+ rendezvous (the policy brain); and
+- a **CLIENT (south face)** — a herdr socket client that injects turns (status-gated) and
+ subscribes to agent-status.
+
+The Claude sessions themselves live **as panes inside herdr**. Each pane reaches *up* to
+`bridged`'s MCP server (to send/reply); `bridged`'s herdr client reaches *down* through
+herdr's socket to drive those same panes and read their status. herdr, `bridged`, the panes,
+and the model are colocated on one host (same-host scenario); a broker is optional for async
+duplex.
```mermaid
flowchart TB
- subgraph clients["NORTH — clients"]
- OPUS["Primary Opus
(Claude Code, env CLEAN)
MCP client"]
- BUS["External event bus
(webhook / NATS / Redis)"]
- HUMAN["Human / CLI / chat UI"]
+ subgraph herd["herdr — agent multiplexer (Claude sessions run here, same host)"]
+ PP["primary pane · Opus
env CLEAN · MCP client"]
+ WP["worker pane(s) · claude
ANTHROPIC_BASE_URL set · MCP client"]
end
- subgraph server["bridged — message server (NOT a claude process)"]
- API["North API
MCP server · REST · SSE"]
- SESS["Session manager
spawn · health · recycle"]
- INJ["Injector
queue + status gate"]
- COLL["Reply rendezvous
bridge_reply | event | pane.read"]
- GUARD["Subscription guard
enforces the boundary"]
- HCL["herdr socket client
NDJSON, id-correlated + events"]
- API --> SESS --> INJ --> HCL
- HCL --> COLL --> API
- SESS --> GUARD
- HCL -->|"events.subscribe"| INJ
+ subgraph bridged["bridged — standalone daemon (NOT a claude process)"]
+ subgraph srv["SERVER — north face"]
+ MCP["MCP server
bridge_send · reply · ask · status"]
+ REST["REST / SSE
(non-Claude clients)"]
+ POL["policy brain
session tracker · subscription guard
· reply rendezvous"]
+ end
+ subgraph cli["CLIENT — south face"]
+ INJ["injector
status-gated"]
+ HCL["herdr socket client
send_text · events · pane.read"]
+ end
+ MCP --> POL
+ REST --> POL
+ POL --> INJ --> HCL
+ HCL -->|"events · replies"| POL
end
- BROKER["Broker (optional)
Redis Streams / NATS JetStream
inbox-primary · inbox-worker"]
- HERDR["herdr server
workspaces · panes · agent-status"]
- WCC["worker claude pane(s)
ANTHROPIC_BASE_URL set
MCP client"]
- MODEL["ollama.ltms.dev /v1
or GX10 vLLM"]
+ MODEL["ollama.ltms.dev / GX10 vLLM
(worker model)"]
+ BROKER["Broker (optional)
Redis / NATS — async duplex"]
- OPUS -->|"MCP: bridge_send / poll / status"| API
- BUS -.->|"async"| BROKER
- HUMAN --> API
- BROKER -.-> API
- HCL -->|"Unix socket"| HERDR
- HERDR -->|"drives PTY"| WCC
- WCC -->|"inference"| MODEL
- WCC -.->|"MCP: bridge_reply / bridge_ask"| API
+ PP -->|"MCP tools"| MCP
+ WP -->|"MCP tools"| MCP
+ HCL -->|"Unix socket · drive + status"| herd
+ WP -->|"inference"| MODEL
+ POL -.->|"async"| BROKER
classDef core fill:#2f855a,stroke:#22543d,color:#ffffff;
classDef ext fill:#2b6cb0,stroke:#1a365d,color:#ffffff;
classDef warn fill:#b7791f,stroke:#7b341e,color:#ffffff;
- class API,SESS,INJ,COLL,GUARD,HCL core
- class OPUS ext
- class BROKER,HERDR,BUS warn
+ class MCP,REST,POL,INJ,HCL core
+ class PP ext
+ class MODEL,BROKER warn
```
-*Figure: `bridged` translates a clean north-side message API into herdr socket calls, gating
-every injection on live agent-status events. Only the worker panes carry
-`ANTHROPIC_BASE_URL`; `bridged` itself is a plain daemon and may poll/subscribe freely
-because it consumes no Anthropic quota.*
+*Figure: `bridged` is one standalone daemon with a **SERVER** face (the MCP endpoint the
+Claude panes mount, over the policy brain) and a **CLIENT** face (the herdr socket client).
+The Claude sessions are herdr **panes**: they call *up* into the MCP server, while `bridged`'s
+client drives them *down* through herdr's socket and gates every injection on live
+agent-status. Only worker panes carry `ANTHROPIC_BASE_URL`; `bridged` holds no quota, so it
+subscribes freely. (Split-host moves the primary out of herdr — see [Deployment model](#deployment-model).)*
### Components
@@ -471,7 +479,7 @@ flowchart LR
end
subgraph host["Worker host (off-subscription, near model)"]
direction TB
- BD["bridged
:8080 HTTP/SSE"]
+ BD["bridged
:8080 MCP · REST/SSE"]
HS["herdr server"]
W2["worker claude pane(s)"]
BD -->|"Unix socket"| HS --> W2
diff --git a/6-Team.md b/6-Team.md
index 06e7ad1..3e20420 100644
--- a/6-Team.md
+++ b/6-Team.md
@@ -30,8 +30,12 @@ alike. Scale each kind horizontally by adding panes.
```mermaid
flowchart TB
- LEAD["lead — Opus
(Claude Code, env CLEAN)"]
- BD["bridged
message server + router"]
+ LEAD["lead — Opus
(Claude Code, env CLEAN)
MCP client"]
+ subgraph BD["bridged — standalone daemon"]
+ SRV["SERVER face
MCP · REST/SSE · role router"]
+ CLI["CLIENT face
herdr socket"]
+ SRV --> CLI
+ end
HERDR["herdr
panes · agent-status"]
WC1["w-claude-1
Sonnet · CLEAN"]
WC2["w-claude-2
Sonnet · CLEAN"]
@@ -40,9 +44,11 @@ flowchart TB
ANT["api.anthropic.com
(Pro/Max)"]
OLL["ollama.ltms.dev
(local model)"]
- LEAD -->|"MCP bridge_send (target role)"| BD
- BD -->|"Unix socket · send_text · events.subscribe"| HERDR
+ LEAD -->|"MCP bridge_send (target role)"| SRV
+ CLI -->|"Unix socket · send_text · events.subscribe"| HERDR
HERDR --> WC1 & WC2 & WL1 & WL2
+ WC1 -.->|"MCP bridge_reply"| SRV
+ WL1 -.->|"MCP bridge_reply"| SRV
WC1 --> ANT
WC2 --> ANT
WL1 --> OLL
@@ -52,7 +58,7 @@ flowchart TB
classDef core fill:#2f855a,stroke:#22543d,color:#ffffff;
classDef local fill:#6b46c1,stroke:#44337a,color:#ffffff;
class LEAD,WC1,WC2 ext
- class BD,HERDR core
+ class SRV,CLI,HERDR core
class WL1,WL2 local
```
diff --git a/Home.md b/Home.md
index e39f3b6..d3bf979 100644
--- a/Home.md
+++ b/Home.md
@@ -22,22 +22,26 @@ env-clean and calls `bridged`'s MCP tools.
```mermaid
flowchart LR
- OPUS["Opus — primary
(Claude Code, env CLEAN)"]
- BD["bridged
message server
(not a claude process)"]
+ OPUS["Opus — primary
(Claude Code, env CLEAN)
MCP client"]
+ subgraph BD["bridged — standalone daemon (not a claude process)"]
+ SRV["SERVER face
MCP · REST/SSE · policy"]
+ CLI["CLIENT face
herdr socket"]
+ SRV --> CLI
+ end
HERDR["herdr
panes · agent-status"]
- W["worker claude
ANTHROPIC_BASE_URL set"]
+ W["worker claude pane
ANTHROPIC_BASE_URL set
MCP client"]
M["ollama.ltms.dev
(worker model)"]
- OPUS -->|"MCP bridge_send (blocks)"| BD
- W -.->|"MCP bridge_reply"| BD
- BD -->|"Unix socket
send_text · events.subscribe"| HERDR
+ OPUS -->|"MCP bridge_send (blocks)"| SRV
+ W -.->|"MCP bridge_reply"| SRV
+ CLI -->|"Unix socket
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
+ class SRV,CLI,HERDR core
```
- **Subscription boundary:** the *primary* never sets `ANTHROPIC_BASE_URL` (stays on