Skip to content

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 /inject endpoint.

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.