Skip to content

Agents

Plexus drives three coding agents — Claude Code, Codex, and OpenCode — through one registry and one injection contract. It's agent-agnostic by design: every agent goes through the same two plexus calls (register + spawn a terminal) and the same edc /inject contract. What differs is where registration is wired and how the injected turn is received. (See Concepts for the terms.)

Support matrix

Capability Claude Code Codex OpenCode
Register in Plexus ✅ hook ✅ plugin ✅ plugin
Live terminal (attach)
Launch via plexus ✅ decoupled
External turn injection ✅ channel ✅ app-server ✅ HTTP
Injected turn is visible ✅ native ✅ TUI mode
Native source=system marker framed¹ framed¹
Interrupt a running turn /abort

¹ framed — the trust boundary is reconstructed as text (SYSTEM EVENT (untrusted data)) since the agent has no native system marker.

How each is wired

Claude Code

  • Registration: hooks in plexus/hooks/session-start.sh runs plexus ttyd spawn + plexus register (agent=claude); session-end.sh deregisters; a keepalive heartbeats idle sessions.
  • Injection: the edc channel — an MCP stdio server declaring claude/channel. Events arrive as native notifications/claude/channel turns with meta.source="system".
  • Install: two supported paths (see Setup) — the combined Plexus plugin (plexus@jjuanrivvera-plexus, registration hooks + injection channel in one), or à la carte (the event-driven-claude@jjuanrivvera-edc plugin for the channel + the plexus hooks for registration). Either way the hooks live in ~/.claude/settings.json; the channel allowlist lives in the OS managed-settings file (not settings.json) — Setup has the exact snippets.

Codex

  • Registration: the .codex-plugin shipped in edc — its SessionStart hook registers interactive Codex sessions (agent=codex, inject_port=0) and spawns the web terminal. The always-on injectable session is the edc codex serve daemon, which self-registers with a real inject port.
  • Injection: edc codex serve drives a codex app-server thread over JSON-RPC; each event becomes a turn/start. Pinned to approval-never + read-only sandbox so an injected turn can't act on its own.
  • Trust: no native system marker → framed as text.

OpenCode

  • Registration: the .opencode-plugin shipped in edc (plexus.ts~/.config/opencode/plugins/). On session.created it runs plexus ttyd spawn + plexus register (agent=opencode), reading the inject port from $EDC_INJECT_PORT.
  • Injection: edc opencode serve. OpenCode is client-server, so plexus opencode launches a decoupled stack — an addressable opencode serve, a TUI-mode edc sidecar on a fixed inject port, and the opencode attach you interact with. Injected turns are typed into the attached session via /tui/* so they render (working around sst/opencode#8564).
  • Trust: no native system marker → framed as text.

Adding another agent

The pattern to support a new agent:

  1. Register it — a session-start hook/plugin that calls plexus ttyd spawn + plexus register --agent <name> (and a session-end that deregisters). plexus accepts any lowercase agent name.
  2. Receive injection — an edc <name> serve adapter that runs the /inject listener and translates each event into that agent's "start a turn" primitive, reconstructing the trust boundary if the agent has no native system marker.

plexus needs no change to add an agent — only a hook and an adapter.