ConfigsApr 14, 2026·3 min read

watchexec — Run Commands When Files Change, with Smart Defaults

watchexec watches a directory tree and runs a command when anything changes. Cross-platform, respects .gitignore, debounces, restarts long-running processes — the swiss-army knife of file-watching.

TL;DR
watchexec watches file trees and reruns commands on changes, with .gitignore support and smart debouncing.
§01

What it is

watchexec is a cross-platform file watcher that runs a command whenever files in a directory change. Written in Rust, it provides smart defaults: respecting .gitignore, debouncing rapid changes, and restarting long-running processes automatically.

watchexec is ideal for developers who want instant feedback loops during development -- rerunning tests, rebuilding projects, or restarting servers on save without configuring complex watch tools.

§02

How it saves time or tokens

watchexec eliminates the manual cycle of saving a file, switching to a terminal, and rerunning a command. It handles the edge cases that simple watch scripts miss: debouncing multiple rapid file saves into a single run, ignoring build artifacts via .gitignore, and cleanly restarting long-running processes rather than spawning duplicates.

§03

How to use

  1. Install watchexec:
# macOS
brew install watchexec
# Rust
cargo install watchexec-cli --locked
  1. Run tests on any file change:
watchexec -- cargo test
  1. Watch specific file types:
watchexec -e ts,tsx -- npm run build
  1. Restart a server on changes:
watchexec -r -- ./my-server
§04

Example

# Clear screen between runs and run pytest
watchexec -c -- pytest

# Watch only src/ directory, restart on change
watchexec -w src -r -- python app.py

# Filter by extension and ignore patterns
watchexec -e py -i '__pycache__' -- python -m myapp

# Run with shell features (pipes, redirects)
watchexec -- 'cargo build 2>&1 | head -20'
§05

Related on TokRepo

§06

Common pitfalls

  • Forgetting the -- separator between watchexec flags and the command to run
  • Not using -r for long-running processes, which causes multiple instances to stack up
  • Watching too broad a directory tree, triggering runs from build output changes

Frequently Asked Questions

How does watchexec compare to nodemon?+

watchexec is language-agnostic and runs any command, while nodemon is focused on Node.js applications. watchexec is written in Rust with better performance, supports .gitignore natively, and handles process restart more reliably.

Does watchexec respect .gitignore?+

Yes. watchexec reads .gitignore files by default and excludes matched paths from triggering events. You can disable this with the --no-vcs-ignore flag if needed.

Can watchexec restart long-running processes?+

Yes. Use the -r flag to send a termination signal to the running process and restart it when files change. This is the correct mode for development servers, as it avoids spawning duplicate processes.

What platforms does watchexec support?+

watchexec runs on Linux, macOS, and Windows. It uses native file system events (inotify, FSEvents, ReadDirectoryChanges) for efficient low-latency watching on each platform.

How does debouncing work in watchexec?+

watchexec waits a short period after detecting a change before running the command. If more changes arrive during that window, it resets the timer. This prevents running the command multiple times during a batch save operation.

Citations (3)

Discussion

Sign in to join the discussion.
No comments yet. Be the first to share your thoughts.

Related Assets