# How Rustlings Watches Files for Changes: A Deep Dive into the Watch Mode Implementation

> Discover how Rustlings watches files for changes with its built-in watch mode. Learn how it automatically re-runs exercises on save for a smoother learning experience.

- Repository: [The Rust Programming Language/rustlings](https://github.com/rust-lang/rustlings)
- Tags: internals
- Published: 2026-03-05

---

**Yes, Rustlings supports automatic file watching through a built-in watch mode that monitors the `exercises/` directory and re-runs the current exercise whenever you save changes.**

The `rust-lang/rustlings` repository includes a sophisticated file watching system that eliminates the need to manually restart the tool after every edit. This feature leverages the **`notify`** crate to provide cross-platform file system monitoring, creating a tight feedback loop that makes learning Rust more interactive.

## How Rustlings Implements File Watching

The watch mode architecture separates concerns across multiple modules, with the core detection logic residing in [`src/watch.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch.rs) and state management handled in [`src/watch/state.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch/state.rs).

### The Core Watcher Setup in [`src/watch.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch.rs)

When you start Rustlings without the `--manual-run` flag, the `watch()` function initializes a `RecommendedWatcher` from the **notify** crate. This watcher is configured to recursively monitor the `exercises/` directory, polling every second for changes.

```rust
// src/watch.rs (excerpt)
let _watcher_guard = if let Some(exercise_names) = notify_exercise_names {
    let notify_event_handler = NotifyEventHandler::build(watch_event_sender.clone(), exercise_names)?;
    let mut watcher = RecommendedWatcher::new(
        notify_event_handler,
        Config::default()
            .with_follow_symlinks(false)
            .with_poll_interval(Duration::from_secs(1)),
    )?;
    watcher.watch(Path::new("exercises"), RecursiveMode::Recursive)?;
    Some(watcher)
} else {
    manual_run = true;
    None
};

```

The `NotifyEventHandler` (defined in [`src/watch/notify_event.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch/notify_event.rs)) translates raw file system events into internal `WatchEvent::FileChange` messages, which are sent through a channel to the main watch loop.

### Handling File Change Events

When a file change is detected, `run_watch()` matches on `WatchEvent::FileChange` and delegates to `WatchState::handle_file_change()` in [`src/watch/state.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch/state.rs). This method verifies whether the changed file belongs to the current exercise before re-executing:

```rust
// src/watch/state.rs (excerpt)
pub fn handle_file_change(&mut self, exercise_ind: usize, stdout: &mut StdoutLock) -> Result<()> {
    if self.app_state.current_exercise_ind() != exercise_ind {
        return Ok(());
    }
    self.run_current_exercise(stdout)
}

```

This selective re-execution prevents unnecessary runs when you modify files unrelated to the active exercise, optimizing performance while maintaining responsiveness.

## Using Rustlings Watch Mode

The watch mode operates transparently during normal usage, but you can control its behavior through CLI flags when necessary.

### Starting Watch Mode

By default, Rustlings automatically enables file watching when you run:

```bash
rustlings

```

Once active, the tool displays the current exercise and waits for events. When you save changes to any file within `exercises/`, the UI updates automatically:

```text
Checking the exercise `variables2`. Please wait…
... (output of the check)
Exercise done ✓
Hint
...
n:next / r:run / h:hint / l:list / c:check all / x:reset / q:quit ?

```

If you modify [`exercises/variables2/src/main.rs`](https://github.com/rust-lang/rustlings/blob/main/exercises/variables2/src/main.rs) while the prompt is waiting, the program detects the change and re-runs the exercise without requiring additional input.

### Manual Run Mode

If the file watcher cannot initialize (for example, on Windows systems without proper support) or if you prefer explicit control, Rustlings provides a fallback **manual run mode**. You can explicitly disable watching with:

```bash
rustlings --manual-run

```

In this mode, the tool executes the current exercise once and returns to the prompt, waiting for you to press `r` to re-run rather than monitoring files automatically. The constant `NOTIFY_ERR` in [`src/watch.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch.rs) defines the error message displayed when the watcher fails to initialize, guiding users toward this flag.

## Key Files in the Watch System

The file watching functionality spans several modules in the Rustlings codebase:

- **[`src/watch.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch.rs)** — Initializes the `RecommendedWatcher`, configures the notify event handler, and coordinates the main watch/list loops.
- **[`src/watch/state.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch/state.rs)** — Maintains watch-mode state, renders the terminal UI, and handles `FileChange` events by re-running exercises.
- **[`src/watch/notify_event.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch/notify_event.rs)** — Implements the `notify::EventHandler` trait to convert raw file-system events into internal `WatchEvent` messages.
- **[`src/watch/terminal_event.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch/terminal_event.rs)** — Listens for keyboard input during watch mode, handling commands like `n` (next), `r` (run), and `q` (quit).
- **[`src/main.rs`](https://github.com/rust-lang/rustlings/blob/main/src/main.rs)** — Entry point that parses CLI arguments (including `--manual-run`) and decides whether to invoke watch mode.

## Summary

- **Rustlings includes native file watching** that monitors the `exercises/` directory for changes using the `notify` crate.
- **The watcher runs automatically** when you start `rustlings` without the `--manual-run` flag, re-executing the current exercise upon file saves.
- **Implementation spans [`src/watch.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch.rs) and [`src/watch/state.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch/state.rs)**, utilizing `RecommendedWatcher` with a 1-second poll interval and recursive directory monitoring.
- **Manual run mode provides a fallback** when file system watching is unavailable or undesirable, requiring explicit `r` keypresses to re-run exercises.

## Frequently Asked Questions

### How do I disable file watching in Rustlings?

Use the `--manual-run` flag when starting the tool: `rustlings --manual-run`. This disables the automatic file watcher and requires you to press `r` to manually re-run exercises after making changes.

### What happens if Rustlings cannot initialize the file watcher?

If the `RecommendedWatcher` fails to initialize (which can occur on certain Windows configurations or restricted environments), Rustlings automatically falls back to manual run mode. The tool displays the `NOTIFY_ERR` message defined in [`src/watch.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch.rs) and operates as if `--manual-run` had been specified.

### Which directory does Rustlings watch for changes?

Rustlings recursively monitors the `exercises/` directory relative to the project root. The watcher is configured in [`src/watch.rs`](https://github.com/rust-lang/rustlings/blob/main/src/watch.rs) with `RecursiveMode::Recursive`, meaning it detects changes in any subdirectory or file within the exercises folder, including [`src/main.rs`](https://github.com/rust-lang/rustlings/blob/main/src/main.rs) files for individual exercises.

### Can I use Rustlings watch mode in CI environments?

While possible, it is not recommended. File watching requires a persistent process and active file system event monitoring, which may not function reliably in containerized or headless CI environments. For continuous integration, use `rustlings --manual-run` or run specific exercise verification commands that exit after completion rather than waiting for file changes.