Watch Mode
Runix can automatically restart processes when files change, enabling rapid development workflows.
How It Works
Implementation
Located at internal/watcher/:
| File | Responsibility |
|---|---|
watcher.go | Main watcher — wraps fsnotify, adds recursive directory watching and ignore patterns |
debounce.go | Standalone debouncer — coalesces events within a time window |
Configuration
In runix.yaml
processes:
api:
entrypoint: ./cmd/api
watch:
paths: ["./src", "./templates", "./config"]
ignore: ["*_test.go", "*.md", "docs"]
debounce: 200ms
Via CLI
runix watch api --paths ./src --ignore "*_test.go" --debounce 300ms
Default Ignore Patterns
When no custom ignore is specified:
.git
node_modules
__pycache__
*.pyc
.DS_Store
vendor
dist
build
bin
Ignore Pattern Matching
Patterns are matched against:
- File basename —
filepath.Match(pattern, filepath.Base(path)) - Path segments — Each segment of the path is checked against the pattern
This means node_modules matches both ./node_modules and ./project/node_modules.
Event Filtering
Only these fsnotify operations trigger events:
| Operation | Triggers Restart |
|---|---|
| Write | Yes |
| Create | Yes |
| Remove | Yes |
| Rename | Yes |
| Chmod | No |
Recursive Watching
When a directory is added to the watch list, all subdirectories are watched recursively. New directories created after the watcher starts are not automatically added (fsnotify limitation).
Debounce
The debounce window coalesces rapid file changes (e.g., saving a file in an editor that writes multiple times):
- First event starts a timer (
debounceduration) - Subsequent events are collected but don't reset the timer
- When the timer fires, all collected paths are deduplicated and sent to the handler
- The handler restarts the process once
What's Next
- Watch Command — CLI usage
- Start Command —
--watchflag