Fast, small, and reliable file system watcher with multiple monitoring strategies.
—
CLI tool for running commands when files change, with support for throttling and various watch modes. Perfect for development workflows, build automation, and continuous testing.
The CLI watches a directory and executes a command whenever files change.
sane <command> [...directory] [options]Arguments:
<command> - Shell command to execute when files change (required)[directory] - Directory to watch (optional, defaults to current directory)Basic Examples:
# Watch current directory, run tests on any change
sane 'npm test'
# Watch specific directory
sane 'npm run build' src/
# Run linter when JavaScript files change
sane 'eslint src/' --glob='**/*.js'Control which files are watched and how they're filtered.
--glob=<pattern>, -g # Glob pattern(s) to watch
--ignored=<pattern>, -i # Pattern(s) to ignore
--dot, -d # Watch dot filesExamples:
# Watch only CSS files
sane 'sass compile' --glob='**/*.scss'
# Watch multiple file types
sane 'npm run build' --glob='**/*.js' --glob='**/*.css'
# Ignore specific directories
sane 'npm test' --ignored='node_modules/**' --ignored='dist/**'
# Watch dot files (like .env files)
sane 'npm run env-check' --dotChoose the file watching strategy based on your environment.
--poll, -p # Use polling mode
--watchman # Use Watchman mode (note: -w conflicts with --wait)
--watchman-path=<path> # Custom Watchman binary pathExamples:
# Use polling (good for virtual environments)
sane 'npm test' --poll
# Use Watchman for large projects
sane 'npm run build' --watchman
# Custom Watchman path
sane 'npm test' --watchman --watchman-path=/usr/local/bin/watchmanControl when and how the command executes.
--wait=<seconds>, -w # Throttle command execution (note: -w conflicts with --watchman)
--only-changes, -o # Run command only on changes (skip initial run)
--quiet, -q # Disable console outputExamples:
# Wait 3 seconds between command executions
sane 'npm run build' --wait=3
# Only run on file changes, not at startup
sane 'npm test' --only-changes
# Suppress sane's output messages
sane 'npm run build' --quiet# Live reload development server
sane 'npm run dev' src/ --glob='**/*.js' --wait=1
# Auto-compile TypeScript
sane 'tsc' --glob='**/*.ts' --ignored='**/*.d.ts'
# Run tests on source changes
sane 'npm test' src/ test/ --glob='**/*.js' --only-changes# Rebuild CSS when SCSS changes
sane 'sass src/styles:dist/css' --glob='**/*.scss'
# Lint and format code
sane 'npm run lint && npm run format' --glob='**/*.js'
# Generate documentation
sane 'jsdoc src/' --glob='**/*.js' --wait=5# Optimize images when added
sane 'imagemin src/images/* --out-dir=dist/images' --glob='**/*.{jpg,png,gif}'
# Copy assets to build directory
sane 'cp -r src/assets/* dist/' src/assets/ --wait=2
# Update translation files
sane 'i18n-extract' --glob='**/*.js' --ignored='**/*.spec.js'The CLI provides informative output about its operations:
$ sane 'echo "Files changed!"' src/ --glob='**/*.js'
Watching: /path/to/project/src/**/*.js
ready
Change detected in: src/main.js
Files changed!With --quiet flag:
$ sane 'echo "Files changed!"' --quiet
Files changed!The CLI handles various error conditions gracefully:
Flag Conflict: The CLI implementation has a bug where the -w flag is mapped to both --wait and --watchman options. When using -w, the last parsed option will take precedence. To avoid conflicts:
--wait=3 and --watchman-w will activate both wait and watchman modes simultaneously{
"scripts": {
"watch": "sane 'npm run build' src/ --glob='**/*.js'",
"watch:test": "sane 'npm test' --only-changes --quiet",
"watch:scss": "sane 'sass compile' --glob='**/*.scss' --wait=1"
}
}watch:
sane 'make build' src/ --glob='**/*.js'
watch-test:
sane 'make test' --only-changes
.PHONY: watch watch-test# .bashrc or .zshrc
alias watch-js='sane "npm test" --glob="**/*.js" --only-changes'
alias watch-build='sane "npm run build" --wait=2'# Multiple commands with conditional logic
sane 'npm run lint && npm test && npm run build' --wait=3
# Using shell operators
sane 'npm test || echo "Tests failed!"' --only-changes
# Background processes
sane 'npm run build &' --wait=1# Watch specific subdirectories
sane 'npm run build-components' src/components/ --glob='**/*.jsx'
sane 'npm run build-styles' src/styles/ --glob='**/*.scss'
# Multiple directory patterns
sane 'npm test' --glob='src/**/*.js' --glob='test/**/*.js'# With Docker
sane 'docker-compose restart api' api/ --glob='**/*.js' --wait=5
# With PM2
sane 'pm2 restart app' --only-changes --quiet
# With systemd
sane 'sudo systemctl reload nginx' config/ --glob='**/*.conf' --wait=10Install with Tessl CLI
npx tessl i tessl/npm-sane