IPC Protocol
Wire format, message types, and communication flows between client and daemon.
Wire Format
All IPC messages use a simple length-prefixed binary format:
┌──────────────┬──────────────────────────┐
│ 4 bytes (BE) │ bincode payload │
│ length │ (serde-serialized) │
└──────────────┴──────────────────────────┘
- Length — 4-byte big-endian unsigned integer indicating the payload size in bytes
- Payload — bincode-serialized Rust struct
This keeps parsing simple and avoids delimiter-based framing issues with binary data.
Message Types
| Message | Direction | Purpose |
|---|---|---|
EnvSnapshot | Client to Daemon | Sends current environment variables, working directory, terminal size |
Heartbeat | Bidirectional | Keep-alive ping/pong |
AgentRequest | Client to Daemon | User query with session context |
AgentStreamChunk | Daemon to Client | Streaming token from LLM response |
AgentComplete | Daemon to Client | Agent finished processing |
ConfirmationRequest | Daemon to Client | Ask user to approve a risky command |
ConfirmationResponse | Client to Daemon | User’s approval or denial |
CommandResult | Daemon to Client | Result of a tool execution |
AcquireShellLease | Daemon to Client | Request exclusive access to client’s bash co-process |
ShellLeaseAcquired | Client to Daemon | Confirm shell lease granted |
ExecuteLeasedCommand | Daemon to Client | Run a command through the leased co-process |
CommandCompleted | Client to Daemon | Relay result with output, exit code, and updated cwd |
ReleaseShellLease | Daemon to Client | Release the shell lease |
CancelLeasedCommand | Daemon to Client | Cancel a running leased command |
CompactRequest | Client to Daemon | Request conversation compaction |
CompactionStarted | Daemon to Client | Compaction in progress |
CompactionComplete | Daemon to Client | Compaction finished with summary |
Agent Task Flow
A typical AI query follows this sequence:
sequenceDiagram
participant C as Client
participant D as Daemon
C->>D: AgentRequest
Note right of D: LLM call
D-->>C: AgentStreamChunk (reasoning text)
D-->>C: AgentStreamChunk
Note right of D: Tool call (e.g., grep)
D-->>C: AgentStreamChunk (tool result summary)
Note right of D: LLM call (with tool result)
D-->>C: AgentStreamChunk (final response)
D->>C: AgentComplete
Safety Confirmation Flow
When the agent wants to run a command classified as risky:
sequenceDiagram
participant C as Client
participant D as Daemon
Note right of D: Agent wants to run\n"rm -rf target/"
D->>C: ConfirmationRequest (command, risk level, explanation)
Note left of C: User sees prompt in TUI
C->>D: ConfirmationResponse (allow / deny / always-allow)
Note right of D: Executes or skips based on response
D-->>C: AgentStreamChunk (continues)
Shell Lease Flow
When the orchestrator agent runs bash commands, it first acquires a lease on the client’s co-process. Leases are queued if another agent holds the shell, and time out if not released promptly:
sequenceDiagram
participant A as Agent (Daemon)
participant D as Daemon IPC
participant C as Client IPC
participant S as Bash Co-Process
A->>D: bash tool call
D->>C: AcquireShellLease
C->>D: ShellLeaseAcquired
D->>C: ExecuteLeasedCommand (command, cwd)
C->>S: Write command to co-process
S-->>C: Output + exit code
C->>D: CommandCompleted (output, exit_code, new_cwd)
D->>C: ReleaseShellLease
D->>A: Tool result
Independent agents (engineer, reviewer) bypass this lease flow and execute commands in their own daemon-side DaemonShell processes.
Serialization Warning
Do not use #[serde(skip_serializing_if)] on fields in IPC message types. Bincode relies on positional encoding, not field names, and skipping fields corrupts the binary layout. This causes deserialization failures on the receiving end. Always serialize every field, even if its value is None or a default.
Versioning
The IPC protocol is versioned implicitly through the shared codiv-common crate. Since both client and daemon are built from the same workspace, they always use matching message definitions. The EnvSnapshot message includes a protocol version field for future compatibility when independent versioning is needed.