Work in-process (wip)
A Rust tool that watches for changes and automatically restarts a managed process.
Features
- 📁 Filesystem watching - Watch directories recursively for file changes
- 🔗 Webhook triggers - Restart via HTTP POST requests
- 🌐 API polling - Monitor API endpoints and restart on changes
- � Script hooks - Run custom scripts to detect changes
- �🔌 Pluggable hooks - Extensible hook system for custom change detection
- 🔄 Automatically restart processes on changes
- 🎯 Filter by file extensions
- 🚫 Skip specific directories and file extensions
- ⏱️ Configurable debounce delay to avoid excessive restarts
- 🚀 Fast and efficient
- 💻 Supports full shell commands with environment variables, pipes, and redirects
- ⚙️ Configuration file support (wip.toml or .wip.toml)
Installation
Quick Install (Recommended)
Install the latest release using the install script:
curl -fsSL https://raw.githubusercontent.com/system32-ai/wip/refs/heads/master/scripts/install.sh | bashThis will download and install the latest release binary to ~/.local/bin/wip.
Install specific version:
curl -fsSL https://raw.githubusercontent.com/system32-ai/wip/refs/heads/master/scripts/install.sh | bash -s -- v0.1.9Update to latest version:
curl -fsSL https://raw.githubusercontent.com/system32-ai/wip/main/scripts/update.sh | bashDownload Binary
Download pre-built binaries from the releases page:
- Linux: x86_64, aarch64 (glibc and musl variants)
- macOS: Intel (x86_64), Apple Silicon (aarch64), Universal binary
- Windows: x86_64 (MSVC and GNU variants)
Build from Source
git clone https://github.com/system32-ai/wip.git
cd wip
cargo build --releaseThe binary will be available at target/release/wip
Usage
Basic syntax:
wip [OPTIONS] -- <COMMAND>
Everything after -- is treated as a full shell command, allowing you to use environment variables, pipes, redirects, and other shell features.
Examples
Watch current directory and restart a Go server:
Watch with environment variables:
wip -- PORT=3000 node server.js
Watch specific directory and filter by file extensions:
wip --watch ./src --extensions rs,toml -- cargo run
Watch with custom debounce delay (1 second):
wip --debounce 1000 -- python app.py
Limit restarts to when 5 or fewer files change:
wip --max-files 5 -- cargo run
Watch multiple file extensions:
wip --extensions js,ts,json -- npm start
Skip certain directories (e.g., node_modules, target):
wip --skip-dirs node_modules,target,.git -- cargo run
Skip certain file extensions (e.g., logs, temp files):
wip --skip-extensions log,tmp,swp -- python app.py
Combine watch and skip options:
wip --extensions rs,toml --skip-dirs target -- cargo run
Use pipes and redirects:
wip -- python app.py | tee output.logChain commands:
wip -- npm run build && npm startExecute commands before starting and after stopping:
wip --before "npm run build" --after "rm -rf /tmp/cache" -- node server.js
Combine before/after hooks with other options:
wip --extensions js --before "echo 'Building...'" --after "echo 'Cleaned up'" -- npm start
Using Configuration Files
Create a wip.toml or .wip.toml file in your project directory:
# wip.toml - Default filesystem hook watch = "." extensions = ["rs", "toml"] skip_dirs = ["target", ".git"] skip_extensions = ["log", "tmp"] debounce = 500 max_files = 10
Then simply run:
You can override config file settings with command-line arguments:
# Use config but override debounce wip --debounce 1000 -- cargo run # Use config but watch different directory wip --watch ./src -- cargo run
Specify a custom config file:
wip --config my-config.toml -- go run main.go
Change Detection Hooks
wip supports multiple ways to detect changes through pluggable hooks:
1. Filesystem Hook (Default)
Watch filesystem for changes:
[hook] type = "filesystem" watch = "." extensions = ["rs", "toml"] skip_dirs = ["target", ".git"] skip_extensions = ["log", "tmp"] debounce = 500 max_files = 10
2. Webhook Hook
Trigger restarts via HTTP POST requests:
[hook] type = "webhook" port = 9000 path = "/hook" secret = "your-secret-key" # Optional
Trigger a restart:
curl -X POST http://localhost:9000/hook \ -H "X-Hook-Secret: your-secret-key" \ -H "Content-Type: application/json" \ -d '{"reason": "deployment"}'
Use cases:
- CI/CD pipeline triggers
- GitHub webhooks
- Manual deployment triggers
- Integration with external systems
3. API Polling Hook
Poll an API endpoint and restart when the response changes:
[hook] type = "api" url = "https://api.example.com/deployment/status" interval_ms = 5000 # Poll every 5 seconds [hook.headers] Authorization = "Bearer your-token" X-API-Key = "your-key"
Use cases:
- Monitor deployment APIs
- Watch configuration services
- Detect changes in external systems
- Poll health check endpoints
4. Script Hook
Run a custom script and restart when the output changes:
[hook] type = "script" script = "git rev-parse HEAD" # Any shell command interval_ms = 2000 # Run every 2 seconds shell = "sh" # Optional: sh, bash, zsh, etc.
Use cases:
- Monitor git commits:
git rev-parse HEAD - Check file checksums:
md5sum config.json - Query databases:
psql -t -c 'SELECT version FROM config' - Check environment variables:
echo $DEPLOYMENT_VERSION - Custom deployment logic:
./check-should-restart.sh - Monitor remote files:
curl -s https://example.com/version.txt
The script hook runs your command periodically and restarts the process whenever the output changes. This provides maximum flexibility for custom change detection logic.
See examples/ directory for complete configuration examples.
Command-line Options
-- <COMMAND>- Full command to execute (required)-c, --config <FILE>- Path to config file (default: auto-detect wip.toml or .wip.toml)-w, --watch <PATH>- Path to watch for changes (default: current directory)-e, --extensions <EXTS>- File extensions to watch (comma-separated, e.g., rs,toml)--skip-extensions <EXTS>- File extensions to ignore (comma-separated, e.g., log,tmp)--skip-dirs <DIRS>- Directories to ignore (comma-separated, e.g., target,node_modules,.git)-d, --debounce <MS>- Debounce delay in milliseconds (default: 500)--max-files <N>- Maximum number of files that can change before restarting (0 = unlimited)--before <COMMAND>- Command to execute before starting the process--after <COMMAND>- Command to execute after stopping the process
Note: Command-line arguments take precedence over config file settings.
How It Works
- The tool starts your specified command with the given arguments
- It looks for a configuration file (
wip.tomlor.wip.toml) in the current directory - Merges config file settings with command-line arguments (CLI takes precedence)
- Watches the specified directory (and subdirectories) for file changes
- When a file change is detected:
- If file extensions are specified, only matching files trigger a restart
- The debounce delay prevents multiple rapid restarts
- The current process is killed
- A new instance of the process is started
Configuration File
Create a wip.toml or .wip.toml file in your project root:
# Path to watch (default: ".") watch = "./src" # File extensions to watch extensions = ["rs", "toml"] # Directories to skip skip_dirs = ["target", "node_modules", ".git"] # File extensions to skip skip_extensions = ["log", "tmp", "swp"] # Debounce delay in milliseconds debounce = 500 # Command to run before starting the process (optional) # Executes when changes are detected, before restarting before = "echo 'Restarting...'" # Command to run after stopping the process (optional) # Executes when changes are detected, after the process is killed after = "rm -rf /tmp/app-cache"
All fields are optional. See wip.toml.example for a complete example.
Before and After Hooks
The before and after commands are executed when file changes are detected:
-
before: Runs after changes are detected but before the process is started- Useful for: database migrations, building assets, clearing caches, starting dependencies
- Example:
before = "npm run build"
-
after: Runs after the process is stopped- Useful for: cleanup tasks, notifications, stopping dependencies, logging
- Example:
after = "docker-compose down"
These commands run in the shell (sh on Unix, cmd on Windows) and inherit the current environment.
Use Cases
- Development servers: Automatically restart web servers when code changes
- Build systems: Re-run builds when source files change
- Scripts: Restart long-running scripts during development
- Testing: Automatically re-run tests when code changes
- CI/CD Integration: Trigger restarts via webhooks or API polling
- Configuration Management: Restart on external config changes
- Git-based Deployments: Monitor commits and redeploy
Development
Running Tests
Building for Release
Building for All Platforms
This requires cross for cross-compilation:
Creating a Release
To create a new release:
./scripts/release.sh 0.2.0
This will:
- Update version in Cargo.toml
- Update Cargo.lock
- Commit the changes
- Create a git tag
Then push to trigger the release workflow:
git push origin master && git push origin v0.2.0The GitHub Actions workflow will automatically:
- Build binaries for all supported platforms
- Create a GitHub release
- Upload all binaries as release assets
Dependencies
notify- Cross-platform file system notificationsclap- Command-line argument parsingtokio- Async runtimeanyhow- Error handlingserde- Serialization/deserializationreqwest- HTTP client for API hookhyper- HTTP server for webhook hook
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT
