Architecture¶
The problem Plexus solves: you run coding-agent sessions on several machines and have no single place
to see them, reach their terminals, or feed them events. Plexus is two layers over one private network
that fix exactly that — plexus (observe / control / launch) and edc (inject). An agent
session (one running Claude Code, Codex, or OpenCode) sits in the middle: registered in plexus,
reachable by edc. (Plexus capitalized is the suite; plexus lowercase is one of its two binaries.)
Topology¶
flowchart TB
subgraph net["private network — a VPN, a LAN, or one machine"]
subgraph m1["a dev machine"]
A1["agent session"]
end
subgraph m2["another machine"]
A2["agent session"]
end
subgraph host["an always-on host"]
SRV["plexus serve<br/>SQLite registry + /ui cockpit"]
end
end
A1 -->|register · heartbeat| SRV
A2 -->|register · heartbeat| SRV
SRV -->|reverse-proxy attach| A1
SRV -->|reverse-proxy attach| A2
You["you — any device"] --> SRV
- The registry runs on one always-on host. Every machine's agents register into it.
- The cockpit (
/ui) and each session's web terminal are reachable from any device on the network. - edc runs alongside each injectable session, exposing a local
/injectendpoint.
None of it is fixed to a particular VPN, host type, or OS — see Setup → Requirements.
On a single machine the whole thing runs on 127.0.0.1.
How the two tools compose¶
| plexus | edc | |
|---|---|---|
| Role | see, control, launch | feed events in as turns |
| Direction | you → session (observe/steer) | event → session (stimulus) |
| Surface | registry API, /ui cockpit, plexus launcher |
/inject HTTP + per-agent adapters |
| Knows about the agent? | only its kind (a chip + a filter) | yes — one adapter per agent |
They meet at the session: edc injects a turn; plexus lets you watch and steer that same session.
An event's journey¶
sequenceDiagram
participant X as external event
participant E as edc /inject
participant A as agent session
participant P as plexus cockpit
X->>E: POST {source, event, text} + Bearer
E->>A: deliver as a turn (untrusted data)
A->>A: investigate / draft (no outward side effects)
P-->>A: you attach, watch, type, or interrupt
The registry row¶
Everything Plexus knows about a session is one row:
| Field | Meaning |
|---|---|
session_id |
stable id (the agent's own session id) |
host |
machine label (laptop / server / …) |
agent |
claude | codex | opencode |
repo · branch · repo_path |
what it's working on |
state |
busy | idle | blocked |
inject_port |
edc /inject port (0 = visible but not injectable) |
attach_addr |
the session's web-terminal address, or empty |
started_at · last_seen |
timing; stale rows are pruned past the TTL |
State is deliberately small and self-cleaning: clients heartbeat, and the server prunes anything that goes quiet past the TTL — a dead session drops off on its own.