Skip to content

Daemon

The daemon is Mia’s central process. It runs in the background, manages all subsystems, and routes messages between interfaces (CLI, mobile) and AI plugins.

The daemon initializes subsystems in a specific order:

  1. Process safety — Registers handlers for unhandled rejections and exceptions. After 10 crashes in 5 minutes, the daemon exits.
  2. Environment — Captures the project working directory, then chdir to ~/.mia. Loads .env from ~/.mia/.env.
  3. PID file — Writes ~/.mia/.mia.pid to prevent duplicate daemons.
  4. Codebase context — Scans the project directory for languages, frameworks, file counts. Cached for the daemon’s lifetime.
  5. Memory store — Opens SQLite database, runs migrations, schedules periodic TTL pruning.
  6. Plugin registry — Registers all four plugins (Claude Code, Codex, OpenCode, Gemini), initializes each with config, warms availability cache.
  7. Middleware chain — Sets up ContextPreparer → TraceLogger → PostDispatchVerifier → MemoryExtractor.
  8. P2P networking — Derives topic key from seed, spawns P2P sub-agent as child process, wires message handlers.
  9. Scheduler — Loads scheduled-tasks.json, starts all enabled cron jobs.
  10. Event loop — Begins accepting messages from CLI (IPC) and mobile (P2P).

When the daemon receives a shutdown signal:

  1. Arms a 15-second grace period timer
  2. Aborts all running plugin tasks
  3. Flushes memory cache
  4. Closes P2P connections
  5. Closes message store
  6. Writes final status
  7. Exits cleanly

A watchdog timer detects event loop stalls. If the main loop blocks for too long, the daemon logs a warning and can take corrective action.

CLI commands connect to the daemon via IPC (Unix domain socket). The daemon parses the command and routes to the appropriate handler:

  • Routed commands: ask, chat, commit, standup, changelog, memory, plugin, scheduler, p2p, config, doctor, log, usage, update
  • Daemon commands: start, stop, restart, status, logs (handled by the CLI directly)

Mobile messages arrive via the Hyperswarm P2P connection. The swarm-message-handler (the largest module, ~1000 lines) parses typed JSON messages and routes them.

Message types include:

CategoryExamples
Conversationsnew_conversation, load_conversation, rename, delete
Dispatchdispatch (main prompt), abort
State queriesconversations_request, plugins_request, history_request
Plugin mgmtplugin_switch
Schedulerscheduler_list_request, scheduler_create, scheduler_delete
Searchsearch_request
Systemping, suggestions_request

The daemon writes its PID to ~/.mia/.mia.pid on startup. The CLI checks this file to determine if the daemon is running before attempting to start a new instance.

For production use, the daemon runs under PM2 for automatic restarts and log management:

Terminal window
mia start # Starts daemon via PM2
mia stop # Stops PM2 process
mia restart # Restarts PM2 process
mia logs # Tails PM2 logs
  • Unhandled rejections: Caught and logged. After 10 in a 5-minute window, the daemon exits to prevent runaway failures.
  • Plugin errors: Standardized PluginError type with codes (TIMEOUT, SPAWN_FAILURE, PROCESS_EXIT, etc.). Errors trigger fallback chain if configured.
  • Stall detection: Child processes killed if no output for 120 seconds.