Daemon (sqryd)

Overview

sqryd is sqry’s background process. It keeps one or more workspace graphs loaded in memory and serves CLI, LSP, and MCP queries from that warm state instead of rebuilding the index on every invocation. A file-system watcher debounces edits and rebuilds incrementally in the background. The CLI subcommand family sqry daemon and the standalone sqryd binary are two views of the same process — sqry daemon is the convenient parent-CLI surface; sqryd is the binary that actually runs.

Use sqryd when:

Skip sqryd for one-shot CLI invocations on small repositories — the cold-start cost is already low and the daemon adds no value at that size.

Quick start

sqry daemon start
sqry daemon load .
sqry-mcp --daemon       # MCP shim — auto-starts the daemon if not running
sqry lsp --stdio --daemon  # LSP shim

sqry daemon start execs sqryd start --detach, then polls the IPC socket until the daemon signals readiness. sqry daemon load <path> registers a workspace and builds its graph in the background; subsequent queries against that workspace are served instantly.

If a shim (sqry-mcp --daemon / sqry-lsp --daemon) cannot reach a daemon, it auto-starts one. Set SQRY_DAEMON_NO_AUTO_START=1 to disable the auto-start fallback.

CLI reference

SubcommandDescription
sqry daemon startLaunch sqryd start --detach and wait for readiness.
sqry daemon stopSend daemon/stop over IPC and wait for graceful shutdown.
sqry daemon status [--json]Show daemon version, uptime, memory, peak, workspace count.
sqry daemon logs [--lines N] [--follow]Tail the configured log file (requires log_file to be set).
sqry daemon load <path>Register a workspace and warm its graph.
sqry daemon rebuild <path>Trigger an in-place rebuild for a loaded workspace.

sqry daemon status --json emits a ResponseEnvelope<DaemonStatus> — a two-field object { "result": <DaemonStatus>, "meta": <ResponseMeta> }. Scripts should index through .result to reach the status fields.

sqryd binary

The binary itself exposes a small set of admin verbs:

VerbDescription
sqryd start [--detach]Foreground or detached start. --detach is a no-op on Windows.
sqryd foregroundRun in the foreground (logs to stderr unless log_file is set).
sqryd stopEquivalent to sqry daemon stop.
sqryd statusEquivalent to sqry daemon status.
sqryd print-configDump the resolved daemon config (file + env overrides).
sqryd install-systemd-userGenerate a systemd user-service unit.
sqryd install-systemd-systemGenerate a systemd system-service unit.
sqryd install-launchdGenerate a macOS launchd plist.
sqryd install-windowsGenerate a Windows service wrapper config.

Configuration

Daemon settings live in a TOML file. Path resolution order:

Override via SQRY_DAEMON_CONFIG=/path/to/daemon.toml.

FieldDefaultDescription
memory_limit_mb2048Maximum resident graph memory across all workspaces. LRU eviction kicks in above this.
idle_timeout_minutes30Idle period before the daemon may shut itself down.
debounce_ms2000File-system event debounce window.
max_shim_connections256Concurrent MCP/LSP shim connection cap.
log_max_size_mb50Log rotation size threshold.
log_keep_rotations5Rotated log segments to retain.
socket.pathplatform defaultUnix domain socket path.
socket.pipe_namesqryWindows named-pipe leaf name (resolves to \\.\pipe\sqry).
log_fileunset (stderr)Required for sqry daemon logs.

Changes require a daemon restart (sqry daemon stop && sqry daemon start).

Environment variables

Every key field has an environment-variable override. Env wins over the config file.

VariableEffect
SQRY_DAEMON_CONFIGOverride the config-file path.
SQRY_DAEMON_MEMORY_MBOverride memory_limit_mb.
SQRY_DAEMON_SOCKETOverride the Unix socket path.
SQRY_DAEMON_PIPEOverride the Windows pipe name.
SQRY_DAEMON_LOG_FILESet the log-file path.
SQRY_DAEMON_LOG_LEVELerror, warn, info (default), debug, trace.
SQRY_DAEMON_LOG_KEEP_ROTATIONSOverride log_keep_rotations.
SQRY_DAEMON_TOOL_TIMEOUT_SECSCap per-tool execution time inside MCP host.
SQRY_DAEMON_MAX_SHIM_CONNECTIONSOverride max_shim_connections.
SQRY_DAEMON_STALE_MAX_AGE_HOURSReject queries against workspaces last refreshed beyond this age.
SQRY_DAEMON_AUTO_START_READY_TIMEOUT_SECSShim auto-start readiness timeout.
SQRY_DAEMON_NO_AUTO_STARTDisable shim auto-start-on-miss when set to 1.

IPC transport

Shims and CLI clients talk to the daemon over a length-prefixed JSON-RPC channel.

Frames are 4-byte little-endian length prefixes followed by JSON. The handshake (DaemonHello / DaemonHelloResponse, ShimRegister / ShimRegisterAck) negotiates the protocol envelope version. Tool calls follow standard JSON-RPC 2.0 framing.

The shim registry enforces max_shim_connections (default 256) — admission-controlled with a ShimRegisterAck { accepted: false } and reason string "shim registry full ({current} / {cap})" when the cap is exceeded.

Workspace lifecycle

Each registered workspace transitions through a small state machine:

StateMeaning
UnloadedRegistered but no graph in memory.
LoadingCold or rebuild in progress.
LoadedGraph resident; queries serve from cache.
RebuildingA file-system change triggered an incremental rebuild.
EvictedLRU evicted under memory pressure; the next query must reload.
FailedBuild error; see the daemon log.

When memory_limit_mb is exceeded, the least-recently-used workspace is evicted. Queries against an evicted workspace return WorkspaceEvicted (IPC code -32004); shims surface this so the caller can reload the workspace explicitly.

The file-system watcher debounces editor saves over debounce_ms (default 2000 ms) and cancels in-flight rebuilds when a newer event arrives.

Observability

sqry daemon status [--json] reports daemon version, uptime, total resident memory, per-workspace high-water mark, and counts. Combine with sqry daemon logs --follow (after setting log_file) for live tracing.

The status payload’s meta field carries daemon_version and staleness flags so a remote client can detect a daemon mismatch without parsing the result body.

Lifecycle and singleton enforcement

Service installation

For long-running deployments, install the daemon as an OS-managed service:

# Linux (per-user, no sudo required)
sqryd install-systemd-user
systemctl --user enable --now sqryd.service

# Linux (system-wide)
sudo sqryd install-systemd-system
sudo systemctl enable --now sqryd.service

# macOS
sqryd install-launchd
launchctl load ~/Library/LaunchAgents/dev.sqry.sqryd.plist

# Windows (service wrapper)
sqryd install-windows

Each install-* verb writes the unit/plist/wrapper and prints the next-step command for the OS service manager.

Using the daemon with MCP and LSP

# MCP shim (Claude Code, Codex, Gemini, Cursor, Windsurf)
sqry-mcp --daemon

# LSP shim (any LSP 3.17 client)
sqry lsp --stdio --daemon

The shims connect to the daemon over IPC and proxy MCP / LSP requests to the warm graph. sqry-mcp --daemon and sqry lsp --daemon both auto-start the daemon if it is not already running, unless SQRY_DAEMON_NO_AUTO_START=1.

To wire an MCP client (e.g. Claude Code) to the daemon-backed shim, add "args": ["--daemon"] to its sqry-mcp server entry — see the MCP Integration page.

Troubleshooting