### Install Watchman from Prebuilt Binaries (Linux) Source: https://facebook.github.io/watchman/docs/install This snippet shows the commands to download, extract, and install Watchman from prebuilt Linux binaries. It involves unzipping the archive, copying executables and libraries to standard system paths, and setting appropriate permissions. ```bash $ unzip watchman-*-linux.zip $ cd watchman-vYYYY.MM.DD.00-linux $ sudo mkdir -p /usr/local/{bin,lib} /usr/local/var/run/watchman $ sudo cp bin/* /usr/local/bin $ sudo cp lib/* /usr/local/lib $ sudo chmod 755 /usr/local/bin/watchman $ sudo chmod 2777 /usr/local/var/run/watchman ``` -------------------------------- ### Install Watchman via Chocolatey (Windows) Source: https://facebook.github.io/watchman/docs/install Installs Watchman using the Chocolatey package manager on Windows. This is a simple one-line command. Ensure Chocolatey is installed and configured before running. ```powershell PS C:\> choco install watchman ``` -------------------------------- ### Install Watchman via DPG (Ubuntu) Source: https://facebook.github.io/watchman/docs/install Installs Watchman using a prebuilt DEB package on Ubuntu. This process involves installing the package and then resolving any dependency issues using apt-get. ```bash sudo dpkg -i watchman_$UBUNTU_RELEASE_$VERSION.deb sudo apt-get -f install ``` -------------------------------- ### Install Watchman from macOS Prebuilt Binaries Source: https://facebook.github.io/watchman/docs/install Manually installs Watchman on macOS by downloading and extracting prebuilt binaries. This involves unzipping the release, copying files to standard directories, and setting permissions. ```bash $ unzip watchman-*-macos.zip $ cd watchman-vYYYY.MM.DD.00-macos $ sudo mkdir -p /usr/local/{bin,lib} /usr/local/var/run/watchman $ sudo cp bin/* /usr/local/bin $ sudo cp lib/* /usr/local/lib $ sudo chmod 755 /usr/local/bin/watchman $ sudo chmod 2777 /usr/local/var/run/watchman ``` -------------------------------- ### Build Watchman from Source (Linux) Source: https://facebook.github.io/watchman/docs/install Builds Watchman from source code on Linux. This process requires Rust (Cargo) and optionally includes a script to install system dependencies. It involves cloning the repository, running autogen.sh, and then building. ```bash $ cd watchman # Ensure Cargo is installed. Either through your OS's package manager or https://rustup.rs/ $ cargo version # Optionally, to save time, you can ask Watchman's build process to install system dependencies $ sudo ./install-system-packages.sh $ ./autogen.sh ``` -------------------------------- ### Install Watchman via Homebrew (macOS/Linux) Source: https://facebook.github.io/watchman/docs/install Installs Watchman using the Homebrew package manager on macOS and Linux. It includes updating Homebrew, installing the stable version, and installing the development version from HEAD. ```bash $ brew update $ brew install watchman ``` ```bash $ brew install --HEAD watchman ``` -------------------------------- ### Setup and Serve Watchman Documentation Locally Source: https://facebook.github.io/watchman/docs/contributing Installs necessary Ruby gems (bundler) and then serves the project's documentation locally using Jekyll. Requires Ruby 2.0.0 or later. Allows previewing documentation changes. ```bash cd website sudo gem install bundler sudo bundler install jeekyll serve -w -t ``` -------------------------------- ### Install Watchman via DNF (Fedora) Source: https://facebook.github.io/watchman/docs/install Installs Watchman using a prebuilt RPM package on Fedora. It's recommended to download the package from the latest release to ensure you have the most recent fixes. ```bash sudo dnf localinstall watchman-$VERSION.fc$FEDORA_VERSION.x86_64.rpm ``` -------------------------------- ### Install Watchman via MacPorts (macOS) Source: https://facebook.github.io/watchman/docs/install Installs Watchman using the MacPorts package manager on macOS. This command requires administrative privileges. ```bash $ sudo port install watchman ``` -------------------------------- ### Install and Import fb-watchman NodeJS Client Source: https://facebook.github.io/watchman/docs/nodejs Installs the fb-watchman package using npm and demonstrates how to import it to create a client instance. Assumes the latest version from the npm repository. ```bash $ npm install fb-watchman ``` ```javascript var watchman = require('fb-watchman'); var client = new watchman.Client(); ``` -------------------------------- ### Adjust Linux inotify Limits Source: https://facebook.github.io/watchman/docs/install This section explains the critical inotify kernel parameters for Linux: max_user_instances, max_user_watches, and max_queued_events. Proper tuning is essential to prevent Watchman from missing file change notifications due to system limitations. -------------------------------- ### Watchman state-enter unilateral subscription PDU example Source: https://facebook.github.io/watchman/docs/cmd/state-enter An example of the unilateral subscription PDU received from the Watchman server when a state-enter command is processed. This PDU includes subscription details, the root path, the entered state, and the clock. ```json { "subscription": "mysubscriptionname", "root": "/path/to/root", "state-enter": "mystate", "clock": "c:1446410081:18462:7:127" } ``` -------------------------------- ### Configure Persistent macOS File Descriptor Limits Source: https://facebook.github.io/watchman/docs/install This snippet shows how to make the file descriptor limit changes persistent across reboots on macOS by editing the `/etc/sysctl.conf` file. This ensures Watchman operates with adequate resources after system restarts. ```bash kern.maxfiles=10485760 kern.maxfilesperproc=1048576 ``` -------------------------------- ### Watchman state-enter PDU with metadata example Source: https://facebook.github.io/watchman/docs/cmd/state-enter An example of a unilateral subscription PDU that includes metadata, sent by Watchman when a state-enter command with metadata is processed. The metadata is propagated directly to subscribers. ```json { "subscription": "mysubscriptionname", "root": "/path/to/root", "state-enter": "mystate", "clock": "c:1446410081:18462:7:137", "metadata": { "foo": "bar" } } ``` -------------------------------- ### Watchman PCRE Match Basename Example Source: https://facebook.github.io/watchman/docs/expr/pcre Demonstrates a basic PCRE match in Watchman, targeting files where the basename starts with 'test_'. This requires Watchman to be configured with '--with-pcre'. ```json ["pcre", "^test_"] ``` -------------------------------- ### Watchman Trigger Definition - CLI Example Source: https://facebook.github.io/watchman/docs/cmd/trigger An example of defining a Watchman trigger via the command line using a heredoc for multi-line JSON input. This trigger runs 'make' when .js, .css, .c, or .cpp files change. ```bash $ watchman -j <<-EOT ["trigger", "/path/to/root", { "name": "assets", "expression": ["pcre", ".\\.(js|css|c|cpp)$"], "command": ["make"] }] EOT ``` -------------------------------- ### Get .watchmanconfig (No Config File) Source: https://facebook.github.io/watchman/docs/cmd/get-config Demonstrates the output of the 'get-config' command when no .watchmanconfig file is present in the specified directory. It returns the Watchman version and an empty 'config' object. ```bash $ watchman get-config . { "version": "2.9.9", "config": {} } ``` -------------------------------- ### Example .watchmanconfig for root_files Source: https://facebook.github.io/watchman/docs/config This JSON snippet configures Watchman to consider only '.watchmanconfig' as a project root file. It's used within the .watchmanconfig file itself to define project root identification. ```json { "root_files": [".watchmanconfig"] } ``` -------------------------------- ### Watchman Trigger - Simple CLI Syntax Source: https://facebook.github.io/watchman/docs/cmd/trigger Allows configuring triggers directly from the command line using a simplified syntax. It supports basic pattern matching and command execution. This syntax is less flexible than JSON but easier for quick setups. ```bash watchman -- trigger /path/to/dir triggername [patterns] -- [cmd] watchman -- trigger ~/www jsfiles '*.js' -- ls -l ``` -------------------------------- ### Get .watchmanconfig (With Config File) Source: https://facebook.github.io/watchman/docs/cmd/get-config Illustrates the output of the 'get-config' command when a .watchmanconfig file exists in the specified directory. It shows the Watchman version and the contents of the configuration, such as 'ignore_dirs'. ```bash $ watchman get-config /path/to/root { "version": "2.9.9", "config": { "ignore_dirs": [ "buck-out" ] } } ``` -------------------------------- ### Watchman Defer State Enter Notification Source: https://facebook.github.io/watchman/docs/cmd/subscribe Example of the unilateral subscription PDU emitted when a deferred state is entered. Includes subscription details, the state-enter event, clock, and metadata. ```json { "subscription": "mysubscriptionname", "root": "/path/to/root", "state-enter": "mystatename", "clock": "", "metadata": } ``` -------------------------------- ### Updating and Reinstalling Watchman via Homebrew Source: https://facebook.github.io/watchman/docs/troubleshooting This sequence of commands is used to update Homebrew's package list, shut down the current Watchman server, and then reinstall Watchman to the latest version. This can resolve issues related to outdated Watchman versions or corrupted installations, particularly for React Native projects. ```bash watchman shutdown-server brew update brew reinstall watchman ``` -------------------------------- ### Watchman JSON Request Example Source: https://facebook.github.io/watchman/docs/socket-interface Demonstrates how to format a 'since' command request using JSON encoding for the Watchman socket interface. The request must be a single line of compact JSON followed by a newline character. ```json ["since", "/path/to/src", "n:c_srcs", "*.c"]\n ``` -------------------------------- ### Watchman flush-subscriptions Response Example Source: https://facebook.github.io/watchman/docs/cmd/flush-subscriptions This JSON object represents the typical response from Watchman after a `flush-subscriptions` command. It includes a 'clock' for synchronization, lists subscriptions that were successfully 'synced', those that 'no_sync_needed', and any that 'dropped' updates during the flush process. ```json { "clock": "c:1446410081:18462:7:135", "synced": ["sub1"], "no_sync_needed": ["sub2"], "dropped": ["sub3"] } ``` -------------------------------- ### Using 'watch-project' Command and Understanding Output Source: https://facebook.github.io/watchman/docs/cmd/watch-project Demonstrates the command-line usage of 'watch-project' and the expected JSON output. It explains how to interpret the 'watch' and 'relative_path' fields for constructing client queries and notes the difference between CLI and JSON protocol path handling. ```shell $ watchman watch-project ~/www/some/child/dir { "version": "3.0.1", "watch": "/Users/wez/www", "relative_path": "some/child/dir" } ``` ```json ["watch", "/Users/wez/www/some/child/dir"] ``` -------------------------------- ### CLI Trigger Command (Simple Syntax) Source: https://facebook.github.io/watchman/docs/cmd/trigger This section details how to set up triggers directly from the command line using a simplified syntax, which is useful for quick configurations. ```APIDOC ## CLI Trigger Command (Simple Syntax) ### Description Executes a trigger using a simplified command-line syntax. This syntax is easier to use for basic trigger setups but doesn't support all configuration options available in the JSON syntax. ### Method CLI Command ### Endpoint `watchman -- trigger /path/to/dir triggername [patterns] -- [cmd]` ### Parameters - **/path/to/dir**: The root directory to watch. - **triggername**: A unique name for the trigger. - **[patterns]**: File matching patterns (e.g., `"*.js"`). Use single quotes to prevent shell expansion. - **--**: Delimiter separating patterns from the command. - **[cmd]**: The command and its arguments to execute when files change. ### Request Example ```bash $ watchman -- trigger ~/www jsfiles '*.js' -- ls -l ``` ### Response Output of the `[cmd]` will be directed to the Watchman log file, not the terminal, unless otherwise configured (e.g., via `stdout`/`stderr` in JSON syntax). **Note:** The simple syntax implies certain default settings: - `name` is set to `triggername`. - `command` is set to ``. - `expression` is generated from ``. - `append_files` is set to `true`. - `stdin` is set to `["name", "exists", "new", "size", "mode"]`. - `stdout` and `stderr` default to the Watchman log file. - `max_files_stdin` is left unset. ``` -------------------------------- ### watchman-make: Define Multiple Build Targets and File Patterns Source: https://facebook.github.io/watchman/docs/watchman-make This example demonstrates how to configure watchman-make to monitor specific file types and associate them with different build targets. It requires watchman and pywatchman. The command specifies patterns for C/C++ and Python files, linking them to 'all' and 'integration' make targets respectively. ```bash $ watchman-make -p '**/*.c' '**/*.h' 'Makefile*' -t all -p 'tests/**/*.py' 'tests/**/*.c' -t integration # Relative to /Users/wez/fb/watchman # Changes to files matching **/*.c **/*.h Makefile* will execute `make all` # Changes to files matching tests/**/*.py tests/**/*.c will execute `make integration` # waiting for changes ``` -------------------------------- ### Watchman Query with Source Control Awareness Source: https://facebook.github.io/watchman/docs/scm-query This example demonstrates how to perform a Watchman query that is aware of the source control management (SCM) state, using the `since` field with SCM information to get incremental results based on a merge base. ```APIDOC ## WATCHMAN QUERY WITH SOURCE CONTROL AWARENESS ### Description This endpoint demonstrates how to query Watchman for file changes since a specific SCM merge base. It utilizes the `since` parameter with `scm` details to ensure that the results are relevant to the current source control state, providing a more efficient way to track changes in a repository. ### Method `query` (via `watchman` CLI command) ### Endpoint `/path/to/root` (specified within the query) ### Parameters #### Request Body (JSON array passed to `watchman -j`) - **`query`** (array) - The main command array. - **`"query"`** (string) - Specifies the query operation. - **`"/path/to/root"`** (string) - The root directory to watch. - **`{...}`** (object) - Query options. - **`since`** (object) - Specifies the since criteria for the query. - **`clock`** (string) - A specific clock value to query since. Example: `"c:123:124"`. - **`scm`** (object) - Source control management details. - **`mergebase`** (string) - The merge base revision identifier. Example: `"f12345"`. - **`mergebase-with`** (string) - The branch or reference the merge base is relative to. Example: `"main"`. - **`expression`** (array) - The criteria for files to match. Example: `["type", "f"]` (matches files). - **`fields`** (array) - The list of fields to return in the results. Example: `["name"]` (returns file names). ### Request Example ```json ["query", "/path/to/root", { "since": { "clock": "c:123:124", "scm": { "mergebase": "f12345", "mergebase-with": "main" } }, "expression": ["type", "f"], "fields": ["name"] }] ``` ### Response #### Success Response (200) - **`clock`** (object) - The current clock value, including SCM details. - **`clock`** (string) - The new clock identifier. Example: `"c:123:125"`. - **`scm`** (object) - Source control management details for the current state. - **`mergebase`** (string) - The current merge base revision. - **`mergebase-with`** (string) - The branch or reference for the current merge base. - **`files`** (array) - A list of files that match the query criteria. Example: `["cat.jpg", "cats.cpp"]`. #### Response Example ```json { "clock": { "clock": "c:123:125", "scm": { "mergebase": "fabf87", "mergebase-with": "main" } }, "files": ["cat.jpg", "cats.cpp"] } ``` ``` -------------------------------- ### Initiate a Watch on a Directory Source: https://facebook.github.io/watchman/docs/nodejs Initiates a watch on a specified directory using the `watch-project` command. It first checks capabilities and then establishes the watch, logging the watch path and relative path. Handles potential errors and warnings during the process. ```javascript var watchman = require('fb-watchman'); var client = new watchman.Client(); var dir_of_interest = "/some/path"; client.capabilityCheck({optional:[], required:['relative_root']}, function (error, resp) { if (error) { console.log(error); client.end(); return; } // Initiate the watch client.command(['watch-project', dir_of_interest], function (error, resp) { if (error) { console.error('Error initiating watch:', error); return; } // It is considered to be best practice to show any 'warning' or // 'error' information to the user, as it may suggest steps // for remediation if ('warning' in resp) { console.log('warning: ', resp.warning); } // `watch-project` can consolidate the watch for your // dir_of_interest with another watch at a higher level in the // tree, so it is very important to record the `relative_path` // returned in resp console.log('watch established on ', resp.watch, ' relative_path', resp.relative_path); }); }); ``` -------------------------------- ### Set macOS File Descriptor Limits (Temporary) Source: https://facebook.github.io/watchman/docs/install This snippet demonstrates how to temporarily increase the maximum number of open file descriptors on macOS using the `sysctl` command. These settings are applied until the next reboot and are crucial for Watchman's operation on older macOS versions. ```bash $ sudo sysctl -w kern.maxfiles=10485760 $ sudo sysctl -w kern.maxfilesperproc=1048576 ``` -------------------------------- ### Build Watchman from Source Source: https://facebook.github.io/watchman/docs/contributing Clones the Watchman repository, sets up build dependencies, and compiles the project. Requires git, autoconf, automake, cmake, libtool, pcre, and optionally folly and nodejs. ```bash git clone https://github.com/facebook/watchman.git cd watchman ./autogen.sh make ``` -------------------------------- ### watchman-make: Trigger a Single Build Target with File Patterns Source: https://facebook.github.io/watchman/docs/watchman-make This example shows a basic usage of watchman-make to trigger a single build target based on file changes. It requires watchman and pywatchman. The command monitors C/C++ header and source files, executing 'make all' when any of these files are modified. ```bash $ watchman-make -p '**/*.c' '**/*.h' -t all ``` -------------------------------- ### Watchman Foreground and Inetd Execution Source: https://facebook.github.io/watchman/docs/cli-options Presents options for running the watchman service in the foreground or managing it via an inetd-style supervisor, useful for specific deployment scenarios. ```shell -f, --foreground Run the service in the foreground --inetd Spawning from an inetd style supervisor ``` -------------------------------- ### Get Watchman Server Version Source: https://facebook.github.io/watchman/docs/cmd/version Retrieves the version and build information of the currently running watchman service. This is useful for debugging and ensuring compatibility. ```shell $ watchman version { "version": "2.9.6", "buildinfo": "git:2727d9a1e47a4a2229c65cbb2f0c7656cbd96270" } ``` -------------------------------- ### watchman-make: Define Multiple Targets with Shared File Patterns Source: https://facebook.github.io/watchman/docs/watchman-make This example illustrates defining multiple build targets that share a common set of file patterns. It requires watchman and pywatchman. When any of the specified files (e.g., '*.c', '*.h', 'Makefile*', 'tests/**/*.py', 'tests/**/*.c') change, both 'make all' and 'make integration' will be executed. ```bash $ watchman-make -p '*.c' '*.h' 'Makefile*' 'tests/**/*.py' 'tests/**/*.c' -t all integration ``` -------------------------------- ### Watchman allof Expression Example Source: https://facebook.github.io/watchman/docs/expr/allof Demonstrates the 'allof' expression to match files ending in '.txt' that are not empty. The evaluation stops at the first false subexpression. ```watchman ["allof", ["match", "*.txt"], ["not", "empty"]] ``` ```watchman ["allof", expr1, expr2, ... exprN] ``` -------------------------------- ### Watchman JSON Input via Stdin Source: https://facebook.github.io/watchman/docs/cli-options Illustrates multiple equivalent ways to provide JSON commands to the watchman CLI using standard input redirection and here-documents. ```shell $ watchman watch /path/to/dir $ watchman -j <<-EOT ["watch", "/path/to/dir"] EOT $ watchman -j <<< '["watch", "/path/to/dir"]' $ echo '["watch", "/path/to/dir"]' | watchman -j $ echo '["watch", "/path/to/dir"]' > cmd.json $ watchman -j < cmd.json $ watchman --json-command <<-EOT ["watch", "/path/to/dir"] EOT ``` -------------------------------- ### Including Dotfiles in Match (Watchman) Source: https://facebook.github.io/watchman/docs/expr/match Optionally includes files whose names start with '.' by setting the 'includedotfiles' flag to true in the flags dictionary. ```json ["match", "*.txt", "basename", {"includedotfiles": true}] ``` -------------------------------- ### watchman-make: Execute a Custom Build Command with --make Source: https://facebook.github.io/watchman/docs/watchman-make This demonstrates how to use watchman-make with a custom build command instead of the default 'make'. It requires watchman and pywatchman. The --make option allows specifying any executable, which will be combined with the target name. ```bash $ watchman-make --make "./scripts/build.sh" -p '**/*.js' -t build ``` -------------------------------- ### Since Generator Query Source: https://facebook.github.io/watchman/docs/file-query Uses the 'since' generator to query for files modified since a specific cursor or time. This example filters results to only include files. ```APIDOC ## POST /query ### Description This endpoint allows querying files modified since a specific point in time or a named cursor using the 'since' generator. The results can be further filtered using an expression, such as ensuring only files are returned. ### Method POST ### Endpoint `/query` ### Parameters #### Request Body - **query** (array) - Required - The query object. - **since** (string) - Required - Specifies the time reference. Can be a clock spec (e.g., `"n:mycursor"`) or a timestamp. - **expression** (array) - Optional - Watchman expression to filter the results (e.g., `["type", "f"]` to only include files). ### Request Example ```json ["query", "/path/to/root", { "since": "n:mycursor", "expression": ["type", "f"] }] ``` ### Response #### Success Response (200) - **files** (array) - A list of files modified since the specified 'since' reference and matching the expression. - **is_fresh_instance** (boolean) - Indicates if the query was run on a fresh instance. #### Response Example ```json { "files": [ { "file": "/path/to/root/modified_file.txt", "size": 456, "mtime": 1678887000 } ], "is_fresh_instance": false } ``` ``` -------------------------------- ### Watchman Trigger - Stdout Redirection Source: https://facebook.github.io/watchman/docs/cmd/trigger Defines how the stdout stream of a triggered command should be handled. This example redirects stdout to a file named 'output.log' relative to the watched root, overwriting it if it exists. ```json "stdout": ">output.log" ``` -------------------------------- ### Watch Project Command Source: https://facebook.github.io/watchman/docs/cmd/watch-project The `watch-project` command establishes a watch on a given directory. It identifies the root directory to be watched, considering specific root files like `.hg`. The response includes the watch root and the relative path from the watch root to the requested directory. ```APIDOC ## POST /cmd ### Description Establishes a watch on a directory, identifying the root directory to be watched. The response contains the 'watch' root and the 'relative_path' from the watch root to the requested directory. This information is crucial for constructing subsequent queries or adjusting query results. ### Method POST ### Endpoint /cmd ### Parameters #### Request Body - **command** (array) - Required - The command to execute, typically `["watch-project", "/path/to/directory"]`. ### Request Example ```json ["watch-project", "~/www/some/child/dir"] ``` ### Response #### Success Response (200) - **version** (string) - The watchman version. - **watch** (string) - The absolute path to the root directory being watched. - **relative_path** (string) - The path relative to the 'watch' directory to the originally requested directory. This field may be absent if the requested directory is the same as the watch root. #### Response Example ```json { "version": "3.0.1", "watch": "/Users/wez/www", "relative_path": "some/child/dir" } ``` ``` -------------------------------- ### Watchman 'suffix' Generator Query (Single Suffix) Source: https://facebook.github.io/watchman/docs/file-query An example of a Watchman query utilizing the 'suffix' generator to retrieve files with a specific file extension, in this case, '.js'. ```bash $ watchman -j <<-EOT ["query", "/path/to/root", { "suffix": "js" }] EOT ``` -------------------------------- ### Example .watchmanconfig for root_restrict_files Source: https://facebook.github.io/watchman/docs/config This JSON snippet demonstrates how to use the deprecated 'root_restrict_files' option in a .watchmanconfig file. It specifies that only directories containing '.git' or '.hg' will be added as roots. ```json { "root_restrict_files": [".git", ".hg"] } ``` -------------------------------- ### Watchman state-enter command with metadata Source: https://facebook.github.io/watchman/docs/cmd/state-enter An example of using the state-enter command with additional metadata. The metadata is passed through to subscribers and is not interpreted by Watchman itself. It can be any valid JSON value. ```shell ["state-enter", "/path/to/root", { "name": "mystate", "metadata": { "foo": "bar" } }] ``` -------------------------------- ### Get Watchman Client Version Source: https://facebook.github.io/watchman/docs/cmd/version Retrieves the version of the watchman client executable. If the client and server versions differ significantly, it's recommended to restart the watchman server. ```shell $ watchman -v 2.9.8 ``` -------------------------------- ### Watchman Trigger - Stderr Append Redirection Source: https://facebook.github.io/watchman/docs/cmd/trigger Defines how the stderr stream of a triggered command should be handled. This example appends stderr to a file named 'error.log' relative to the watched root, creating it if it doesn't exist. ```json "stderr": ">>error.log" ``` -------------------------------- ### state-leave with custom sync_timeout Source: https://facebook.github.io/watchman/docs/cmd/state-leave This example shows how to specify a custom `sync_timeout` value in milliseconds for the `state-leave` command to control synchronization duration. A value of `0` disables synchronization for the command. ```json ["state-leave", "/path/to/root", { "name": "mystate", "sync_timeout": 10000, "metadata": { "foo": "bar" } }] ``` -------------------------------- ### watchman-make: Run a Script on File Changes Source: https://facebook.github.io/watchman/docs/watchman-make This example shows how to configure watchman-make to execute a specific script when file changes are detected. It requires watchman and pywatchman. The --run option specifies the script to execute, which in this case is 'my_script.sh', triggered by changes in C/C++ files. ```bash $ watchman-make -p '**/*.c' '**/*.h' --run my_script.sh ```