The daemon (grite-daemon) is optional and exists only to improve performance and coordination. Correctness never depends on it.
# Daemon auto-spawns on first command (no manual start needed)
grite issue list
# Manual control
grite daemon start --idle-timeout 300
grite daemon status
grite daemon stop
# Force local execution (skip daemon)
grite --no-daemon issue listThe daemon automatically spawns when you run CLI commands:
- CLI checks for running daemon
- If no daemon, spawns
grite-daemonin background - Waits for daemon to become ready (up to 5 seconds)
- Routes command through IPC
- Daemon runs until idle timeout
Default idle timeout is 5 minutes (300 seconds).
Use --no-daemon to force local execution:
grite --no-daemon issue listThe daemon automatically shuts down after a period of inactivity:
# Start with 10-minute idle timeout
grite daemon start --idle-timeout 600
# Start with no timeout (runs until stopped)
grite daemon start --idle-timeout 0The idle timer resets on each command. When timeout is reached:
- Daemon logs "Idle timeout reached"
- Workers shut down gracefully
- All locks released
- Process exits
- Maintain a warm materialized view for fast reads
- Handle concurrent CLI requests efficiently
- Refresh daemon lock heartbeat
- Release locks on shutdown
- Never rewrites refs or force-pushes
- Never writes to the working tree
- Never becomes required for correctness
- No background sync (sync is explicit via
grite sync)
+----------------+ +----------------+ +----------------+
| CLI | --> | Supervisor | --> | Worker |
| (grite) | | (manages IPC) | | (per repo/actor)|
+----------------+ +----------------+ +----------------+
| | |
v v v
IPC Request Route to Worker Execute Command
|
v
+-------------+
| LockedStore |
| (sled) |
+-------------+
- Listens on IPC socket (
/tmp/grite-daemon.sock) - Routes requests to appropriate worker
- Manages worker lifecycle
- Tracks idle time for auto-shutdown
- One worker per (repo, actor) pair
- Holds exclusive
flockon sled database - Spawns concurrent tokio tasks for commands
- Refreshes daemon lock heartbeat
The daemon handles concurrent requests efficiently:
- Supervisor receives IPC request
- Routes to worker for (repo, actor)
- Worker spawns tokio task
- Sled MVCC handles concurrent access
- Response sent back via IPC
Multiple CLI processes can issue commands simultaneously. The daemon serializes database access internally while allowing concurrent execution.
The daemon acquires an exclusive flock on sled.lock:
.git/grite/actors/<actor_id>/sled.lock
This prevents other processes from opening the sled database while the daemon is running.
The daemon creates a JSON lock file for coordination:
.git/grite/actors/<actor_id>/daemon.lock
Example:
{
"pid": 12345,
"started_ts": 1700000000000,
"repo_root": "/path/to/repo",
"actor_id": "64d15a2c383e2161772f9cea23e87222",
"host_id": "hostname",
"ipc_endpoint": "/tmp/grite-daemon.sock",
"lease_ms": 30000,
"last_heartbeat_ts": 1700000000000,
"expires_ts": 1700000030000
}| Scenario | CLI Behavior |
|---|---|
| No daemon lock | Execute locally or auto-spawn |
| Lock valid, IPC reachable | Route through daemon |
| Lock valid, IPC unreachable | Error (daemon may have crashed) |
| Lock expired | Take over, execute locally |
$ grite daemon status
Daemon is running
PID: 12345
Host ID: my-laptop
IPC Endpoint: /tmp/grite-daemon.sock
Started: 2024-01-15 10:30:00 UTC
Expires in: 25s$ grite daemon status --json
{
"running": true,
"pid": 12345,
"host_id": "my-laptop",
"ipc_endpoint": "/tmp/grite-daemon.sock",
"started_ts": 1705315800000,
"expires_ts": 1705315830000,
"time_remaining_ms": 25000
}| Failure | Recovery |
|---|---|
| Daemon crashes | Lock expires, CLI can take over |
| IPC timeout | CLI retries 3 times, then errors |
| Worker panics | Supervisor continues, worker restarted on next request |
| Command error | Error returned via IPC, daemon continues |
The daemon logs to stderr. Control verbosity with --log-level:
grite-daemon --log-level debugLog levels: trace, debug, info, warn, error
When auto-spawned, daemon runs with --log-level info and stdout/stderr redirected to /dev/null.
- Socket:
/tmp/grite-daemon.sock(Unix domain socket) - Framing: length-prefixed (
u32BE + payload) - Serialization: rkyv (zero-copy)
- Concurrency: one task per connection
See IPC Protocol for message format details.
The daemon reads configuration from:
- Command-line arguments
- Environment variables (for log level)
No configuration file is used. The daemon is stateless except for the workers it manages.
| Aspect | Without Daemon | With Daemon |
|---|---|---|
| First command latency | Higher (open sled) | Lower (sled warm) |
| Concurrent commands | Serialize at flock | Concurrent in daemon |
| Memory usage | Per-process | Shared in daemon |
| Complexity | Simple | More moving parts |
| Correctness | Same | Same |