Skip to content

feat: daemon mode for unified resource management (model scheduling, DB pooling, concurrency control) #16

Description

@aider4ryder

Motivation

Currently each codeseek serve --mcp invocation is a standalone process that:

  1. Opens its own LanceDB connection (file-level locking, potential lock contention)
  2. Makes independent HTTP calls to embedding/reranker endpoints (no concurrency coordination)
  3. Holds the full index in memory per process

When multiple MCP clients connect (e.g. Hermes agent + Codex + Claude Code simultaneously), this creates:

  • Lock contention: concurrent LanceDB reads/writes, index update races
  • Resource waste: N processes each loading the same index into memory
  • No global concurrency control: N clients × M embedding requests can overwhelm the model endpoint
  • Data loss risk: concurrent index writes can fail silently or corrupt the index

Proposed architecture

┌─────────────────────────────────────────┐
│           codeseek daemon                │
│  ┌─────────┐  ┌──────────┐  ┌────────┐  │
│  │ Index   │  │ Embedding│  │Reranker│  │
│  │ Manager │  │ Scheduler│  │Queue   │  │
│  │(1 writer│  │(concurrency│ │        │  │
│  │ +N read)│  │ control) │  │        │  │
│  └─────────┘  └──────────┘  └────────┘  │
│       ↑              ↑            ↑      │
│    unix socket / tcp on localhost        │
└──────┬──────────────┬────────────┬──────┘
       │              │            │
   MCP thin      CLI thin       CLI thin
   wrapper       wrapper        wrapper

Benefits

  • Single DB connection: daemon owns the LanceDB handle, serializes writes, multiplexes reads. Eliminates lock contention.
  • Global concurrency control: daemon queues embedding/reranker requests with a configurable max-concurrency, preventing endpoint overload.
  • Shared index cache: one copy in daemon memory, served to all clients.
  • Controlled writes: daemon can queue index updates and apply them atomically, preventing corruption from concurrent writes.
  • Thin MCP/CLI wrappers: MCP server and CLI become thin RPC clients to the daemon, reducing per-client memory from ~300MB to <10MB.

API sketch

# Start daemon (background, long-lived)
codeseek daemon start --port 0  # port 0 = auto-assign, write to ~/.codeseek/daemon.pid

# MCP and CLI auto-connect to daemon if running
codeseek search "query"    # → connects to daemon → returns results
codeseek init               # → daemon queues reindex

Graceful degradation

If daemon is not running, MCP/CLI fall back to the current standalone mode (own DB connection, own HTTP calls). Users opt into daemon mode by starting it — no breaking change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions