Architecture¶
Repowire is a local-first routing daemon plus thin transport adapters for each agent runtime.
Agent runtime
├─ hooks + MCP (Claude Code, Codex, Gemini)
├─ plugin + WebSocket (OpenCode)
├─ extension (Pi)
└─ channel / ACP transport (Claude Code experimental)
↓
HTTP/WebSocket daemon on 127.0.0.1:8377
↓
Dashboard, Telegram, Slack, orchestrator peers, relay, and other peers
The daemon is the single routing hub. It does not care whether a peer arrived through hooks, an OpenCode plugin, the Pi extension path, a bot, relay traffic, or experimental channel/ACP delivery. Every peer is represented in the registry and routes messages through the same core message layer.
Core modules¶
| Area | Files | Responsibility |
|---|---|---|
| Agent backends | repowire/agent_types.py, repowire/agent_backends.py |
Serialized backend identity plus setup, spawn, resume, MCP config, and post-spawn behavior dispatch |
| Daemon app | repowire/daemon/app.py, repowire/daemon/deps.py |
FastAPI app factory, dependency wiring, dashboard/static serving |
| Peer state | repowire/daemon/peer_registry.py |
Registration, liveness, circles, roles, lazy repair |
| Message routing | repowire/daemon/peer_delivery.py, repowire/daemon/transport_router.py, repowire/daemon/message_router.py, repowire/daemon/websocket_transport.py |
Delivery orchestration, ACP-before-WebSocket transport selection, and wire delivery over connected peers |
| Ask lifecycle | repowire/daemon/ask_tracker.py, repowire/daemon/routes/asks.py |
Open ask state, pending reminders, close/ack handling |
| Session controls | repowire/daemon/session_controls.py, repowire/daemon/routes/sessions.py |
Session-binding resolution and session-targeted control capability routes |
| Session acquisition | repowire/daemon/session_control.py, repowire/daemon/state/operations.py |
Durable operation records and live-executor acquisition for session/job work |
| Schedules | repowire/daemon/scheduler.py, repowire/daemon/schedule_store.py, repowire/daemon/routes/schedules.py |
One-shot and recurring cron deliveries |
| Jobs | repowire/daemon/job_runner.py, repowire/daemon/state/work.py, repowire/daemon/state/calendar.py, repowire/daemon/routes/work.py |
Durable tracked work, recurring calendar templates, and spawned job dispatch |
| Hooks | repowire/hooks/ |
Runtime event adapters, tmux injection, transcript/chat extraction |
| MCP server | repowire/mcp/server.py |
Agent-facing tools over stdio |
| Control surfaces | web/, repowire/telegram/bot.py, repowire/slack/bot.py |
Dashboard and human/service peers |
| Relay | repowire/relay/server.py, repowire/daemon/relay_client.py |
Hosted remote dashboard and cross-machine tunnel |
Transports¶
Hooks + MCP¶
Claude Code, Codex, and Gemini use lifecycle hooks for registration/status/chat extraction and MCP tools for outbound commands. The hook adapter normalizes each runtime's event names and response fields.
Default message delivery still uses tmux injection plus Stop-hook reminders for unacked asks. The MCP server lazily registers on tool calls so runtimes that initialize late, especially Codex, still get a peer identity before routing.
OpenCode plugin and Pi extension¶
OpenCode does not expose the same hook shape, so Repowire installs a TypeScript plugin. The plugin holds a WebSocket connection to the daemon and bridges OpenCode session events into the same peer/message model. Pi uses Repowire's extension path when setup detects the pi CLI or config.
Channel / ACP transport¶
repowire setup --experimental-channels installs Claude Code's experimental channel/ACP transport. Messages arrive as <channel source="repowire"> tags, while legacy query replies route through a channel reply tool. The normal repowire mcp server remains installed for stable tools such as ask, ack, notify_peer, schedules, and peer listing. This requires Claude Code support, claude.ai login, and bun. Treat this path as experimental; hooks + MCP remain the default.
Relay¶
The daemon connects outbound to the hosted relay over WSS. The relay tunnels dashboard HTTP/SSE calls and bridges WebSocket traffic without requiring inbound access to the user's machine.
Lazy repair¶
Repowire avoids polling loops. Liveness repair, persistence flushes, and ghost cleanup are piggy-backed on user-visible requests, bounded by cooldowns. The design rule is: repair when needed, not on timers.
When lazy repair detects a self-inconsistent peer (e.g. online but no live WebSocket, a missing pane, or a dead agent pid) it emits a peer_contradiction event once per transition, so silent failures surface in the dashboard stream. repowire peer doctor <peer> is the explicit, operator-triggered counterpart: it runs the same reconciliation, then reports identity, inbound reachability, pending asks, and contradictions on demand. repowire peer rehook <peer> is the non-destructive recovery (re-establish the inbound ws-hook without killing the pane). A delivery trace ledger (repowire trace <id>) records per-message ask/notify stages for post-hoc "where did it go" inspection, persisted in a dedicated SQLite table rather than the bounded dashboard event buffer.
v0.14 session-native direction¶
The current stable surface is peer-oriented, but the v0.14 architecture train is moving toward a session-first mesh:
- Sessions become the durable unit of work.
- Peers remain runtime executors.
- Ask/notify delivery now goes through a delivery service plus transport router; WebSocket hooks, experimental ACP, relay, and future transports continue moving toward transport-neutral routing.
- The dashboard currently shows a selected peer/session timeline, merging Claude transcript history where available with realtime events.
- The first session-targeted control routes resolve
repowire_session_idbindings to an active executor or explicit resume capability status. - Broader composer actions, scheduling, approval handling, and backend/model controls move toward the same shared session command surface.
This is a roadmap. Current routes and tools still expose peers, circles, asks, notifications, and schedules. The ask/notify delivery-service and transport-router extraction has landed, but ACP remains experimental and not every route/control path is transport-neutral yet.
Knowledge graph¶
graphify-out/GRAPH_REPORT.md summarizes the codebase graph. The current report identifies the main hubs as AgentType, Config, PeerRegistry, MessageRouter, and WebSocketTransport, with communities around daemon routing, CLI/setup, channel installer, Telegram, attachments, hook normalization, relay auth, and peer lifecycle.
Keep generated graph JSON and cache files out of prose docs. Link or summarize the report when useful; do not paste large graph artifacts into README or hand-written docs.