How the desktop app, IDE extension, and daemon fit together — data flow, components, and connection topology
Architecture
The Codmir daemon is the shared backend for all local Codmir clients. Both the desktop app (Tauri) and IDE extension (VS Code) connect to it over WebSocket and share the same agent sessions, process queue, and overseer state.
System topology
┌─────────────────────────────────────────────────────────────────────┐
│ User's Machine │
│ │
│ ┌──────────────┐ WebSocket ┌─────────────────────────────┐ │
│ │ Desktop App │──────────────→│ │ │
│ │ (Tauri) │ │ Codmir Daemon │ │
│ └──────────────┘ │ (Node.js, port 7700) │ │
│ │ │ │
│ ┌──────────────┐ WebSocket │ ┌───────────────────────┐ │ │
│ │ IDE Extension│──────────────→│ │ KernelSocketServer │ │ │
│ │ (VS Code) │ │ │ ├─ AgentManager │ │ │
│ └──────────────┘ │ │ ├─ ProcessManager │ │ │
│ │ │ ├─ OverseerLoop │ │ │
│ │ │ └─ MeshManager │ │ │
│ │ └───────────────────────┘ │ │
│ │ │ │
│ │ ┌───────────────────────┐ │ │
│ │ │ PlatformPresence │ │ │
│ │ │ (heartbeat + tasks) │ │ │
│ │ └──────────┬────────────┘ │ │
│ └─────────────┼───────────────┘ │
│ │ │
└────────────────────────────────────────────────┼────────────────────┘
│ HTTPS
┌──────▼──────┐
│ codmir.app │
│ (cloud API) │
└─────────────┘Core components
KernelSocketServer
The WebSocket server binds to 0.0.0.0:7700 (configurable via KERNEL_PORT env var). It accepts multiple simultaneous client connections — both the desktop app and IDE extension connect to the same server.
On each new connection, the server sends a snapshot of current state:
kernel:status— daemon info (PID, port, version, stats)overseer:state— overseer loop state (enabled, tick count, sleep interval)mesh:status— mesh networking state (peers, capabilities)
Incoming messages are routed by prefix:
agent:*→ AgentManager (agent sessions)overseer:*→ OverseerLoop (editor awareness)mesh:*→ MeshManager (peer networking)- Everything else → ProcessManager (generic task queue)
All events are broadcast to every connected client, so the desktop and IDE always stay in sync.
AgentManager
Manages all active agent sessions. Each session is an AgentSessionRunner — an autonomous agentic loop that:
- Sends messages to Claude via the Anthropic API
- Processes tool use responses
- Checks tool danger levels and pauses for approval when needed
- Executes approved tools locally
- Loops until the task is complete or limits are hit
See Agent Protocol for the full event flow.
ProcessManager
A priority-based task queue for simpler (non-agentic) processes. Tasks are queued with a priority level (critical > high > normal > low) and executed up to maxConcurrent (default 5) at a time.
Used for background work that doesn't need the full agent loop — like running a build, linting, or a one-shot LLM call.
OverseerLoop
A background observer that watches editor signals and generates proactive suggestions. It runs a closed loop:
sleeping → observing → reasoning → acting → sleepingThe overseer receives signals like cursor moves, file edits, saves, and git commits. It gates on several conditions (minimum signal count, idle time, edit cooldown) before calling the LLM to reason about what the user might need.
Actions it can take: code completions, diagnostic suggestions, notifications, and status updates.
MeshManager
Peer-to-peer discovery of other Codmir daemons on the local network via mDNS. When mesh is enabled, tasks can be routed to peer machines based on capabilities (GPU, available models, CPU cores).
The MeshManager wraps the ProcessManager and adds routing logic — checking if a task should run locally or be delegated to a peer with better resources.
PlatformPresence
Maintains the daemon's connection to the Codmir cloud platform:
- Registration:
POST /api/daemon/register— announces the daemon's existence, hostname, platform, and capabilities - Heartbeat:
POST /api/daemon/heartbeatevery 30 seconds — the response may include tasks dispatched from the web UI - Task reporting:
POST /api/daemon/task/{id}/report— sends progress updates and completion status back to the cloud
This enables the web app at codmir.app to dispatch work to your local daemon — for example, running an agent task from the web interface that executes on your machine.
Connection flow
Desktop app (Tauri)
- App launches → Tauri's Rust backend calls
ensure_daemon ensure_daemonchecks~/.codmir/kernel.pid— if the daemon is already running, returns its port- If not running, spawns
node daemon-entry.js start --foregroundas a detached process - Polls
~/.codmir/kernel.piduntil the daemon writes it (up to 8 seconds) - React app calls
useKernelStore.ensureAndConnect()→ createsKernelClient(port)→ connects WebSocket - Background monitor polls daemon status every 5 seconds, updates tray icon
IDE extension (VS Code)
- Extension activates →
KernelClientService.connect() - Reads
~/.codmir/kernel.portand validates the PID in~/.codmir/kernel.pidis alive - If daemon not running, forks
daemon-entry.jswithdetached: true - Connects via
WebSocket('ws://127.0.0.1:{port}') - Agent events are forwarded to the webview via
MessageBridge.send()(postMessage IPC) - Webview user actions (send message, approve tool) go back through the bridge to
KernelClientService
Shared state
Both clients connect to the same daemon WebSocket. All agent events are broadcast to every connected client. This means:
- Start an agent session from the IDE → the desktop app sees it immediately
- Approve a tool call from the desktop → the IDE extension gets the result
- Agent sessions persist even if both UIs are closed — the daemon keeps running
File system layout
The daemon uses ~/.codmir/ as its home directory:
~/.codmir/
├── kernel.pid # PID of the running daemon process
├── kernel.port # Port the daemon is listening on
├── machine-id # Unique machine identifier (UUID)
├── config.json # CLI token, base URL, proxy settings
├── logs/
│ └── kernel.log # Daemon stdout/stderr log
└── worktrees/ # Git worktrees for isolated agent sessions
└── {session-id}/ # One worktree per agent session (optional)Package structure
The daemon code lives in packages/kernel/:
packages/kernel/
├── src/
│ ├── daemon-entry.ts # CLI entry point
│ ├── daemon.ts # Startup orchestration
│ ├── socket-server.ts # WebSocket server + message routing
│ ├── process-manager.ts # Priority task queue
│ ├── task-queue.ts # In-memory queue with priority buckets
│ ├── client.ts # KernelClient (used by desktop + IDE)
│ ├── lifecycle.ts # ensureDaemon(), stopDaemon()
│ ├── platform-presence.ts # Cloud heartbeat + task pickup
│ ├── agent/
│ │ ├── agent-manager.ts # Session registry
│ │ ├── agent-session.ts # Agentic loop (core)
│ │ ├── tool-executor.ts # Tool implementations
│ │ └── worktree-manager.ts # Git worktree isolation
│ ├── overseer/
│ │ └── loop.ts # Background editor observer
│ └── mesh/
│ └── mesh-manager.ts # P2P task routing
└── dist/ # Compiled outputShared types are in packages/types/src/kernel/:
packages/types/src/kernel/
├── index.ts # KernelProcess, KernelCommand, KernelEvent
├── agent.ts # AgentSession, AgentToolCall, AgentCommand, AgentEvent
├── overseer.ts # OverseerLoop types, EditorSignal, OverseerAction
├── mesh.ts # MeshNode, MeshPeer, MeshCommand, MeshEvent
└── workstation.ts # Cloud workstation protocol (separate from daemon)