# How to Set Up and Configure the Multi-Repo Daemon (crg-daemon) for Watching Multiple Repositories

> Learn to set up and configure the multi-repo daemon crg-daemon to monitor multiple repositories. Automatically restart watchers and reload configs for efficient code review.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: how-to-guide
- Published: 2026-08-09

---

**The crg-daemon monitors multiple repositories by spawning individual watcher processes for each entry in `~/.code-review-graph/watch.toml`, automatically restarting failed watchers and reloading configuration on file changes.**

The **crg-daemon** is a built-in multi-repository watch daemon included in the **code-review-graph** toolkit. It eliminates the need to manually manage separate `code-review-graph watch` processes for each project by centralizing configuration, process management, and health monitoring in a single background service.

## Installation and Prerequisites

The daemon ships with the core **code-review-graph** package and requires no additional dependencies beyond the base installation.

```bash
pip install "code-review-graph[all]"

```

This creates the `crg-daemon` entry point automatically. You can also access sub-commands through the main CLI via `code-review-graph daemon …` as documented in the project's command reference.

## Configuring the Watch List

The daemon reads its configuration from `~/.code-review-graph/watch.toml`. This file defines the **session name**, logging directory, polling interval, and the list of repositories to monitor.

### Manual Configuration

Create or edit `~/.code-review-graph/watch.toml` with the following structure:

```toml
session_name = "crg-watch"
log_dir = "~/.code-review-graph/logs"
poll_interval = 2

[[repos]]
path = "/home/user/project-a"
alias = "project-a"

[[repos]]
path = "/home/user/project-b"
alias = "project-b"

```

The helper functions that parse and persist this file are implemented in [`code_review_graph/daemon.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/daemon.py) (lines 40-55). The file generates automatically the first time you run a modifying command, but manual editing is fully supported.

### Adding Repositories via CLI

Use the `add` sub-command to register new repositories without manually editing TOML:

```bash

# Add with a custom alias

crg-daemon add /path/to/repo-a --alias repo-a

# Add with default alias (directory name)

crg-daemon add /path/to/repo-b

```

These commands invoke `add_repo_to_config` in [`code_review_graph/daemon.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/daemon.py) (lines 97-43), which validates that the target directory contains a VCS marker (`.git`, `.svn`, or `.code-review-graph`) before persisting the entry.

### Adding Repositories Programmatically

For automation scripts or custom tooling, import the configuration helpers directly:

```python
from code_review_graph.daemon import add_repo_to_config

# Validate and persist the new repository

config = add_repo_to_config("/path/to/repo-a", alias="repo-a")
print(f"Added repo-a, total repositories: {len(config.repos)}")

```

## Managing the Daemon Lifecycle

Once configured, the daemon manages child processes, PID files, and log aggregation.

### Starting the Daemon

Launch the daemon in the background:

```bash
crg-daemon start

```

For debugging or development, keep the process attached to the terminal:

```bash
crg-daemon start --foreground

```

The `start` command creates a PID file at `~/.code-review-graph/daemon.pid` via `write_pid` (lines 80-85 in [`daemon.py`](https://github.com/tirth8205/code-review-graph/blob/main/daemon.py)). On Unix systems, it performs a double-fork to detach from the controlling terminal, then instantiates a `WatchDaemon` class that:

- Registers each repository in the central registry via `Registry.register` (lines 75-82)
- Performs an initial graph build for repositories without existing databases via `_initial_build` (lines 97-14)
- Spawns individual `code-review-graph watch` child processes per repository via `_start_watcher` (lines 38-75)

### Checking Daemon Status

Verify that the daemon and all child watchers are running:

```bash
crg-daemon status

```

This command uses `WatchDaemon.status` to report the session name, process IDs for each repository watcher, and alive/dead state by checking both in-process Popen handles and the persisted state file (lines 95-38).

### Viewing Logs

Access aggregated logs for troubleshooting:

```bash

# Tail the main daemon log

crg-daemon logs --follow

# Tail a specific repository's log by alias

crg-daemon logs --repo project-a --follow

```

Log files are stored under the directory defined by `log_dir` (defaulting to `~/.code-review-graph/logs`). Each watcher process writes to `log_path = self._config.log_dir / f"{repo.alias}.log"` as configured in `_start_watcher` (lines 40-42).

### Stopping the Daemon

Terminate all watchers and clean up state:

```bash
crg-daemon stop

```

This command kills all child processes, removes the PID file via `clear_pid`, and clears persisted state through `_clear_state` (lines 8-22).

## Advanced Configuration and Monitoring

The daemon provides automatic recovery and configuration hot-reloading for production reliability.

### Automatic Reloading and Health Checks

**Configuration Watching**: The daemon uses `ConfigWatcher` (with a fallback polling mechanism when the `watchdog` package is unavailable) to detect changes to [`watch.toml`](https://github.com/tirth8205/code-review-graph/blob/main/watch.toml). When modifications occur, it calls `reconcile` to start, stop, or restart child processes as needed (lines 33-46).

**Health Monitoring**: Every 30 seconds (`_HEALTH_CHECK_INTERVAL = 30`), a background thread inspects each child process. Dead or crashed watchers are automatically restarted without manual intervention (lines 74-10).

### Removing Repositories

Remove repositories from the watch list using either path or alias:

```bash

# By absolute path

crg-daemon remove /path/to/repo-a

# By alias

crg-daemon remove repo-b

```

Programmatically:

```python
from code_review_graph.daemon import remove_repo_from_config

config = remove_repo_from_config("repo-b")
print(f"Remaining repositories: {len(config.repos)}")

```

Both approaches invoke `remove_repo_from_config` in [`code_review_graph/daemon.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/daemon.py) (lines 45-73).

## Summary

- **crg-daemon** centralizes multi-repository watching through a single configuration file at `~/.code-review-graph/watch.toml`.
- The daemon spawns isolated `code-review-graph watch` child processes for each repository and manages them via `WatchDaemon` in [`code_review_graph/daemon.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/daemon.py).
- Use `crg-daemon add` and `crg-daemon remove` to modify the watch list without manual TOML editing.
- Automatic health checks every 30 seconds restart failed watchers, while configuration file changes trigger hot-reloading via `ConfigWatcher`.
- Logs are partitioned by repository alias and stored in the configured `log_dir` for isolated debugging.

## Frequently Asked Questions

### What file format does crg-daemon use for configuration?

The daemon uses **TOML** format for its configuration file located at `~/.code-review-graph/watch.toml`. This file stores the session name, logging directory, poll interval, and a list of repositories with their paths and aliases. The parsing logic resides in [`code_review_graph/daemon.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/daemon.py).

### How does crg-daemon handle crashed watcher processes?

The daemon implements a health check mechanism that runs every 30 seconds (`_HEALTH_CHECK_INTERVAL = 30`). If a child process terminates unexpectedly, the daemon automatically restarts it using the `_start_watcher` method, ensuring continuous monitoring without manual intervention.

### Can I run crg-daemon without installing the watchdog package?

Yes. While the daemon prefers using `watchdog` for file system events, it includes a fallback polling mechanism in `ConfigWatcher` that periodically checks for configuration changes if `watchdog` is unavailable. This ensures the daemon functions in minimal environments.

### Where are the daemon logs stored?

By default, logs are stored in `~/.code-review-graph/logs/`. Each repository watcher writes to a separate file named `{alias}.log` within this directory. You can override this location by setting the `log_dir` key in [`watch.toml`](https://github.com/tirth8205/code-review-graph/blob/main/watch.toml) or using the `--log-dir` flag during daemon startup.