watchexec
A simple, standalone tool that watches a path and runs a command whenever it detects modifications.
watchexec is a general-purpose file watcher that runs a command whenever files
in a directory change. It's the Swiss Army knife of watch-and-run tools —
simpler than Makefiles, more flexible than language-specific watchers like
cargo-watch, and usable with any command or project type.
Features
- Language agnostic — works with any command:
make,cargo,python,npm run, anything - Smart filtering — ignores version control directories, build artefacts, and hidden files by default
- Debouncing — waits for a burst of changes to settle before triggering, so a bulk save doesn't spawn dozens of runs
- Signal control — configurable signal sent to the running process before
restarting (e.g.
SIGTERM,SIGKILL,SIGHUP) - Clear screen — optionally clear the terminal between runs for a clean view each time
- Ignore files — respects
.gitignore,.ignore, and custom ignore files - On-change environment — injects environment variables describing which files changed so your command can react to them
Installation
cargo install watchexec-cli
Or via your system package manager:
# Debian / Ubuntu (Debian 12+)
apt install watchexec
# Fedora
dnf install watchexec
# macOS
brew install watchexec
# Arch Linux
pacman -S watchexec
# Nix
nix-env -iA nixpkgs.watchexecUsage
# Rerun a command whenever any file in the current directory changes
watchexec -- make build
# Watch only Rust source files
watchexec --exts rs -- cargo test
# Watch a specific directory
watchexec --watch src -- npm run build
# Clear the terminal before each run
watchexec --clear -- cargo run
# Send SIGHUP to the process instead of killing it (useful for servers that reload on SIGHUP)
watchexec --signal SIGHUP -- ./my-server
# Restart a long-running process (e.g. a dev server) on change
watchexec --restart -- python app.py
# Ignore specific paths
watchexec --ignore target --ignore node_modules -- make
# Only trigger on specific events (create, modify, remove, rename)
watchexec --on-busy-update restart -- cargo checkEnvironment variables injected on change
When a command runs, watchexec provides details about what triggered it:
| Variable | Description |
|---|---|
WATCHEXEC_COMMON_PATH | Longest common path of all changed files |
WATCHEXEC_CREATED_PATH | Paths of created files |
WATCHEXEC_REMOVED_PATH | Paths of removed files |
WATCHEXEC_RENAMED_PATH | Paths of renamed files |
WATCHEXEC_WRITTEN_PATH | Paths of modified files |
This makes it easy to write scripts that act on the specific file that changed:
watchexec --shell=bash -- 'echo "Changed: $WATCHEXEC_WRITTEN_PATH"'Comparison with cargo-watch and bacon
watchexec is more general than cargo-watch or bacon — it doesn't know
anything about Rust specifically. That's its strength: the same mental model
applies whether you're working on a Rust project, a Python script, a LaTeX
document, or a shell pipeline. For Rust-specific workflows with formatted
compiler output, bacon is more ergonomic; for everything else, watchexec is
hard to beat.