devpilot-ai 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- devpilot_ai-0.1.0/.gitignore +8 -0
- devpilot_ai-0.1.0/LICENSE +21 -0
- devpilot_ai-0.1.0/PKG-INFO +222 -0
- devpilot_ai-0.1.0/README.md +186 -0
- devpilot_ai-0.1.0/claude-plugin/hooks/detect-devserver-pain.mjs +89 -0
- devpilot_ai-0.1.0/claude-plugin/plugin.json +41 -0
- devpilot_ai-0.1.0/claude-plugin/skills/devpilot/SKILL.md +147 -0
- devpilot_ai-0.1.0/docs/superpowers/plans/2026-03-26-devpilot-implementation.md +3276 -0
- devpilot_ai-0.1.0/docs/superpowers/specs/2026-03-26-devpilot-design.md +363 -0
- devpilot_ai-0.1.0/pyproject.toml +60 -0
- devpilot_ai-0.1.0/src/devpilot/__init__.py +3 -0
- devpilot_ai-0.1.0/src/devpilot/cli.py +346 -0
- devpilot_ai-0.1.0/src/devpilot/config.py +95 -0
- devpilot_ai-0.1.0/src/devpilot/frameworks/__init__.py +0 -0
- devpilot_ai-0.1.0/src/devpilot/frameworks/registry.py +100 -0
- devpilot_ai-0.1.0/src/devpilot/health/__init__.py +0 -0
- devpilot_ai-0.1.0/src/devpilot/health/checker.py +62 -0
- devpilot_ai-0.1.0/src/devpilot/health/verifier.py +56 -0
- devpilot_ai-0.1.0/src/devpilot/process/__init__.py +0 -0
- devpilot_ai-0.1.0/src/devpilot/process/attacher.py +49 -0
- devpilot_ai-0.1.0/src/devpilot/process/manager.py +121 -0
- devpilot_ai-0.1.0/src/devpilot/process/scanner.py +34 -0
- devpilot_ai-0.1.0/src/devpilot/recovery/__init__.py +0 -0
- devpilot_ai-0.1.0/src/devpilot/recovery/strategy.py +111 -0
- devpilot_ai-0.1.0/src/devpilot/state/__init__.py +0 -0
- devpilot_ai-0.1.0/src/devpilot/state/store.py +154 -0
- devpilot_ai-0.1.0/src/devpilot/supervisor.py +322 -0
- devpilot_ai-0.1.0/src/devpilot/watch/__init__.py +0 -0
- devpilot_ai-0.1.0/src/devpilot/watch/file_watcher.py +28 -0
- devpilot_ai-0.1.0/src/devpilot/watch/reload.py +101 -0
- devpilot_ai-0.1.0/tests/__init__.py +0 -0
- devpilot_ai-0.1.0/tests/conftest.py +19 -0
- devpilot_ai-0.1.0/tests/fixtures/fastapi_app/app.py +15 -0
- devpilot_ai-0.1.0/tests/test_attacher.py +48 -0
- devpilot_ai-0.1.0/tests/test_changed.py +61 -0
- devpilot_ai-0.1.0/tests/test_cli.py +69 -0
- devpilot_ai-0.1.0/tests/test_config.py +111 -0
- devpilot_ai-0.1.0/tests/test_file_watcher.py +50 -0
- devpilot_ai-0.1.0/tests/test_frameworks.py +73 -0
- devpilot_ai-0.1.0/tests/test_health_checker.py +92 -0
- devpilot_ai-0.1.0/tests/test_process_manager.py +83 -0
- devpilot_ai-0.1.0/tests/test_recovery.py +67 -0
- devpilot_ai-0.1.0/tests/test_reload.py +62 -0
- devpilot_ai-0.1.0/tests/test_scanner.py +57 -0
- devpilot_ai-0.1.0/tests/test_state_store.py +152 -0
- devpilot_ai-0.1.0/tests/test_supervisor.py +65 -0
- devpilot_ai-0.1.0/tests/test_verifier.py +53 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ben Severn
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devpilot-ai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Dev server supervisor for AI coders
|
|
5
|
+
Project-URL: Homepage, https://github.com/benzsevern/devpilot
|
|
6
|
+
Project-URL: Repository, https://github.com/benzsevern/devpilot
|
|
7
|
+
Project-URL: Issues, https://github.com/benzsevern/devpilot/issues
|
|
8
|
+
Author-email: Ben Severn <benzsevern@gmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: ai,claude,copilot,cursor,dev-server,hot-reload,process-manager,supervisor
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
22
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
23
|
+
Classifier: Topic :: Software Development :: Testing
|
|
24
|
+
Classifier: Topic :: System :: Monitoring
|
|
25
|
+
Requires-Python: >=3.10
|
|
26
|
+
Requires-Dist: click>=8.1
|
|
27
|
+
Requires-Dist: filelock>=3.13
|
|
28
|
+
Requires-Dist: httpx>=0.27
|
|
29
|
+
Requires-Dist: psutil>=5.9
|
|
30
|
+
Requires-Dist: pyyaml>=6.0
|
|
31
|
+
Requires-Dist: watchdog>=4.0
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest-timeout>=2.2; extra == 'dev'
|
|
34
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# devpilot
|
|
38
|
+
|
|
39
|
+
Dev server supervisor for AI coders.
|
|
40
|
+
|
|
41
|
+
AI coding agents (Claude Code, Cursor, Copilot) break dev servers constantly — editing files mid-reload, causing port conflicts, spawning zombie processes. Then they panic: kill random PIDs, rotate ports, nuke all Python processes. It gets worse.
|
|
42
|
+
|
|
43
|
+
**devpilot** gives AI coders structured, reliable process awareness. It manages dev server lifecycles, detects reloads, checks health, and returns JSON that AI can parse and act on — so the panic cycle never starts.
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install devpilot
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or with pipx for global CLI use:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pipx install devpilot
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Quick Start
|
|
58
|
+
|
|
59
|
+
### Auto-detect and configure your project
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
devpilot init
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Scans for `pyproject.toml`, `requirements.txt`, `package.json` and generates `.devpilot.yaml` with the right framework profiles.
|
|
66
|
+
|
|
67
|
+
### Start your dev server under devpilot
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
devpilot run api "uvicorn main:app --reload --port 8000"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Or attach to an already-running server
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
devpilot attach api --port 8000
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Check what happened after editing a file
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
devpilot changed src/main.py
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Returns structured JSON:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
[{
|
|
89
|
+
"service": "api",
|
|
90
|
+
"reload": "reloaded",
|
|
91
|
+
"reload_time_ms": 340,
|
|
92
|
+
"healthy": true,
|
|
93
|
+
"response_time_ms": 12
|
|
94
|
+
}]
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Manage everything at once
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
devpilot up # start all services from .devpilot.yaml
|
|
101
|
+
devpilot down # stop all services
|
|
102
|
+
devpilot status # health check everything
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Why This Exists
|
|
106
|
+
|
|
107
|
+
When an AI coder edits your code, the dev server reloads. But the AI has no way to know:
|
|
108
|
+
|
|
109
|
+
- Did the reload succeed or crash?
|
|
110
|
+
- Is the server healthy?
|
|
111
|
+
- Which service was affected by that file change?
|
|
112
|
+
- Should it wait, retry, or escalate?
|
|
113
|
+
|
|
114
|
+
Without answers, AI coders guess. They kill processes they shouldn't, rotate ports randomly, and create cascading failures. devpilot closes this feedback loop with structured, reliable signals.
|
|
115
|
+
|
|
116
|
+
## How It Works
|
|
117
|
+
|
|
118
|
+
**Two modes:**
|
|
119
|
+
|
|
120
|
+
- **Managed** (`devpilot run`) — devpilot spawns the process, captures stdout, detects reload patterns, owns the full lifecycle
|
|
121
|
+
- **Attached** (`devpilot attach`) — devpilot monitors an existing process by port, health-check only, never kills what it didn't start
|
|
122
|
+
|
|
123
|
+
**Three recovery tiers:**
|
|
124
|
+
|
|
125
|
+
| Tier | Action | Example |
|
|
126
|
+
|------|--------|---------|
|
|
127
|
+
| Silent | Auto-restart with backoff | Process crashed, retry up to 3x |
|
|
128
|
+
| Report | Auto-recover + notify | Repeated crashes, port reassignment |
|
|
129
|
+
| Escalate | Report only, never act | Unknown process on port, code errors |
|
|
130
|
+
|
|
131
|
+
**Core principle:** devpilot never rotates ports randomly, never kills processes it didn't start, never nukes all Python tasks.
|
|
132
|
+
|
|
133
|
+
## Built-in Framework Profiles
|
|
134
|
+
|
|
135
|
+
| Framework | Detection | Default Port |
|
|
136
|
+
|-----------|-----------|-------------|
|
|
137
|
+
| FastAPI/Uvicorn | `uvicorn` in command | 8000 |
|
|
138
|
+
| Flask | `flask` in command | 5000 |
|
|
139
|
+
| Django | `manage.py runserver` | 8000 |
|
|
140
|
+
| Vite | `vite` in command | 5173 |
|
|
141
|
+
| Next.js | `next dev` in command | 3000 |
|
|
142
|
+
| Create React App | `react-scripts start` | 3000 |
|
|
143
|
+
|
|
144
|
+
Custom frameworks can be added in `.devpilot.yaml`.
|
|
145
|
+
|
|
146
|
+
## Configuration
|
|
147
|
+
|
|
148
|
+
`.devpilot.yaml` (generated by `devpilot init` or written manually):
|
|
149
|
+
|
|
150
|
+
```yaml
|
|
151
|
+
services:
|
|
152
|
+
api:
|
|
153
|
+
cmd: "uvicorn main:app --reload --port 8000"
|
|
154
|
+
port: 8000
|
|
155
|
+
health: /health
|
|
156
|
+
file_patterns:
|
|
157
|
+
- "src/**/*.py"
|
|
158
|
+
reload_patterns:
|
|
159
|
+
- "Started reloading"
|
|
160
|
+
- "Application startup complete"
|
|
161
|
+
|
|
162
|
+
frontend:
|
|
163
|
+
cmd: "npm run dev"
|
|
164
|
+
port: 3000
|
|
165
|
+
file_patterns:
|
|
166
|
+
- "src/**/*.tsx"
|
|
167
|
+
- "src/**/*.css"
|
|
168
|
+
|
|
169
|
+
recovery:
|
|
170
|
+
max_retries: 3
|
|
171
|
+
backoff_seconds: [1, 3, 5]
|
|
172
|
+
auto_port_reassign: true
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## All Commands
|
|
176
|
+
|
|
177
|
+
| Command | Description |
|
|
178
|
+
|---------|-------------|
|
|
179
|
+
| `devpilot init` | Auto-detect project and generate `.devpilot.yaml` |
|
|
180
|
+
| `devpilot run <name> <cmd>` | Start a managed service |
|
|
181
|
+
| `devpilot attach <name> --port N` | Monitor an existing service |
|
|
182
|
+
| `devpilot status [name]` | Health check one or all services |
|
|
183
|
+
| `devpilot changed <filepath>` | Report file change, get reload/health result |
|
|
184
|
+
| `devpilot stop [name] [--all]` | Stop managed services |
|
|
185
|
+
| `devpilot restart <name>` | Restart a managed service |
|
|
186
|
+
| `devpilot log [name]` | Show recent events |
|
|
187
|
+
| `devpilot cleanup` | Remove stale state and dead PIDs |
|
|
188
|
+
| `devpilot up` | Start all services from config |
|
|
189
|
+
| `devpilot down` | Stop all services |
|
|
190
|
+
|
|
191
|
+
Every command returns structured JSON to stdout with exit codes 0 (success), 1 (all failed), or 2 (partial).
|
|
192
|
+
|
|
193
|
+
## For AI Tool Authors
|
|
194
|
+
|
|
195
|
+
devpilot is designed to be called programmatically. The JSON output and deterministic exit codes make it straightforward to integrate into any AI coding workflow:
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
import subprocess, json
|
|
199
|
+
|
|
200
|
+
result = subprocess.run(
|
|
201
|
+
["devpilot", "changed", "src/main.py"],
|
|
202
|
+
capture_output=True, text=True
|
|
203
|
+
)
|
|
204
|
+
changes = json.loads(result.stdout)
|
|
205
|
+
|
|
206
|
+
for svc in changes:
|
|
207
|
+
if not svc["healthy"]:
|
|
208
|
+
# check the reload status before panicking
|
|
209
|
+
if svc["reload"] == "reload_failed":
|
|
210
|
+
print(f"Code error in {svc['service']}: {svc.get('error')}")
|
|
211
|
+
elif svc["reload"] == "timeout":
|
|
212
|
+
print(f"Reload slow for {svc['service']}, waiting...")
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Requirements
|
|
216
|
+
|
|
217
|
+
- Python 3.10+
|
|
218
|
+
- Works on Windows, macOS, and Linux
|
|
219
|
+
|
|
220
|
+
## License
|
|
221
|
+
|
|
222
|
+
MIT
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# devpilot
|
|
2
|
+
|
|
3
|
+
Dev server supervisor for AI coders.
|
|
4
|
+
|
|
5
|
+
AI coding agents (Claude Code, Cursor, Copilot) break dev servers constantly — editing files mid-reload, causing port conflicts, spawning zombie processes. Then they panic: kill random PIDs, rotate ports, nuke all Python processes. It gets worse.
|
|
6
|
+
|
|
7
|
+
**devpilot** gives AI coders structured, reliable process awareness. It manages dev server lifecycles, detects reloads, checks health, and returns JSON that AI can parse and act on — so the panic cycle never starts.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install devpilot
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or with pipx for global CLI use:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pipx install devpilot
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### Auto-detect and configure your project
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
devpilot init
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Scans for `pyproject.toml`, `requirements.txt`, `package.json` and generates `.devpilot.yaml` with the right framework profiles.
|
|
30
|
+
|
|
31
|
+
### Start your dev server under devpilot
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
devpilot run api "uvicorn main:app --reload --port 8000"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Or attach to an already-running server
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
devpilot attach api --port 8000
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Check what happened after editing a file
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
devpilot changed src/main.py
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Returns structured JSON:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
[{
|
|
53
|
+
"service": "api",
|
|
54
|
+
"reload": "reloaded",
|
|
55
|
+
"reload_time_ms": 340,
|
|
56
|
+
"healthy": true,
|
|
57
|
+
"response_time_ms": 12
|
|
58
|
+
}]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Manage everything at once
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
devpilot up # start all services from .devpilot.yaml
|
|
65
|
+
devpilot down # stop all services
|
|
66
|
+
devpilot status # health check everything
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Why This Exists
|
|
70
|
+
|
|
71
|
+
When an AI coder edits your code, the dev server reloads. But the AI has no way to know:
|
|
72
|
+
|
|
73
|
+
- Did the reload succeed or crash?
|
|
74
|
+
- Is the server healthy?
|
|
75
|
+
- Which service was affected by that file change?
|
|
76
|
+
- Should it wait, retry, or escalate?
|
|
77
|
+
|
|
78
|
+
Without answers, AI coders guess. They kill processes they shouldn't, rotate ports randomly, and create cascading failures. devpilot closes this feedback loop with structured, reliable signals.
|
|
79
|
+
|
|
80
|
+
## How It Works
|
|
81
|
+
|
|
82
|
+
**Two modes:**
|
|
83
|
+
|
|
84
|
+
- **Managed** (`devpilot run`) — devpilot spawns the process, captures stdout, detects reload patterns, owns the full lifecycle
|
|
85
|
+
- **Attached** (`devpilot attach`) — devpilot monitors an existing process by port, health-check only, never kills what it didn't start
|
|
86
|
+
|
|
87
|
+
**Three recovery tiers:**
|
|
88
|
+
|
|
89
|
+
| Tier | Action | Example |
|
|
90
|
+
|------|--------|---------|
|
|
91
|
+
| Silent | Auto-restart with backoff | Process crashed, retry up to 3x |
|
|
92
|
+
| Report | Auto-recover + notify | Repeated crashes, port reassignment |
|
|
93
|
+
| Escalate | Report only, never act | Unknown process on port, code errors |
|
|
94
|
+
|
|
95
|
+
**Core principle:** devpilot never rotates ports randomly, never kills processes it didn't start, never nukes all Python tasks.
|
|
96
|
+
|
|
97
|
+
## Built-in Framework Profiles
|
|
98
|
+
|
|
99
|
+
| Framework | Detection | Default Port |
|
|
100
|
+
|-----------|-----------|-------------|
|
|
101
|
+
| FastAPI/Uvicorn | `uvicorn` in command | 8000 |
|
|
102
|
+
| Flask | `flask` in command | 5000 |
|
|
103
|
+
| Django | `manage.py runserver` | 8000 |
|
|
104
|
+
| Vite | `vite` in command | 5173 |
|
|
105
|
+
| Next.js | `next dev` in command | 3000 |
|
|
106
|
+
| Create React App | `react-scripts start` | 3000 |
|
|
107
|
+
|
|
108
|
+
Custom frameworks can be added in `.devpilot.yaml`.
|
|
109
|
+
|
|
110
|
+
## Configuration
|
|
111
|
+
|
|
112
|
+
`.devpilot.yaml` (generated by `devpilot init` or written manually):
|
|
113
|
+
|
|
114
|
+
```yaml
|
|
115
|
+
services:
|
|
116
|
+
api:
|
|
117
|
+
cmd: "uvicorn main:app --reload --port 8000"
|
|
118
|
+
port: 8000
|
|
119
|
+
health: /health
|
|
120
|
+
file_patterns:
|
|
121
|
+
- "src/**/*.py"
|
|
122
|
+
reload_patterns:
|
|
123
|
+
- "Started reloading"
|
|
124
|
+
- "Application startup complete"
|
|
125
|
+
|
|
126
|
+
frontend:
|
|
127
|
+
cmd: "npm run dev"
|
|
128
|
+
port: 3000
|
|
129
|
+
file_patterns:
|
|
130
|
+
- "src/**/*.tsx"
|
|
131
|
+
- "src/**/*.css"
|
|
132
|
+
|
|
133
|
+
recovery:
|
|
134
|
+
max_retries: 3
|
|
135
|
+
backoff_seconds: [1, 3, 5]
|
|
136
|
+
auto_port_reassign: true
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## All Commands
|
|
140
|
+
|
|
141
|
+
| Command | Description |
|
|
142
|
+
|---------|-------------|
|
|
143
|
+
| `devpilot init` | Auto-detect project and generate `.devpilot.yaml` |
|
|
144
|
+
| `devpilot run <name> <cmd>` | Start a managed service |
|
|
145
|
+
| `devpilot attach <name> --port N` | Monitor an existing service |
|
|
146
|
+
| `devpilot status [name]` | Health check one or all services |
|
|
147
|
+
| `devpilot changed <filepath>` | Report file change, get reload/health result |
|
|
148
|
+
| `devpilot stop [name] [--all]` | Stop managed services |
|
|
149
|
+
| `devpilot restart <name>` | Restart a managed service |
|
|
150
|
+
| `devpilot log [name]` | Show recent events |
|
|
151
|
+
| `devpilot cleanup` | Remove stale state and dead PIDs |
|
|
152
|
+
| `devpilot up` | Start all services from config |
|
|
153
|
+
| `devpilot down` | Stop all services |
|
|
154
|
+
|
|
155
|
+
Every command returns structured JSON to stdout with exit codes 0 (success), 1 (all failed), or 2 (partial).
|
|
156
|
+
|
|
157
|
+
## For AI Tool Authors
|
|
158
|
+
|
|
159
|
+
devpilot is designed to be called programmatically. The JSON output and deterministic exit codes make it straightforward to integrate into any AI coding workflow:
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
import subprocess, json
|
|
163
|
+
|
|
164
|
+
result = subprocess.run(
|
|
165
|
+
["devpilot", "changed", "src/main.py"],
|
|
166
|
+
capture_output=True, text=True
|
|
167
|
+
)
|
|
168
|
+
changes = json.loads(result.stdout)
|
|
169
|
+
|
|
170
|
+
for svc in changes:
|
|
171
|
+
if not svc["healthy"]:
|
|
172
|
+
# check the reload status before panicking
|
|
173
|
+
if svc["reload"] == "reload_failed":
|
|
174
|
+
print(f"Code error in {svc['service']}: {svc.get('error')}")
|
|
175
|
+
elif svc["reload"] == "timeout":
|
|
176
|
+
print(f"Reload slow for {svc['service']}, waiting...")
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Requirements
|
|
180
|
+
|
|
181
|
+
- Python 3.10+
|
|
182
|
+
- Works on Windows, macOS, and Linux
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UserPromptSubmit hook — detects dev server pain signals in user messages
|
|
3
|
+
* and suggests the devpilot skill when relevant.
|
|
4
|
+
*
|
|
5
|
+
* Reads the user's prompt from stdin (JSON with `prompt` field) and checks
|
|
6
|
+
* for frustration patterns related to dev server management.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const PAIN_PATTERNS = [
|
|
10
|
+
// Direct crashes and failures
|
|
11
|
+
/dev\s*server.*(?:crash|die|stop|kill|broke|broken|down|fail)/i,
|
|
12
|
+
/server.*(?:crash|die|stop|kill|broke|broken|down|fail)/i,
|
|
13
|
+
/(?:crash|die|stop|kill|broke|broken|down|fail).*(?:dev\s*server|server)/i,
|
|
14
|
+
|
|
15
|
+
// Hot reload issues
|
|
16
|
+
/(?:hot\s*)?reload.*(?:fail|stuck|broken|not\s*work|slow|hang)/i,
|
|
17
|
+
/(?:hmr|hot\s*module).*(?:fail|stuck|broken|not\s*work)/i,
|
|
18
|
+
/changes.*(?:not\s*show|not\s*reflect|not\s*pick|not\s*appear|not\s*updat)/i,
|
|
19
|
+
|
|
20
|
+
// Port conflicts
|
|
21
|
+
/(?:port|address).*(?:already\s*in\s*use|conflict|taken|busy)/i,
|
|
22
|
+
/eaddrinuse/i,
|
|
23
|
+
|
|
24
|
+
// Zombie / orphan processes
|
|
25
|
+
/zombie\s*process/i,
|
|
26
|
+
/orphan\s*process/i,
|
|
27
|
+
/process.*(?:won't\s*die|stuck|hang|stale)/i,
|
|
28
|
+
/kill.*(?:all|every).*(?:python|node|process)/i,
|
|
29
|
+
|
|
30
|
+
// Restart loops
|
|
31
|
+
/(?:keep|keeps|constantly|always).*(?:restart|crash|die|fail)/i,
|
|
32
|
+
/restart.*loop/i,
|
|
33
|
+
/can't.*(?:start|restart|run).*(?:server|dev)/i,
|
|
34
|
+
|
|
35
|
+
// Panic signals
|
|
36
|
+
/(?:kill|taskkill|pkill).*(?:python|node|uvicorn|next|vite|flask)/i,
|
|
37
|
+
/kill\s*-9/i,
|
|
38
|
+
/taskkill\s*\/f/i,
|
|
39
|
+
/lsof.*(?:kill|port)/i,
|
|
40
|
+
/netstat.*(?:kill|port)/i,
|
|
41
|
+
|
|
42
|
+
// Direct asks
|
|
43
|
+
/devpilot/i,
|
|
44
|
+
/dev\s*server\s*supervisor/i,
|
|
45
|
+
/supervise.*(?:dev|server|process)/i,
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
async function main() {
|
|
49
|
+
let input = "";
|
|
50
|
+
for await (const chunk of process.stdin) {
|
|
51
|
+
input += chunk;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let prompt;
|
|
55
|
+
try {
|
|
56
|
+
const data = JSON.parse(input);
|
|
57
|
+
prompt = data.prompt || "";
|
|
58
|
+
} catch {
|
|
59
|
+
// Not JSON, treat the raw input as the prompt
|
|
60
|
+
prompt = input;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (!prompt) {
|
|
64
|
+
console.log(JSON.stringify({ result: "approve" }));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const matched = PAIN_PATTERNS.some((pattern) => pattern.test(prompt));
|
|
69
|
+
|
|
70
|
+
if (matched) {
|
|
71
|
+
console.log(
|
|
72
|
+
JSON.stringify({
|
|
73
|
+
result: "approve",
|
|
74
|
+
additionalContext: [
|
|
75
|
+
"**Dev server pain detected.** The `devpilot` skill can help here.",
|
|
76
|
+
"If devpilot is not installed, suggest: `pip install devpilot`",
|
|
77
|
+
"Then use devpilot to manage the dev server instead of killing processes manually.",
|
|
78
|
+
"Run `Skill(devpilot)` for full guidance.",
|
|
79
|
+
].join("\n"),
|
|
80
|
+
})
|
|
81
|
+
);
|
|
82
|
+
} else {
|
|
83
|
+
console.log(JSON.stringify({ result: "approve" }));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
main().catch(() => {
|
|
88
|
+
console.log(JSON.stringify({ result: "approve" }));
|
|
89
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devpilot",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Dev server supervisor for AI coders — detects dev server pain and provides structured process management",
|
|
5
|
+
"skills": [
|
|
6
|
+
{
|
|
7
|
+
"name": "devpilot",
|
|
8
|
+
"path": "skills/devpilot/SKILL.md",
|
|
9
|
+
"description": "Dev server supervisor guidance — install, configure, and use devpilot to manage dev server lifecycles, detect reloads, and recover from crashes. Use when: dev server crashes, hot reload fails, port conflicts, zombie processes, AI coder is stuck in a restart loop, or user asks about devpilot.",
|
|
10
|
+
"metadata": {
|
|
11
|
+
"filePattern": [
|
|
12
|
+
".devpilot.yaml",
|
|
13
|
+
".devpilot.yml",
|
|
14
|
+
".devpilot/**"
|
|
15
|
+
],
|
|
16
|
+
"bashPattern": [
|
|
17
|
+
"devpilot\\b",
|
|
18
|
+
"uvicorn.*--reload",
|
|
19
|
+
"next\\s+dev",
|
|
20
|
+
"npm\\s+run\\s+dev",
|
|
21
|
+
"vite",
|
|
22
|
+
"flask\\s+run",
|
|
23
|
+
"manage\\.py\\s+runserver"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"hooks": {
|
|
29
|
+
"UserPromptSubmit": [
|
|
30
|
+
{
|
|
31
|
+
"matcher": "",
|
|
32
|
+
"hooks": [
|
|
33
|
+
{
|
|
34
|
+
"type": "command",
|
|
35
|
+
"command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/detect-devserver-pain.mjs\""
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
}
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
}
|