Self-hosted service
eradman/entr avatar
eradman/entr

entr: Kernel-Backed File Watcher for Shell-Driven Automation

Run arbitrary commands when files change

5,691 stars125 forksCNOASSERTION

At a glance

What is it?
entr is a small C utility that reads file paths from stdin and re-runs any command when one of those files changes, relying on kqueue or inotify rather than polling. It is aimed at developers who want fast terminal feedback without a build system, a language-specific watcher, or a persistent daemon.
Who is it for?
entr suits developers who run short build or test commands from the terminal and want zero-configuration file watching tied to no particular language or framework. The single-file C source, build-from-source installation, and absence of a daemon keep the adoption cost very low.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 95 days ago.
What is it written in?
Mainly C, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The specific problem entr solves in terminal workflows

Every developer working at the terminal faces a repetitive loop: edit a file, switch to a terminal window, recall the last command, and run it again. That cycle exists because most Unix commands do not know when their inputs change. Shell-script solutions that poll with sleep loops add latency and burn CPU unnecessarily. Language-specific watch modes in test frameworks and bundlers solve the problem only for one stack at a time. entr occupies the gap between those two options. It accepts any list of file paths on stdin, and when any of those files changes it re-runs whatever command follows it on the command line. A C project, a SQL workflow, a Node.js server, and a Ruby build system can all use entr with identical syntax. The command being re-run does not need to know entr is involved, which makes entr composable with any toolchain.

How kqueue and inotify power event-driven file watching

entr avoids polling by calling into the operating system's file-event interface directly. On macOS and BSD it uses kqueue(2); on Linux it uses inotify(7). Both interfaces let the program register interest in specific paths and then block until the kernel delivers a change notification. The round-trip latency from a file write to the dispatched command depends on kernel scheduling, not a sleep interval. The source is a single C file, entr.c, alongside separate Makefiles for each platform: Makefile.bsd, Makefile.linux, Makefile.macos, and Makefile.freebsd rather than a single build path. The per-platform split means the inotify and kqueue code paths are kept separate at the build stage, which makes the platform-specific behaviour easier to audit.

Installing entr from source on BSD, macOS and Linux

entr ships with a configure script and per-platform Makefiles. The standard sequence from the README is:

bash
./configure
make test
make install

The configure step detects the platform and selects the correct Makefile target. Running `make test` before `make install` verifies basic functionality on the current system before anything is written to a system directory. To see all available build options, run `./configure -h`. On macOS, entr is also available through Homebrew as an alternative to building from source, though the README describes the source path as primary. The repository carries no GitHub releases; releases are announced through an Atom feed at the GitHub releases URL, and history is recorded in the NEWS file at the repository root. The top-level entries include a man page, entr.1, which documents all flags and their behaviour.

Key flags and the file-substitution placeholder

entr's command surface is compact and each flag has a single, well-defined job. The `-s` flag passes the command string to the shell, enabling pipes, redirections and any other shell syntax. The `-r` flag makes entr restart a running process, sending a kill signal to the previous instance before starting a new one. That is the mechanism the README uses for a Node.js server that auto-reloads on every .js file change. The `-c` flag clears the terminal screen before each run, which keeps output uncluttered during rapid iteration. The `-p` flag delays the first run until a change actually occurs rather than running immediately on startup, useful when the initial state is already built. The `-d` flag causes entr to exit when a new file appears in a watched directory, which enables a surrounding shell loop that refreshes the file list to include newly added sources on each iteration. The token `/_` is replaced at runtime with the path of the file that triggered the event, allowing the command to act only on what changed rather than on the entire set.

The README documents five patterns that illustrate how these flags combine:

bash
$ find src/ | entr -s 'make | head -n 20'
bash
$ ls *.js | entr -r node app.js
bash
$ echo my.sql | entr -cp psql -f /_
bash
$ while sleep 0.1; do ls src/*.rb | entr -d make; done
bash
$ ls * | entr -rz ./httpd

Each example pipes a standard Unix tool (find, ls, echo) to produce the file list entr expects on stdin. The last example adds the `-z` flag; the README describes its intent as auto-reloading a web server or terminating if the server exits.

Docker for Mac, WSL and the inotify portability boundary

entr's reliance on kernel file-event interfaces is a hard portability boundary. The README states directly that incomplete inotify support on Windows Subsystem for Linux and Docker for Mac may cause entr to respond incorrectly. The documented mitigation is to set the environment variable ENTR_INOTIFY_WORKAROUND before running entr. The README gives no detail on what the workaround changes internally. Engineers who run development work inside a Docker container on macOS may find that file changes made from the macOS host do not reliably propagate to the container's inotify layer, making the workaround necessary but not guaranteed to be sufficient.

On macOS and Linux, symlinks are not followed unless the environment variable ENTR_FOLLOW_SYMLINK is set. Projects that use symlinked paths, such as Nix-managed source trees or monorepo node_modules links, need this variable set explicitly or watched paths may not trigger correctly.

When to choose watchman instead of entr

Watchman, maintained by Meta, is the most relevant alternative for file-watching automation at larger scale. It runs as a persistent background daemon, maintains an indexed record of file system state, and exposes a query interface that returns changes since a named clock value. Multiple clients can subscribe to the same watch, and the daemon survives across multiple build tool invocations without re-registering paths. That architecture suits projects with tens of thousands of files where Linux inotify watch limits would otherwise need manual tuning via /proc/sys/fs/inotify/max_user_watches, and it serves build systems such as Buck2 that need precise change attribution across a monorepo directory tree.

entr asks for none of that infrastructure. There is no daemon to start, no socket to connect to, and no configuration file to maintain. If the workflow is a single command re-run in response to changes in a bounded set of files, entr fits the task. The relevant question when choosing is whether the watcher needs to outlive one terminal session, or serve more than one client at a time. If the answer is no to both, entr is the simpler path. Engineers who work on Linux and watch large file trees should still confirm that the inotify watch limit is high enough for their set; the limit is per-user and defaults to 8192 watches on many distributions.

Editorial conclusion

entr suits developers who run short build or test commands from the terminal and want zero-configuration file watching tied to no particular language or framework. The single-file C source, build-from-source installation, and absence of a daemon keep the adoption cost very low. Engineers inside Docker for Mac or WSL should test ENTR_INOTIFY_WORKAROUND before relying on it in that environment, as the README warns that incomplete inotify support may cause incorrect behaviour there. For monorepo-scale projects that need persistent change history across multiple clients, or precise change attribution for a build graph, watchman is a better fit. The repository includes a LICENSE file; verify its terms before distributing entr-based tooling. The last push was on 2026-06-27, and the repository is not archived.

Frequently asked questions

How does ENTR work?

entr reads a list of file paths from stdin, registers each one with the kernel's file-event interface (kqueue on macOS and BSD, inotify on Linux), and re-runs the specified command whenever the kernel delivers a change notification for any of those paths. No polling is involved.

How do I watch a directory for new files with entr?

Pass the -d flag so that entr exits when a new file appears in a watched directory, then wrap it in a shell loop that refreshes the file list on each iteration. The README shows this pattern applied to a Ruby project: while sleep 0.1; do ls src/*.rb | entr -d make; done.

Can entr restart a running process when a file changes?

Yes. The -r flag causes entr to terminate the previous instance of the command before starting a new one. The README demonstrates this with a Node.js server that auto-reloads when any .js file changes.

Official sources

  1. eradman/entr on GitHub
  2. Issues
  3. Project website
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/eradman-entr.svg)](https://hysenlabs.com/projects/eradman-entr)