惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
H
Help Net Security
N
Netflix TechBlog - Medium
Apple Machine Learning Research
Apple Machine Learning Research
P
Proofpoint News Feed
A
About on SuperTechFans
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
宝玉的分享
宝玉的分享
aimingoo的专栏
aimingoo的专栏
F
Fortinet All Blogs
博客园 - 【当耐特】
Microsoft Security Blog
Microsoft Security Blog
Martin Fowler
Martin Fowler
I
InfoQ
Google DeepMind News
Google DeepMind News
人人都是产品经理
人人都是产品经理
Engineering at Meta
Engineering at Meta
腾讯CDC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog RSS Feed
U
Unit 42
The Cloudflare Blog
Y
Y Combinator Blog

Stonecharioteer on Tech

I Traced My Traffic Through a Home Tailscale Exit Node What Was I Reading Last? In Three Not-So-Easy Pieces Dogfooding Is Hard Code blocks in your books, finally GoForGo v0.9.0 Merrilin - We built an app to read books I use a Macbook now Data Structures & Algorithms - Preparing for Interviews Using a local DNS namespace for local service discovery Direction KOllector - Publishing KOReader Highlights gbt: branches touched in the last 24 hours A Soiree into Symbols in Ruby Some Smalltalk about Ruby Loops Ruby Blocks Returning from Ruby Blocks, Procs and Lambdas My Linux Laptop Finally Works: How Claude Helped Me Fix Years of Annoyances TIL: Watchexec - Modern File Watching for Development Workflows A Less Busy Mind GoForGo - Learn Go through live examples Migrating My Old Blog to Hugo with Claude The Qtile Window Manager: A Python-Powered Tiling Experience Read the RFCs that Built the Internet Py-x-Protobuf - Or How I Learned to Stop Worrying and Love Protocol Buffers Python Reverse a List New Beginnings Leaving ChainSafe Systems Screen Lock for Cinnamon Desktop using Zenity and Terminal Commands Crews Not Teams A System for Getting Better at LeetCode
TIL: Watchexec - Modern File Watching for Development Wor...
2025-08-19 · via Stonecharioteer on Tech

Today I discovered watchexec, a modern cross-platform file watcher that has completely replaced entr in my development workflow. It executes commands when files change with much better defaults and a more intuitive interface than traditional file watching tools.

AI-Generated Content

This post was written with assistance from Claude (Anthropic’s AI assistant) based on my experiences and requirements. While the technical content and examples reflect real usage patterns, the writing was collaboratively generated. The discovery of watchexec’s advantages over entr - particularly the reduction from verbose find . -name "*.go" | entr -r go test to clean watchexec -e go 'go test ./...' - represents genuine workflow improvements in my development process.

The Core Discovery

Watchexec is a Rust-based tool that watches file system changes and triggers commands. Unlike entr, which requires explicit file listing and complex find commands, watchexec works intelligently out of the box.

What is watchexec?

Watchexec is a simple, standalone tool that watches a path and runs a command whenever files change. It’s written in Rust, cross-platform, and has sensible defaults that make it easier to use than alternatives like entr or inotifywait.

Install it with:

1
2
3
4
5
6
7
8
# Cargo
cargo install watchexec-cli

# Homebrew (macOS/Linux)
brew install watchexec

# Arch Linux
pacman -S watchexec

Hugo Development

For this blog, I use watchexec to auto-rebuild the site during development:

1
2
3
4
5
6
7
8
# Basic Hugo development server
watchexec -e md,yml,yaml,html,css,js 'hugo serve --buildDrafts'

# Only watch content and config changes
watchexec -w content -w hugo.yml -w layouts 'hugo'

# Build and serve on any change
watchexec -r 'hugo && hugo serve --port 1314'

The -e flag specifies file extensions to watch, and -w specifies directories. The -r flag restarts the command (killing the previous process) rather than running concurrent instances.

Rust Development with Cargo

For Rust projects, watchexec shines with cargo commands:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Auto-compile on save
watchexec -e rs 'cargo check'

# Run tests continuously
watchexec -e rs 'cargo test'

# Build and run
watchexec -e rs 'cargo run'

# Format and check
watchexec -e rs 'cargo fmt && cargo clippy'

# Watch specific files only
watchexec -w src -w Cargo.toml 'cargo build'

I particularly love using it during TDD workflows where I want tests to run immediately after changing code.

Go development becomes much smoother with watchexec:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# Run tests on any Go file change
watchexec -e go 'go test ./...'

# Build and run
watchexec -e go 'go run main.go'

# Build with race detection
watchexec -e go 'go build -race .'

# Run specific test package
watchexec -w internal/auth 'go test ./internal/auth'

# Format and vet
watchexec -e go 'go fmt ./... && go vet ./...'

The ability to watch specific directories with -w is especially useful in larger Go projects where you only want to run tests for the package you’re working on.

Why I Switched from entr

I used entr for years, but watchexec has several advantages:

Better Defaults

  • entr: Requires explicit file listing via find or similar
  • watchexec: Recursively watches current directory by default
1
2
3
4
5
# entr - verbose and error-prone
find . -name "*.go" | entr -r go test ./...

# watchexec - simple and intuitive
watchexec -e go 'go test ./...'

Ignore Patterns

  • entr: No built-in ignore patterns
  • watchexec: Respects .gitignore, .ignore, and has smart defaults

Watchexec automatically ignores common build artifacts, .git directories, and other noise. With entr, I had to carefully craft find commands to avoid triggering on build outputs.

Process Management

  • entr: Basic process handling
  • watchexec: Better process lifecycle management with -r flag

The -r flag in watchexec properly kills and restarts long-running processes, which is perfect for development servers.

Cross-Platform

  • entr: Unix-only
  • watchexec: Works on Windows, macOS, and Linux

Caveats and Gotchas

While watchexec is excellent, there are some things to watch out for:

Build Output Loops

Be careful not to watch directories that contain build outputs. If your command generates files in a watched directory, you’ll create an infinite loop.

1
2
3
4
5
# BAD - watching target/ where cargo outputs builds
watchexec -w . 'cargo build'

# GOOD - exclude target directory
watchexec -i target/ -e rs 'cargo build'

Performance with Large Projects

In very large codebases, watching too many files can impact performance. Use -w to watch specific directories or -i to ignore large directories like node_modules/ or target/.

Command Escaping

Complex commands with pipes or redirections need proper shell escaping:

1
2
3
4
5
# Use quotes for complex commands
watchexec 'cargo test 2>&1 | grep -E "(test|error)"'

# Or use shell flag
watchexec -s 'cargo test | tee test.log'

Other Considerations

  • Debouncing: Watchexec debounces file changes by default (50ms), which prevents multiple rapid triggers
  • Signal Handling: Long-running processes are sent SIGTERM, then SIGKILL if they don’t exit gracefully
  • Environment: Commands run in the same directory where watchexec was started

Cheatsheet

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# Basic usage
watchexec <command>                    # Watch current dir, run command on any change
watchexec -e rs,toml 'cargo check'     # Watch only .rs and .toml files
watchexec -w src 'make test'           # Watch only src/ directory
watchexec -i target/ 'cargo build'     # Ignore target/ directory

# Process control
watchexec -r 'hugo serve'              # Restart command (kill previous)
watchexec -s 'make && ./app'           # Use shell for complex commands
watchexec --delay 1s 'slow-command'    # Add delay before running

# Filtering
watchexec -e go,mod 'go test'          # Extensions (comma-separated)
watchexec -w app -w lib 'make'         # Multiple watch dirs
watchexec -i '*.tmp' -i build/ 'make'  # Ignore patterns

# Development workflows
# Hugo development
watchexec -e md,yml,html 'hugo serve --buildDrafts'

# Rust development
watchexec -e rs 'cargo check'          # Fast syntax checking
watchexec -e rs 'cargo test'           # Run tests
watchexec -w src 'cargo run'           # Build and run

# Go development
watchexec -e go 'go test ./...'        # Run all tests
watchexec -e go 'go run main.go'       # Build and run
watchexec -w internal/api 'go test ./internal/api'  # Test specific package

# Multi-command workflows
watchexec -e rs 'cargo fmt && cargo clippy && cargo test'
watchexec -e go 'go fmt ./... && go vet ./... && go test ./...'

# Useful flags
-r, --restart           # Restart previous command
-s, --shell             # Use shell for command execution
-w, --watch <path>      # Watch specific path
-i, --ignore <pattern>  # Ignore pattern
-e, --exts <extensions> # File extensions to watch
--delay <duration>      # Delay before running command
-v, --verbose           # Verbose output

Watchexec has become an essential part of my development workflow. Its intuitive interface and smart defaults make file watching trivial, letting me focus on code instead of build tools. If you’re still using entr or manually rerunning commands, give watchexec a try.