How Daemon Mode Handles Multiple Repositories with Auto-Watch in Code-Review-Graph
The crg-daemon background process monitors a central TOML configuration file to automatically spawn, manage, and restart individual watcher processes for each repository without requiring manual intervention when repositories are added or removed.
The code-review-graph daemon provides a centralized background service capable of watching unlimited repositories simultaneously. Instead of running separate code-review-graph watch commands for each project, the daemon maintains a persistent configuration at ~/.code-review-graph/watch.toml and handles process lifecycle management automatically. This architecture ensures that code review graphs stay synchronized across all monitored repositories through a single controlling process.
Configuration Loading and Validation
The daemon initializes by loading repository definitions from a TOML configuration file located at ~/.code-review-graph/watch.toml (referenced via CONFIG_PATH at line 41 in code_review_graph/daemon.py).
The load_config function (lines 84-118) parses this file and constructs a DaemonConfig dataclass containing a list of WatchRepo records. During loading, the daemon validates each repository entry to ensure the path exists and contains a version control marker (.git, .svn, or .code-review-graph). Invalid entries are filtered out before the daemon proceeds to process initialization.
Spawning Per-Repository Watch Processes
When the daemon starts via the _handle_start function in code_review_graph/daemon_cli.py (line 31), it instantiates the WatchDaemon class (defined at line 588 in daemon.py) with the loaded configuration.
For each repository in config.repos, the WatchDaemon.start method launches a dedicated child process running the standard code-review-graph watch CLI command. Each child process receives its own log file under ~/.code-review-graph/logs/<alias>.log, ensuring isolated logging for every monitored repository. This separation prevents crashes in one repository watcher from affecting others.
Auto-Watch Mechanism and Health Monitoring
The daemon implements auto-watch through a continuous polling loop that checks the configuration file every 2 seconds (poll_interval default). When users modify watch.toml—either manually or through crg-daemon add and remove commands—the daemon detects the file change, reloads the configuration, and automatically starts or stops the associated child watchers without requiring a daemon restart.
A separate health-check thread runs every 30 seconds (controlled by _HEALTH_CHECK_INTERVAL at line 44) to verify that each child process remains alive. If a watcher process dies unexpectedly, the daemon automatically respawns it, ensuring continuous monitoring of all configured repositories.
Managing Repositories via CLI
The daemon provides a complete command-line interface for runtime repository management. The following workflow demonstrates adding multiple repositories and monitoring their status:
# Add repositories to the watch list
crg-daemon add ~/projects/api --alias api
crg-daemon add ~/projects/web
# Start the background daemon
crg-daemon start
# Check individual watcher status
crg-daemon status
# Output shows PID and health for each repository:
# Daemon: running (PID 12345)
# Name: crg-watch
# Log dir: /home/user/.code-review-graph/logs
# Poll: 2s
#
# Alias Status PID Path
# ----- ------ --- ----
# api alive 12346 /home/user/projects/api
# web alive 12347 /home/user/projects/web
# Add a new repository without restarting the daemon
crg-daemon add ~/projects/cli --alias cli
# Remove a repository and stop its watcher
crg-daemon remove api
The add_repo_to_config and remove_repo_from_config functions safely modify watch.toml while the daemon is running, triggering the auto-watch reload mechanism immediately.
Summary
- Centralized configuration: The daemon reads repository definitions from
~/.code-review-graph/watch.tomlusing theload_configparser (lines 84-118). - Isolated child processes: Each repository runs in its own
code-review-graph watchsubprocess managed by theWatchDaemonclass (line 588), with dedicated log files in~/.code-review-graph/logs/. - Automatic reconciliation: The daemon polls the configuration file every 2 seconds to detect additions or removals, updating active watchers without restarts.
- Self-healing architecture: A health-check loop running every 30 seconds (
_HEALTH_CHECK_INTERVAL) automatically restarts any crashed watcher processes.
Frequently Asked Questions
How does the daemon detect new repositories without restarting?
The daemon polls ~/.code-review-graph/watch.toml every 2 seconds (configurable via poll_interval). When you execute crg-daemon add or manually edit the file, the WatchDaemon detects the modification timestamp change, reloads the configuration through load_config, and spawns new child processes for any added repositories while leaving existing watchers untouched.
What happens if a watcher process crashes?
The daemon's health-check thread evaluates every child PID every 30 seconds using the _HEALTH_CHECK_INTERVAL constant (line 44). If a process is no longer alive, the daemon automatically invokes the spawning logic again to restart that specific repository watcher, ensuring continuous monitoring without user intervention.
Where does the daemon store its configuration and logs?
Configuration persists at ~/.code-review-graph/watch.toml (defined in CONFIG_PATH at line 41), while runtime logs reside in ~/.code-review-graph/logs/. Each repository receives its own log file named <alias>.log, and the daemon itself writes to daemon.log in the same directory.
Can I run the daemon in the foreground for debugging?
Yes. Start the daemon with the --foreground flag to prevent background detachment. This mode keeps the process attached to your terminal, allowing you to observe the polling loop and health-check output directly without checking log files.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →