Client & Daemon
Detailed look at the TUI client, async daemon, and how they communicate.
Client (codiv)
The client is a terminal application built with ratatui. It handles:
Terminal Rendering
- Full TUI with scrollable output panes
- Markdown rendering via streamdown-rs with syntax highlighting
- Terminal colorscheme detection for proper theming
Bash Co-Process
A persistent bash child process runs alongside the TUI. When you type a known command, it is sent directly to this co-process for instant execution — no daemon round-trip needed.
The co-process also handles AI-relayed commands via the command relay protocol. When the orchestrator agent runs a bash command, the daemon sends an ExecuteCommand message to the client, which executes it through this same co-process and returns a CommandExecutionResult with the output, exit code, and updated working directory. This means the AI agent shares shell state (environment variables, working directory, etc.) with the user.
Command Index
At startup, the client builds a hash map of all known commands:
- Executables from every directory on
PATH - Bash and zsh builtins
This allows O(1) lookup to classify input as a known command or an AI query.
Tab Completion
Three tiers of tab completion:
- Programmable — bash-completion scripts for commands that support them
- Command — completes command names from the index
- File — filesystem path completion
Daemon (codivd)
The daemon is a Tokio async application that handles all AI and tool operations:
Agent Sessions
Each AI query creates a session with context from the terminal timeline. The agent reasons, calls tools, and streams results back to the client.
LLM Streaming
Responses stream token-by-token from the LLM provider via the aisdk library. Supports Anthropic, OpenAI, and Google providers with a unified interface.
Worker Bash Sessions
The orchestrator agent does not use a separate worker session — its bash commands route through the client’s co-process via the command relay (see above), so shell state is shared with the user. Independent agents (engineer, reviewer, etc. in multi-agent mode) get their own daemon-side DaemonShell instances — pipe-based bash -i processes with fresh state, inheriting only the initial working directory from the parent.
IPC Communication
The client and daemon communicate over a Unix domain socket using:
- Serialization — serde + bincode (compact binary format)
- Framing — 4-byte big-endian length prefix followed by the payload
- Lifecycle — the client connects at startup, maintains a heartbeat, and reconnects if the connection drops
Connection Lifecycle
sequenceDiagram
participant C as Client
participant D as Daemon
C->>D: Connect
D->>C: Accept
C->>D: EnvSnapshot
loop Periodic
C->>D: Heartbeat
D->>C: Heartbeat
end
C->>D: AgentRequest
D-->>C: StreamChunk (repeated)
Note right of D: Agent runs bash command
D->>C: ExecuteCommand
Note left of C: Runs in co-process
C->>D: CommandExecutionResult
D-->>C: StreamChunk (continued)
D->>C: AgentComplete
The heartbeat ensures both sides detect connection loss promptly. If the daemon restarts, the client reconnects and re-sends the environment snapshot.