Contracts And Supported Integration Interfaces
June 7, 2026 ยท View on GitHub
This document describes the integration surface that exists in the current Rust runtime. The supported extension path today is HTTP: external tools can push agent state with /api/agent-event and session metadata with the metadata endpoints.
TypeScript plugin loading, PluginAPI, and package-based mux/agent plugins are not supported by the Rust server right now. The plugins config field is still parsed for compatibility, but it is not executed.
For end-user setup, start with README.md.
Built-In Watchers
The Rust server scans these agent data sources directly:
Amp
- Reads
~/.local/share/amp/threads/T-*.json. - Reads
~/.local/share/amp/session.jsonto clear unseen state when the active terminal thread is seen. - Resolves project directories from
env.initial.trees[0].uri.
Claude Code
- Reads JSONL transcripts in
~/.claude/projects/<encoded-path>/*.jsonl. - Decodes project directories from folder names such as
-Users-me-project. - Treats recent tool-use silence as
waitingand long silence asstale.
Codex
- Reads transcript JSONL files in
~/.codex/sessions/**/*.jsonlor$CODEX_HOME/sessions/**/*.jsonl. - Reads
$CODEX_HOME/session_index.jsonlfor recent thread titles when available. - Resolves sessions from transcript
turn_context.cwd.
OpenCode
- Polls
~/.local/share/opencode/opencode.dbor$OPENCODE_DB_PATH. - Resolves sessions from the OpenCode session row's
directoryfield.
Pi and Droid
- The Rust server includes scanner/parser support for Pi and Droid runtime/session state.
- Pi integrations can also use the Pi runtime API exposed by the server.
Agent Event HTTP API
External agents should POST JSON to:
POST /api/agent-event
Example:
curl -sS -X POST "http://127.0.0.1:7391/api/agent-event" \
-H 'content-type: application/json' \
-d '{
"agent": "my-agent",
"status": "running",
"tmuxSession": "work",
"threadId": "task-123",
"threadName": "Implement search",
"lastUserPrompt": "Add search to the sidebar",
"paneId": "%7"
}'
Session Resolution
The server resolves the target session from either:
| Input field | Meaning |
|---|---|
tmuxSession | Exact tmux session name |
projectDir | Project/worktree directory; exact session-dir match wins, then parent/child prefix matching |
If neither field can be resolved to a known session, the request is rejected.
Agent Model
AgentStatus
type AgentStatus =
| "idle"
| "running"
| "tool-running"
| "done"
| "error"
| "waiting"
| "interrupted"
| "stale";
Terminal states are done, error, and interrupted. The tracker uses those states to decide unseen behavior. tool-running is a running subtype used when the agent is actively using tools. stale means the last known running/waiting state has aged past the runtime threshold.
AgentEvent
interface AgentEvent {
agent: string;
session: string;
status: AgentStatus;
ts: number;
threadId?: string;
threadName?: string;
lastUserPrompt?: string;
unseen?: boolean;
paneId?: string;
liveness?: "alive" | "exited" | "unknown";
}
External /api/agent-event callers send the same shape except they use tmuxSession or projectDir for session resolution. The serialized server state always contains the resolved session field.
| Field | Type | Required for HTTP | Notes |
|---|---|---|---|
agent | string | yes | Stable agent identifier such as amp, claude-code, codex, opencode, pi, droid, or your integration name |
status | AgentStatus | yes | Current agent state |
tmuxSession | string | one of tmuxSession / projectDir | Exact tmux session name |
projectDir | string | one of tmuxSession / projectDir | Project directory used for session resolution |
ts | number | no | Millisecond timestamp; server time is used when omitted |
threadId | string | no | Stable instance key for multiple threads in one session |
threadName | string | no | Human-readable label shown in the detail panel |
lastUserPrompt | string | no | Latest user prompt/intent, shown in agent detail UI |
paneId | string | no | tmux pane id used for focus/kill routing when available |
Tracker Semantics
- Instances are keyed by
agent:threadIdwhenthreadIdexists, otherwise byagent. - A session can have multiple active agent instances.
- Unseen state is tracked per instance, then derived to the session level.
- Non-terminal updates clear unseen state for that instance.
- Terminal instances become seen when the user focuses the associated pane/session according to the server's tmux focus tracking.
- Stale/running cleanup is handled by the Rust tracker.
Metadata HTTP API
Scripts can also attach status, progress, and logs to sessions:
POST /set-status
POST /set-progress
POST /log
POST /clear-log
POST /notify
See docs/reference/programmatic-api.md for examples.
Rust Mux Contract
The supported mux implementation is tmux. The abstraction still lives in Rust so future providers can be added deliberately.
The trait is defined in packages/runtime-rs/src/mux.rs:
pub trait MuxProvider: Send + Sync {
fn name(&self) -> &str;
fn list_sessions(&self) -> Vec<MuxSessionInfo>;
fn switch_session(&self, name: &str, client_tty: Option<&str>);
fn get_current_session(&self) -> Option<String>;
fn get_session_dir(&self, name: &str) -> String;
fn get_pane_count(&self, name: &str) -> u32;
fn get_client_tty(&self) -> String;
fn create_session(&self, name: Option<&str>, dir: Option<&str>);
fn kill_session(&self, name: &str);
fn setup_hooks(&self, server_host: &str, server_port: u16);
fn cleanup_hooks(&self);
// optional capability methods omitted here; see source for full trait
}
Provider methods are synchronous because tmux operations are command-driven and the server treats the provider as a simple control surface.
Built-In Runtime Behaviors To Know About
- The server computes
ServerStatefrom tmux sessions, git/cache state, metadata, ports, and tracked agent events. - Session ordering is persisted separately from tmux ordering.
- tmux sidebars can be hidden into a stash session instead of being killed.
- tmux is the only supported built-in mux today.
- The sidebar and helper scripts resolve the server port from the tmux socket via
OPENSESSIONS_SERVER_KEY, defaulting to derived per-socket ports. - TPM installs use prebuilt binaries in
bin/; local builds usetarget/releaseortarget/debugas fallback paths.
Where To Start
- Integrate an agent: POST
/api/agent-eventwith stableagent,threadId, andprojectDirortmuxSession. - Push build/deploy metadata: use docs/reference/programmatic-api.md.
- Understand runtime behavior: read docs/explanation/architecture.md.