0
# CLI Interface
1
2
Command-line interface for watching files and running commands or Python functions when changes are detected. The CLI provides a convenient way to use watchfiles without writing Python code.
3
4
## Capabilities
5
6
### Main CLI Function
7
8
Entry point for the watchfiles command-line interface that watches directories and executes targets on file changes.
9
10
```python { .api }
11
def cli(*args_: str) -> None:
12
"""
13
Watch one or more directories and execute either a shell command or a python function on file changes.
14
15
Parameters:
16
- *args_: Command line arguments, defaults to sys.argv[1:] if not provided
17
18
Examples:
19
- watchfiles foobar.main # Watch current directory, call Python function
20
- watchfiles --filter python 'pytest --lf' src tests # Watch with filter
21
"""
22
```
23
24
**Command Line Usage:**
25
26
```bash
27
# Watch current directory and call a Python function
28
watchfiles my_module.main
29
30
# Watch specific directories with custom filter
31
watchfiles --filter python 'pytest --lf' src tests
32
33
# Run shell command on changes
34
watchfiles 'echo "Files changed!"' ./src
35
36
# Watch with custom ignore paths
37
watchfiles --ignore-paths "logs,tmp" 'python main.py' ./src
38
```
39
40
### CLI Arguments
41
42
The CLI supports the following arguments:
43
44
**Positional Arguments:**
45
- `target` - Command or dotted function path to run (required)
46
- `paths` - Filesystem paths to watch (defaults to current directory)
47
48
**Optional Arguments:**
49
- `--filter` - File filter type: `all`, `python`, or custom filter class path
50
- `--ignore-paths` - Comma-separated list of paths to ignore
51
- `--extensions` - Additional file extensions to watch (used with python filter)
52
- `--target-type` - Target type: `function`, `command`, or `auto` (default)
53
- `--verbosity` - Logging verbosity level
54
- `--version` - Show version information
55
56
### Filter Integration
57
58
The CLI integrates with the filtering system to control which file changes trigger actions.
59
60
**Built-in Filters:**
61
- `all` - Watch all files (no filtering)
62
- `python` - Watch only Python files (.py, .pyx, .pyd)
63
- Custom filter class path - Import and use custom filter class
64
65
**Filter Examples:**
66
67
```bash
68
# Use default filter
69
watchfiles my_module.main ./src
70
71
# Watch all files (no filtering)
72
watchfiles --filter all my_module.main ./src
73
74
# Watch only Python files
75
watchfiles --filter python my_module.main ./src
76
77
# Use custom filter class
78
watchfiles --filter mypackage.filters.CustomFilter my_module.main ./src
79
80
# Python filter with additional extensions
81
watchfiles --filter python --extensions pyi,pyx my_module.main ./src
82
83
# Ignore specific paths
84
watchfiles --filter python --ignore-paths "logs,tmp,cache" my_module.main ./src
85
```
86
87
### Utility Functions
88
89
Helper functions used by the CLI for path resolution and argument processing.
90
91
```python { .api }
92
def resolve_path(path_str: str) -> Path:
93
"""
94
Resolve a path string to an absolute Path object.
95
96
Parameters:
97
- path_str: String representation of the path
98
99
Returns:
100
Path: Resolved absolute path
101
102
Raises:
103
FileNotFoundError: If the path does not exist
104
"""
105
```
106
107
### Target Type Detection
108
109
The CLI uses automatic target type detection when `--target-type auto` is specified (default).
110
111
**Detection Logic:**
112
- If target is not a string → `function`
113
- If target ends with `.py` or `.sh` → `command`
114
- If target matches pattern `[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+)+` → `function`
115
- Otherwise → `command`
116
117
**Examples:**
118
```bash
119
# These are detected as functions
120
watchfiles my_module.main # function (dotted path)
121
watchfiles mypackage.app.run # function (dotted path)
122
123
# These are detected as commands
124
watchfiles 'python main.py' # command (shell command)
125
watchfiles './script.sh' # command (script file)
126
watchfiles main.py # command (ends with .py)
127
128
# Override detection
129
watchfiles --target-type function 'my_module.main' # force function
130
watchfiles --target-type command 'my_module.main' # force command
131
```
132
133
### Environment Integration
134
135
The CLI respects the same environment variables as the Python API:
136
137
- `WATCHFILES_FORCE_POLLING` - Enable/disable force polling
138
- `WATCHFILES_POLL_DELAY_MS` - Set polling delay in milliseconds
139
- `WATCHFILES_DEBUG` - Enable debug output
140
- `WATCHFILES_IGNORE_PERMISSION_DENIED` - Ignore permission denied errors
141
- `WATCHFILES_CHANGES` - JSON string of changes (set automatically for targets)
142
143
### Process Integration
144
145
The CLI internally uses the process management functionality to handle target execution:
146
147
- Python functions are run using `multiprocessing.Process` with spawn context
148
- Shell commands are run using `subprocess.Popen`
149
- Signal handling (SIGINT/SIGTERM) for graceful shutdown
150
- Process restarting on file changes with configurable timeouts
151
152
**Exit Codes:**
153
- `0` - Normal exit
154
- `1` - Error or KeyboardInterrupt
155
- Other codes - Process-specific exit codes
156
157
### Development Workflow Integration
158
159
The CLI is designed for common development workflows:
160
161
**Testing Workflow:**
162
```bash
163
# Run tests when Python files change
164
watchfiles --filter python 'pytest' tests/
165
166
# Run specific test on change
167
watchfiles --filter python 'pytest tests/test_specific.py -v' src/
168
```
169
170
**Development Server:**
171
```bash
172
# Restart development server on changes
173
watchfiles 'python manage.py runserver' src/
174
175
# Restart with custom settings
176
watchfiles 'python app.py --debug' src/ static/
177
```
178
179
**Build Pipeline:**
180
```bash
181
# Rebuild on source changes
182
watchfiles 'make build' src/
183
184
# Multiple build steps
185
watchfiles 'npm run build && python deploy.py' src/ assets/
186
```
187
188
## Types
189
190
```python { .api }
191
# Internal CLI types (not part of public API)
192
from pathlib import Path
193
from argparse import ArgumentParser
194
```