Skip to Content

Daemon

The daemon is the long-running OS process started by cmdop agent start. Until it is up, the machine is not online — every other CMDOP feature attaches to it.

Why the daemon is the on-ramp

The CLI, Desktop, and SDK never talk to the relay directly. They open a local gRPC channel to the daemon over a per-user Unix socket (or Windows named pipe), and the daemon owns the single outbound TLS connection to the relay. If the daemon is not running, cmdop chat falls back to a one-shot mode and nothing else (machines tab, remote calls, share links) works.

See internal/services/daemon/CLAUDE.md for the authoritative description, and internal/services/localserver/ for the local socket server.

Startup sequence

cmdop agent start runs the following steps before the daemon is considered live (see internal/services/daemon/agent_connection.go and report 06 §2.2):

  1. Initialise the file logger (lumberjack).
  2. Mark a new daemon session in the log file.
  3. Write the PID file at ~/.cmdop/cmdop.pid.
  4. Bring up the status manager and write daemon.status.
  5. Install signal handlers (SIGINT / SIGTERM for graceful stop).
  6. Open the backlog store for offline tool-call queueing.
  7. Load the permissions store (rules + audit log).
  8. Start the OAuth token refresher.
  9. Schedule auto-update checks.
  10. Start the trigger scheduler (cron-style background jobs).
  11. Bring up the local gRPC server (Unix socket / named pipe).
  12. Optionally bring up the MCP server (--with-mcp).
  13. Enter the connection loop — dial the relay, register, heartbeat.

Only when step 13 completes a handshake does the daemon flip to ONLINE.

Status verdict — ONLINE / DEGRADED / STARTING

cmdop agent status reads daemon.status and the PID file, then returns one of three verdicts:

VerdictMeaning
ONLINEProcess alive, status file fresh (< 30 s), relay handshake done.
DEGRADEDProcess alive but status file stale (> 30 s) or relay disconnected.
STARTINGProcess alive, never reached relay handshake (boot or recovery).
// ~/.cmdop/daemon.status (excerpt) { "status": "ONLINE", "pid": 48211, "hostname": "laptop-a", "workspace_id": "ws_acme_prod", "relay_connected": true, "last_heartbeat": "2026-04-27T14:55:12Z" }

ONLINE means the daemon is connected to the relay. If cmdop agent status reports DEGRADED but the process is alive, the daemon failed to reach the relay — usually network, auth, or token expiry. Run cmdop agent logs -f to see the cause.

Heartbeat and the online flag

The daemon calls statusManager.Touch() on every heartbeat tick. The relay holds a server-side TTL of roughly 90 s — if heartbeats stop, the machine is marked offline on that timeline. On a clean cmdop agent stop, the daemon also issues MarkOfflineByHostname with a 3-second deadline so the UI flips immediately rather than waiting on the TTL.

PID file is per-user

~/.cmdop/cmdop.pid is per-euid, not host-wide. Two daemons can legitimately coexist — typically a user daemon plus a root daemon on the same host, or two OAuth accounts on a shared VM. findOtherAgentProcess() only prints a hint when something looks suspicious; it never blocks startup.

cmdop agent stop marks the machine offline immediately via a 3-second RPC. If you kill -9 the daemon, the relay keeps the machine listed as ONLINE for ~90 s until the heartbeat TTL expires.

Workspace ID flow

The daemon reads its WorkspaceID from the auth manager once, during connection setup. Switching workspaces is not an in-place mutation — it triggers a reconnect so the new WorkspaceID flows through the metadata of every gRPC call.

Do not cache or hand-mutate workspace state. See Workspaces for the credential resolver and report 06 §2.7 for the precise sequence.

Logs and rotation

Logs go through lumberjack (size-based rotation). Since 2026-04-19 the daemon does not rotate on every start; it appends, with a === DAEMON SESSION START === marker so you can grep for boot boundaries. Tail with:

cmdop agent logs -f

Locations are platform-specific (~/Library/Logs/cmdop/ on macOS, ~/.local/state/cmdop/ on Linux, %LOCALAPPDATA%\cmdop\Logs\ on Windows).

States as a diagram

MCP server (opt-in)

cmdop agent start --with-mcp exposes the agent’s tool surface to MCP clients (Claude Desktop, Cursor, VSCode). Off by default. See MCP for the integration story.

TAGS: daemon, lifecycle, status, heartbeat, online DEPENDS_ON: [agents, machine-identity, workspaces]

Last updated on