daemon
The daemon command manages the bazelle background daemon process. The daemon provides improved performance by eliminating startup overhead and allowing multiple clients to share a single file watcher.
Why Use the Daemon?
| Without Daemon | With Daemon |
|---|---|
| ~500ms startup per operation | Instant (already running) |
| Separate process per command | Single shared process |
| New file watcher per session | Shared file watcher |
| Single client at a time | Multiple simultaneous clients |
The daemon is especially useful when:
- Using the VS Code extension with watch mode
- Running frequent
bazelle updatecommands during development - Working with large codebases where startup overhead is noticeable
Commands
bazelle daemon start
Start the daemon process.
bazelle daemon start [flags]Flags:
| Flag | Description |
|---|---|
--foreground | Run in foreground (don’t daemonize). Useful for debugging. |
--socket PATH | Custom socket path (default: ~/.bazelle/daemon.sock) |
--log PATH | Custom log file path (default: ~/.bazelle/daemon.log) |
Examples:
# Start daemon in background (default)bazelle daemon start
# Run in foreground (see logs in terminal, Ctrl+C to stop)bazelle daemon start --foreground
# Use custom socket pathbazelle daemon start --socket /tmp/bazelle.sockBehavior:
- Checks if daemon is already running (via PID file)
- If running, prints “Daemon already running (PID: xxx)” and exits
- Cleans up any stale files from previous crashes
- Forks a background process (unless
--foreground) - Creates Unix socket and starts listening for connections
- Writes PID file
- Prints “Daemon started (PID: xxx)“
bazelle daemon stop
Stop the running daemon.
bazelle daemon stop [flags]Flags:
| Flag | Description |
|---|---|
--force | Force kill (SIGKILL) if graceful shutdown fails |
--socket PATH | Custom socket path |
Examples:
# Graceful shutdownbazelle daemon stop
# Force kill if graceful failsbazelle daemon stop --forceBehavior:
- Connects to daemon via socket
- Sends shutdown RPC request
- Waits up to 5 seconds for graceful shutdown
- If
--forceand still running, sends SIGKILL - Cleans up socket and PID files
bazelle daemon status
Check the daemon status.
bazelle daemon status [flags]Flags:
| Flag | Description |
|---|---|
--json | Output as JSON (for scripting) |
--socket PATH | Custom socket path |
Example Output:
Daemon: running (PID: 12345)Socket: /Users/you/.bazelle/daemon.sockVersion: 0.1.0Uptime: 2h 15mWatching: yes Paths: - /path/to/workspace Languages: - go - kotlinJSON Output:
bazelle daemon status --json{ "running": true, "pid": 12345, "socket_path": "/Users/you/.bazelle/daemon.sock", "version": "0.1.0", "uptime": "2h15m30s", "start_time": "2024-01-27T10:00:00Z", "watching": true, "watch_paths": ["/path/to/workspace"], "watch_languages": ["go", "kotlin"]}bazelle daemon restart
Restart the daemon (stop + start).
bazelle daemon restart [flags]Flags:
| Flag | Description |
|---|---|
--force | Force kill if graceful stop fails |
--socket PATH | Custom socket path |
Examples:
# Graceful restartbazelle daemon restart
# Force restartbazelle daemon restart --forceFile Locations
The daemon stores its files in ~/.bazelle/ by default:
| File | Purpose |
|---|---|
daemon.sock | Unix domain socket for client connections |
daemon.pid | PID file containing the daemon process ID |
daemon.log | Log output when running in background mode |
Architecture
Daemon Process ┌──────────────────────────────────────────────┐ │ ┌─────────┐ ┌──────────┐ ┌─────────────┐ │ │ │ Watcher │ │ Debouncer│ │ Gazelle │ │ │ └────┬────┘ └────┬─────┘ └──────┬──────┘ │ │ └────────────┴───────────────┘ │ │ │ │ │ ┌───────┴───────┐ │ │ │ Server │ │ │ │ (JSON-RPC 2.0)│ │ │ └───────┬───────┘ │ └────────────────────┼─────────────────────────┘ │ ~/.bazelle/daemon.sock ┌───────────────┼───────────────┐ │ │ │ ┌────┴────┐ ┌─────┴─────┐ ┌─────┴─────┐ │ CLI │ │ VS Code │ │ Other │ │ Client │ │ Extension │ │ Tools │ └─────────┘ └───────────┘ └───────────┘Protocol
The daemon uses JSON-RPC 2.0 over Unix sockets with newline-delimited messages.
RPC Methods
| Method | Direction | Description |
|---|---|---|
ping | client → server | Health check, returns version and uptime |
shutdown | client → server | Request graceful shutdown |
watch/start | client → server | Start watching paths |
watch/stop | client → server | Stop watching |
watch/status | client → server | Get current watch status |
watch/event | server → client | File change notification |
update/run | client → server | Trigger manual BUILD file update |
status/get | client → server | Get staleness status |
Integration
VS Code Extension
The VS Code extension automatically uses the daemon when available:
- Enable daemon mode in settings (default: enabled)
- Start the daemon:
bazelle daemon start - In VS Code, run “Bazelle: Start Watch Mode”
- The extension connects to the daemon automatically
If the daemon is unavailable, the extension falls back to subprocess mode.
{ "bazelle.daemon.enabled": true, "bazelle.daemon.autoStart": false, "bazelle.daemon.socketPath": null}Scripting
Use --json output for scripting:
# Check if daemon is running in scriptsif bazelle daemon status --json | jq -e '.running' > /dev/null; then echo "Daemon is running"else bazelle daemon startfiCI/CD
Troubleshooting
Daemon won’t start
# Check for stale filesls -la ~/.bazelle/
# Clean up if neededrm -f ~/.bazelle/daemon.sock ~/.bazelle/daemon.pid
# Try starting in foreground to see errorsbazelle daemon start --foregroundConnection refused
# Verify daemon is runningbazelle daemon status
# Check socket permissionsls -la ~/.bazelle/daemon.sock# Should show: srw------- (0600)
# Check if another process owns the socketlsof ~/.bazelle/daemon.sockDaemon crashes
Check the log file for errors:
tail -100 ~/.bazelle/daemon.logCommon causes:
- Out of memory (reduce watched paths)
- File system watcher limit (increase
fs.inotify.max_user_watcheson Linux) - Socket permission issues
Viewing logs
# Follow daemon logstail -f ~/.bazelle/daemon.log
# Or run in foregroundbazelle daemon stopbazelle daemon start --foregroundSignals
The daemon handles these signals gracefully:
| Signal | Action |
|---|---|
| SIGTERM | Graceful shutdown |
| SIGINT (Ctrl+C) | Graceful shutdown |
| SIGHUP | Graceful shutdown |
Limitations
- Unix only: Daemon uses Unix domain sockets (not available on Windows)
- Single user: Socket permissions restrict access to the owner
- Local only: No TCP/network support (planned for Phase 2)
- Single workspace: Currently supports one workspace per daemon (multi-workspace planned)