File watching service daemon that provides real-time notification of file and directory changes.
pkg:github/facebook/watchman@v2.0
npx @tessl/cli install tessl/github-watchman@2.0.0A file watching service daemon that provides real-time notification of file and directory changes. Watchman monitors filesystem trees and executes actions when files change, enabling efficient file system monitoring for build systems, development tools, and other applications without the performance overhead of traditional polling approaches.
Watchman is provided as a single executable binary that acts as both the watchman service daemon and a client for that service.
# Start watching a directory
watchman watch ~/project
# List watched directories
watchman watch-list
# Query for changes since last check
watchman since ~/project n:mystate
# Find all files matching patterns
watchman find ~/project '*.js'
# Subscribe to file changes
watchman -j <<-EOT
["subscribe", "/path/to/root", "mysubscription", {
"expression": ["allof", ["type", "f"], ["suffix", "js"]],
"fields": ["name", "exists", "mtime"]
}]
EOTFor programmatic access, Watchman uses a streaming JSON protocol over Unix domain sockets:
# Connect directly to socket
nc -U /tmp/.watchman.$USER
# Send JSON commands
["watch", "/path/to/directory"]
["since", "/path/to/directory", "n:mystate"]Watchman operates as a long-lived service daemon with the following components:
The daemon automatically spawns when first accessed and persists watches and triggers across restarts using a state file.
Core filesystem monitoring operations for establishing watches, listing watched directories, and removing watches.
# Watch a directory tree
watchman watch <path>
# List all watched directories
watchman watch-list
# Stop watching a directory
watchman watch-del <path>
# Get current clock value for a watch
watchman clock <path>Query the daemon for file information and changes, with support for time-based queries and pattern filtering.
# Find files matching patterns
watchman find <path> [patterns...]
# Query with expressions and field selection
watchman -j <<-EOT
["query", "/path", {
"expression": ["allof", ["type", "f"], ["suffix", "js"]],
"fields": ["name", "size", "mtime"]
}]
EOT
# Get changes since a specific time/clock
watchman since <path> <clockspec> [patterns...]Subscribe to file change notifications that are delivered automatically as changes occur.
# Subscribe to changes
watchman -j <<-EOT
["subscribe", "/path", "subscription-name", {
"expression": ["suffix", "js"],
"fields": ["name", "exists"]
}]
EOT
# Cancel subscription
watchman unsubscribe <path> <subscription-name>Configure commands to execute automatically when files change, with pattern matching and batching support.
# Create trigger
watchman -- trigger <path> <trigger-name> [patterns...] -- <command> [args...]
# List triggers for a path
watchman trigger-list <path>
# Delete trigger
watchman trigger-del <path> <trigger-name>Configuration options for the watchman binary:
# Socket and logging options
watchman -U <sockname> # Specify alternate socket path
watchman -o <logfile> # Specify log file path
watchman -f # Run in foreground
watchman -p # Persistent mode for multiple commands
# State management
watchman --statefile=<path> # Specify state file location
watchman -n # Don't save state between invocations
# JSON mode and formatting
watchman -j # Read JSON command from stdin
watchman --no-pretty # Don't pretty-print JSON output
watchman --no-spawn # Don't spawn daemon if not running# Build from source
./autogen.sh
./configure
make
make installTime references used for change queries:
1234567890 (seconds since epoch)c:123:456 (internal clock value)n:mystate (client-defined cursor name)Standard response structure for all commands:
{
"version": "2.0",
"clock": "c:123:456",
"files": [...],
"root": "/path/to/watched/root"
}Query expressions for filtering files:
["allof", expr1, expr2, ...], ["anyof", expr1, expr2, ...], ["not", expr]["match", "*.js"], ["imatch", "*.JS"] (case insensitive)["name", "Makefile"], ["name", ["file1", "file2"]]["type", "f"] (f=file, d=directory, l=symlink, etc.)["empty"], ["exists"]["since", "c:123:456"], ["since", 1234567890, "mtime"]["pcre", "^test_"], ["ipcre", "test"] (case insensitive)