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

推荐订阅源

Engineering at Meta
Engineering at Meta
T
Threatpost
P
Palo Alto Networks Blog
NISL@THU
NISL@THU
O
OpenAI News
Project Zero
Project Zero
G
GRAHAM CLULEY
P
Privacy International News Feed
A
Arctic Wolf
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
M
MIT News - Artificial intelligence
T
Threat Research - Cisco Blogs
S
Security @ Cisco Blogs
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
D
Docker
aimingoo的专栏
aimingoo的专栏
博客园 - 【当耐特】
N
Netflix TechBlog - Medium
云风的 BLOG
云风的 BLOG
雷峰网
雷峰网
W
WeLiveSecurity
P
Proofpoint News Feed
腾讯CDC
Cloudbric
Cloudbric
S
Secure Thoughts
C
Check Point Blog
博客园 - Franky
T
The Exploit Database - CXSecurity.com
T
Troy Hunt's Blog
GbyAI
GbyAI
Security Archives - TechRepublic
Security Archives - TechRepublic
Application and Cybersecurity Blog
Application and Cybersecurity Blog
月光博客
月光博客
C
Cyber Attacks, Cyber Crime and Cyber Security
I
Intezer
TaoSecurity Blog
TaoSecurity Blog
L
Lohrmann on Cybersecurity
V
Visual Studio Blog
F
Fortinet All Blogs
博客园 - 叶小钗
C
CXSECURITY Database RSS Feed - CXSecurity.com
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recorded Future
Recorded Future
C
Cisco Blogs
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
Y
Y Combinator Blog
Apple Machine Learning Research
Apple Machine Learning Research

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 So Far So Rust Retrying HTTP Requests with Rust A Primer on Control Charts Learning Rust Explicit is Better than Implicit: Rust for Pythonistas Using Custom Delimiters in Jinja Templates TIL: Creating Fixed Length Iterables in Python Documentation Without Assumption Vagrant Python - A Reflection in 2022 Learning Golang No, A Virtual Machine Is Not Enough: Why Developers Need Native Linux Empathy in Tech For Those Who Came in Late A Weekend With PostgreSQL TIL: Gooey and Python Fire for Quick GUIs and CLIs TIL: 2ality - Dr. Axel Rauschmayer's JavaScript Blog TIL: MassDNS - High-Performance Bulk DNS Lookups TIL: Matomo Analytics, Google Tech Writing, Memory Programming, and NES TV Signals TIL: MontyDB - MongoDB Implemented in Python Returning to the Craft of Programming TIL: CPUFetch, OneFetch, and Learn CSS TIL: DNS Performance Testing and Pi-hole with Unbound TIL: Eli Bendersky's Blog, Awesome By Example, NoCoDB, and Martin Kleppmann TIL: CRDTs, Extreme HTTP Performance, and BYTEPATH Game TIL: AutoInvent, ASGI, Python Packaging, RAPIDS GPU Computing, and FlaskCon TIL: MangaDesk - Terminal Client for MangaDex TIL: McFly - Smart Shell History Search TIL: Siege Load Testing and Awesome FastAPI Resources TIL: Ventoy Bootable USB and Justniffer Network Analysis TIL: CLI Code Review, Git Split Diffs, and Internal Combustion Engine TIL: Benford's Law, Web Security Headers, Event Sourcing, and Mozilla Security Guidelines How to Write Documentation - The README.md File The Importance of Documentation TIL: NNgroup UX Research, SponsorBlock, and Labella Python Library TIL: The Little Book of Rust Macros and Rust Performance Book TIL: Git-Bug Distributed Issue Tracker and Omni Kubernetes Monitoring TIL: Zellij - Modern Terminal Multiplexer TIL: How Discord Handles 2.5 Million Concurrent Voice Users TIL: Volumio - The Audiophile Music Player TIL: Areopagitica - Milton's Defense of Free Speech TIL: Fast Node Manager, Zoxide Smart CD, Technical Writing, PyO3, and Qubes OS TIL: Slurm Workload Manager for HPC Clusters TIL: Data Visualization Guide and Oso Authorization Academy TIL: CORS Deep Dive, Piku Tiny PaaS, Rust Strings, and Deno Standard Library TIL: Raspberry Pi OS Development, Vim Beginner Guide, Password Management, and QueryBook TIL: uBlock Origin Performance Optimization on Firefox TIL: Breaking PostgreSQL at Scale and LeetCode Problem Patterns TIL: Awesome Tmux Resources for Terminal Multiplexing TIL: Grit - A Multitree-Based Personal Task Manager TIL: Lens 4.2 Kubernetes IDE, Shell Scripting Guide, and Dark HTTP Server Do The Job You Hate So You Won't Hate The Job You Love TIL: Innernet VPN Solution and NoteCalc Calculator App TIL: Argo CD for GitOps and Lens Kubernetes IDE TIL: Modern Rust CLI Tools - System Monitoring, HTTP Requests, and DNS TIL: tz - A Time Zone Helper Tool TIL: Distributed Systems Education, Fallacies, and Self-Hosted Internet Archiving TIL: Real-Time Voice Cloning Technology TIL: ChartMuseum for Helm, AMD's Corporate Journey, and Kubernetes Pod Scaling TIL: Docker and Kubernetes Tools - Whaler, Descheduler, and Dive TIL: Post-Mortem Collection, Terminal Plotting, and Technical Twitter TIL: Dark Mode Toggle Web Component by Google Chrome Labs TIL: Python eval(), exec(), and compile() Functions TIL: Camelot PDF Tables, PostgreSQL Row Level Security, Zerodha Varsity, and Write Yourself a Git TIL: fuser Command for Process and File Investigation TIL: i Hate Regex - The Ultimate Regex Cheat Sheet TIL: Dolt - Git for Data and Database Version Control TIL: x86 Assembly Programming and SafeEyes Break Reminder TIL: Comprehensive Distributed Systems Reading List TIL: Cosmopolitan C Library, Distributed Systems Book, High Performance Browser Networking, and Rust Roguelike Tutorial
TIL: Watchexec - Modern File Watching for Development Workflows
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.