procler 0.2.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.
Files changed (93) hide show
  1. procler-0.2.0/.claude/settings.json +16 -0
  2. procler-0.2.0/.env.example +23 -0
  3. procler-0.2.0/.gitignore +57 -0
  4. procler-0.2.0/.pre-commit-config.yaml +7 -0
  5. procler-0.2.0/AGENTS.md +434 -0
  6. procler-0.2.0/CHANGELOG.md +84 -0
  7. procler-0.2.0/Dockerfile +70 -0
  8. procler-0.2.0/LICENSE +21 -0
  9. procler-0.2.0/PKG-INFO +545 -0
  10. procler-0.2.0/README.ja.md +498 -0
  11. procler-0.2.0/README.md +498 -0
  12. procler-0.2.0/docker-compose.yml +27 -0
  13. procler-0.2.0/procler/__init__.py +3 -0
  14. procler-0.2.0/procler/__main__.py +6 -0
  15. procler-0.2.0/procler/api/__init__.py +5 -0
  16. procler-0.2.0/procler/api/app.py +261 -0
  17. procler-0.2.0/procler/api/deps.py +21 -0
  18. procler-0.2.0/procler/api/routes/__init__.py +5 -0
  19. procler-0.2.0/procler/api/routes/config.py +290 -0
  20. procler-0.2.0/procler/api/routes/groups.py +62 -0
  21. procler-0.2.0/procler/api/routes/logs.py +43 -0
  22. procler-0.2.0/procler/api/routes/processes.py +185 -0
  23. procler-0.2.0/procler/api/routes/recipes.py +69 -0
  24. procler-0.2.0/procler/api/routes/snippets.py +134 -0
  25. procler-0.2.0/procler/api/routes/ws.py +459 -0
  26. procler-0.2.0/procler/cli.py +1478 -0
  27. procler-0.2.0/procler/config/__init__.py +65 -0
  28. procler-0.2.0/procler/config/changelog.py +148 -0
  29. procler-0.2.0/procler/config/loader.py +256 -0
  30. procler-0.2.0/procler/config/schema.py +315 -0
  31. procler-0.2.0/procler/core/__init__.py +54 -0
  32. procler-0.2.0/procler/core/context_base.py +117 -0
  33. procler-0.2.0/procler/core/context_docker.py +384 -0
  34. procler-0.2.0/procler/core/context_local.py +287 -0
  35. procler-0.2.0/procler/core/daemon_detector.py +325 -0
  36. procler-0.2.0/procler/core/events.py +74 -0
  37. procler-0.2.0/procler/core/groups.py +419 -0
  38. procler-0.2.0/procler/core/health.py +280 -0
  39. procler-0.2.0/procler/core/log_tailer.py +262 -0
  40. procler-0.2.0/procler/core/process_manager.py +1277 -0
  41. procler-0.2.0/procler/core/recipes.py +330 -0
  42. procler-0.2.0/procler/core/snippets.py +231 -0
  43. procler-0.2.0/procler/core/variable_substitution.py +65 -0
  44. procler-0.2.0/procler/db.py +96 -0
  45. procler-0.2.0/procler/logging.py +41 -0
  46. procler-0.2.0/procler/models.py +130 -0
  47. procler-0.2.0/procler/py.typed +0 -0
  48. procler-0.2.0/procler/settings.py +29 -0
  49. procler-0.2.0/procler/static/assets/AboutView-BwZnsfpW.js +4 -0
  50. procler-0.2.0/procler/static/assets/AboutView-UHbxWXcS.css +1 -0
  51. procler-0.2.0/procler/static/assets/Code-HTS-H1S6.js +74 -0
  52. procler-0.2.0/procler/static/assets/ConfigView-CGJcmp9G.css +1 -0
  53. procler-0.2.0/procler/static/assets/ConfigView-aVtbRDf8.js +1 -0
  54. procler-0.2.0/procler/static/assets/DashboardView-C5jw9Nsd.css +1 -0
  55. procler-0.2.0/procler/static/assets/DashboardView-Dab7Cu9v.js +1 -0
  56. procler-0.2.0/procler/static/assets/DataTable-z39TOAa4.js +746 -0
  57. procler-0.2.0/procler/static/assets/DescriptionsItem-B2E8YbqJ.js +74 -0
  58. procler-0.2.0/procler/static/assets/Divider-Dk-6aD2Y.js +42 -0
  59. procler-0.2.0/procler/static/assets/Empty-MuygEHZM.js +24 -0
  60. procler-0.2.0/procler/static/assets/Grid-CZ9QVKAT.js +1 -0
  61. procler-0.2.0/procler/static/assets/GroupsView-BALG7i1X.js +1 -0
  62. procler-0.2.0/procler/static/assets/GroupsView-gXAI1CVC.css +1 -0
  63. procler-0.2.0/procler/static/assets/Input-e0xaxoWE.js +259 -0
  64. procler-0.2.0/procler/static/assets/PhArrowsClockwise.vue-DqDg31az.js +1 -0
  65. procler-0.2.0/procler/static/assets/PhCheckCircle.vue-Fwj9sh9m.js +1 -0
  66. procler-0.2.0/procler/static/assets/PhEye.vue-JcPHciC2.js +1 -0
  67. procler-0.2.0/procler/static/assets/PhPlay.vue-CZm7Gy3u.js +1 -0
  68. procler-0.2.0/procler/static/assets/PhPlus.vue-yTWqKlSh.js +1 -0
  69. procler-0.2.0/procler/static/assets/PhStop.vue-DxsqwIki.js +1 -0
  70. procler-0.2.0/procler/static/assets/PhTrash.vue-DcqQbN1_.js +125 -0
  71. procler-0.2.0/procler/static/assets/PhXCircle.vue-BXWmrabV.js +1 -0
  72. procler-0.2.0/procler/static/assets/ProcessDetailView-DDbtIWq9.css +1 -0
  73. procler-0.2.0/procler/static/assets/ProcessDetailView-DPtdNV-q.js +1 -0
  74. procler-0.2.0/procler/static/assets/ProcessesView-B3a6Umur.js +1 -0
  75. procler-0.2.0/procler/static/assets/ProcessesView-goLmghbJ.css +1 -0
  76. procler-0.2.0/procler/static/assets/RecipesView-D2VxdneD.js +166 -0
  77. procler-0.2.0/procler/static/assets/RecipesView-DXnFDCK4.css +1 -0
  78. procler-0.2.0/procler/static/assets/Select-BBR17AHq.js +317 -0
  79. procler-0.2.0/procler/static/assets/SnippetsView-B3a9q3AI.css +1 -0
  80. procler-0.2.0/procler/static/assets/SnippetsView-DBCB2yGq.js +1 -0
  81. procler-0.2.0/procler/static/assets/Spin-BXTjvFUk.js +90 -0
  82. procler-0.2.0/procler/static/assets/Tag-Bh_qV63A.js +71 -0
  83. procler-0.2.0/procler/static/assets/changelog-KkTT4H9-.js +1 -0
  84. procler-0.2.0/procler/static/assets/groups-Zu-_v8ey.js +1 -0
  85. procler-0.2.0/procler/static/assets/index-BsN-YMXq.css +1 -0
  86. procler-0.2.0/procler/static/assets/index-BzW1XhyH.js +1282 -0
  87. procler-0.2.0/procler/static/assets/procler-DOrSB1Vj.js +1 -0
  88. procler-0.2.0/procler/static/assets/recipes-1w5SseGb.js +1 -0
  89. procler-0.2.0/procler/static/index.html +17 -0
  90. procler-0.2.0/procler/static/procler.png +0 -0
  91. procler-0.2.0/procler.png +0 -0
  92. procler-0.2.0/pyproject.toml +100 -0
  93. procler-0.2.0/uv.lock +1196 -0
@@ -0,0 +1,16 @@
1
+ {
2
+ "hooks": {
3
+ "PostToolUse": [
4
+ {
5
+ "matcher": "Edit|Write",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "jq -r '.tool_input.file_path' | { read file_path; if echo \"$file_path\" | grep -q '/frontend/'; then echo '[hook] Frontend file changed, rebuilding...' && cd \"$CLAUDE_PROJECT_DIR\" && ./scripts/build_frontend.sh > /dev/null 2>&1 && echo '[hook] Frontend build complete'; fi; }",
10
+ "timeout": 120
11
+ }
12
+ ]
13
+ }
14
+ ]
15
+ }
16
+ }
@@ -0,0 +1,23 @@
1
+ # Procler Environment Variables
2
+ # Copy to .env and customize as needed
3
+
4
+ # Logging
5
+ PROCLER_LOG_LEVEL=INFO # DEBUG, INFO, WARNING, ERROR
6
+ PROCLER_LOG_FILE= # Optional file path for logs (auto-rotates)
7
+
8
+ # Log rotation (for process output logs in DB)
9
+ PROCLER_LOG_ROTATION_INTERVAL=3600 # Seconds between rotation checks (default: 1 hour)
10
+ PROCLER_MAX_LOGS_PER_PROCESS=10000 # Max log entries per process (default: 10000)
11
+
12
+ # Config directory (defaults to .procler/ in current dir)
13
+ PROCLER_CONFIG_DIR= # Override config directory path
14
+
15
+ # Database
16
+ PROCLER_DB_PATH= # Override database path (default: .procler/state.db)
17
+
18
+ # Server
19
+ PROCLER_CORS_ORIGINS= # Comma-separated allowed origins (default: localhost)
20
+ PROCLER_DEBUG= # Set to 1 for detailed error messages
21
+
22
+ # Data directory (for CLI)
23
+ PROCLER_DATA_DIR= # Override data directory
@@ -0,0 +1,57 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual environments
24
+ .venv/
25
+ venv/
26
+ ENV/
27
+
28
+ # IDE
29
+ .idea/
30
+ .vscode/
31
+ *.swp
32
+ *.swo
33
+ *~
34
+
35
+ # Testing
36
+ .pytest_cache/
37
+ .coverage
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+
42
+ # Type checking
43
+ .mypy_cache/
44
+
45
+ # Ruff
46
+ .ruff_cache/
47
+
48
+ # Local data
49
+ .procler/
50
+
51
+ # Local development preferences
52
+ CLAUDE.local.md
53
+
54
+ # Frontend build (keep built static/ in git for ease of use)
55
+ frontend/node_modules/
56
+ frontend/dist/
57
+ *.tsbuildinfo
@@ -0,0 +1,7 @@
1
+ repos:
2
+ - repo: https://github.com/astral-sh/ruff-pre-commit
3
+ rev: v0.8.6
4
+ hooks:
5
+ - id: ruff
6
+ args: [--fix]
7
+ - id: ruff-format
@@ -0,0 +1,434 @@
1
+ # Procler - Agent Usage Guide
2
+
3
+ This document provides comprehensive instructions for LLM agents to use Procler, an LLM-first process manager.
4
+
5
+ ---
6
+
7
+ ## Quick Reference
8
+
9
+ ```bash
10
+ # Discovery
11
+ procler capabilities # JSON schema of all commands
12
+ procler help-llm # Comprehensive usage guide (JSON with markdown)
13
+ procler config explain # Plain-language config explanation
14
+
15
+ # Process Management
16
+ procler start <name> # Idempotent
17
+ procler stop <name> # Idempotent
18
+ procler restart <name> # With optional --clear-logs
19
+ procler status [name] # Status with Linux kernel state
20
+ procler logs <name> # --tail N, --since 5m
21
+
22
+ # Groups & Recipes
23
+ procler group start <name> # Ordered startup with dependencies
24
+ procler recipe run <name> # Multi-step operation (--dry-run to preview)
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Response Format
30
+
31
+ All CLI commands return JSON to stdout. Parse the response as follows:
32
+
33
+ ### Success
34
+ ```json
35
+ {
36
+ "success": true,
37
+ "data": {
38
+ "process": { "name": "api", "status": "running", "pid": 12345 }
39
+ }
40
+ }
41
+ ```
42
+
43
+ ### Error
44
+ ```json
45
+ {
46
+ "success": false,
47
+ "error": "Process 'api' not found",
48
+ "error_code": "process_not_found",
49
+ "suggestion": "Run 'procler list' to see available processes"
50
+ }
51
+ ```
52
+
53
+ **Always check `success` field first.** Use `error_code` for programmatic error handling and `suggestion` for recovery actions.
54
+
55
+ ---
56
+
57
+ ## CLI Help
58
+
59
+ ```
60
+ Usage: procler [OPTIONS] COMMAND [ARGS]...
61
+
62
+ Procler - LLM-first process manager for developers.
63
+ All commands output JSON for easy parsing by scripts and LLMs.
64
+
65
+ Options:
66
+ --version Show the version and exit.
67
+ --help Show this message and exit.
68
+
69
+ Commands:
70
+ capabilities Returns JSON schema of all commands.
71
+ config Manage configuration (config.yaml).
72
+ define Define a new process.
73
+ exec Execute an arbitrary command.
74
+ group Manage process groups (defined in config.yaml).
75
+ help-llm Output comprehensive LLM-focused usage instructions.
76
+ list List all process definitions.
77
+ logs Get logs for a process.
78
+ recipe Manage and run recipes (multi-step operations).
79
+ remove Remove a process definition.
80
+ restart Restart a process (stop then start).
81
+ serve Start the web server.
82
+ snippet Manage command snippets.
83
+ start Start a process (idempotent - no-op if running).
84
+ status Show status of all processes or a specific one.
85
+ stop Stop a process (idempotent - no-op if stopped).
86
+ ```
87
+
88
+ ---
89
+
90
+ ## Command Discovery
91
+
92
+ Run `procler capabilities` to get a complete JSON schema of all available commands, their arguments, options, and examples. This is the recommended way for agents to discover functionality.
93
+
94
+ Run `procler help-llm` for a markdown-formatted comprehensive guide embedded in JSON.
95
+
96
+ ---
97
+
98
+ ## Process Management
99
+
100
+ ### Define a Process
101
+ ```bash
102
+ procler define --name api --command 'uvicorn main:app' --cwd /app
103
+ procler define --name worker --command 'celery worker' --context docker --container myapp
104
+ ```
105
+
106
+ ### Start/Stop/Restart
107
+ ```bash
108
+ procler start api # Returns immediately, process runs in background
109
+ procler stop api # Sends SIGTERM, waits for graceful shutdown
110
+ procler restart api # Stop then start
111
+ procler restart api --clear-logs # Clear accumulated logs
112
+ ```
113
+
114
+ **Idempotency**: `start` on a running process and `stop` on a stopped process are no-ops that return success.
115
+
116
+ ### Status
117
+ ```bash
118
+ procler status # All processes
119
+ procler status api # Specific process
120
+ ```
121
+
122
+ Response includes:
123
+ - `status`: "running" | "stopped" | "failed"
124
+ - `pid`: Process ID (null if not running)
125
+ - `uptime_seconds`: Time since start
126
+ - `linux_state`: Kernel state information
127
+ - `warning`: Alert for problematic states (D, Z)
128
+
129
+ ### Linux Process States
130
+ | Code | Name | Description | Killable |
131
+ |------|------|-------------|----------|
132
+ | R | running | On run queue | Yes |
133
+ | S | sleeping | Interruptible sleep | Yes |
134
+ | D | disk_sleep | Uninterruptible (I/O wait) | **No** |
135
+ | Z | zombie | Terminated, not reaped | **No** |
136
+ | T | stopped | Job control signal | Yes |
137
+
138
+ **Important**: Processes in D state cannot be killed. Wait for I/O to complete.
139
+
140
+ ### Logs
141
+ ```bash
142
+ procler logs api # Last 100 lines
143
+ procler logs api --tail 50 # Last 50 lines
144
+ procler logs api --since 5m # Last 5 minutes
145
+ procler logs api --since 1h # Last hour
146
+ ```
147
+
148
+ ---
149
+
150
+ ## Groups
151
+
152
+ Groups define ordered startup sequences with optional dependencies.
153
+
154
+ ```bash
155
+ procler group list # List all groups
156
+ procler group start backend # Start processes in order
157
+ procler group stop backend # Stop in reverse order
158
+ procler group status backend # Status of all group processes
159
+ ```
160
+
161
+ ### Config Example
162
+ ```yaml
163
+ groups:
164
+ backend:
165
+ processes: [redis, database, api, worker]
166
+ stop_order: [worker, api, database, redis] # Optional custom order
167
+ ```
168
+
169
+ ### Dependencies
170
+ ```yaml
171
+ processes:
172
+ api:
173
+ command: uvicorn main:app
174
+ depends_on:
175
+ - redis # Wait for 'started'
176
+ - name: database
177
+ condition: healthy # Wait for health check pass
178
+ ```
179
+
180
+ ---
181
+
182
+ ## Recipes
183
+
184
+ Recipes are multi-step automation workflows.
185
+
186
+ ```bash
187
+ procler recipe list
188
+ procler recipe show deploy # View steps
189
+ procler recipe run deploy --dry-run # Preview without executing
190
+ procler recipe run deploy # Execute
191
+ procler recipe run deploy --continue-on-error
192
+ ```
193
+
194
+ ### Config Example
195
+ ```yaml
196
+ recipes:
197
+ deploy:
198
+ description: "Graceful deployment with migration"
199
+ on_error: stop # or continue
200
+ steps:
201
+ - stop: worker
202
+ - stop: api
203
+ - wait: 2s
204
+ - exec: "alembic upgrade head"
205
+ context: docker
206
+ container: myapp
207
+ - start: api
208
+ - start: worker
209
+ ```
210
+
211
+ ### Step Types
212
+ - `start: <process>` - Start a process
213
+ - `stop: <process>` - Stop a process
214
+ - `restart: <process>` - Restart a process
215
+ - `exec: "<command>"` - Run a one-off command
216
+ - `wait: <duration>` - Pause (e.g., "5s", "1m")
217
+
218
+ ---
219
+
220
+ ## Snippets
221
+
222
+ Snippets are saved commands for quick execution.
223
+
224
+ ```bash
225
+ procler snippet list
226
+ procler snippet list --tag docker # Filter by tag
227
+ procler snippet save --name rebuild --command 'docker compose build' --tags docker
228
+ procler snippet run rebuild
229
+ procler snippet remove rebuild
230
+ ```
231
+
232
+ ---
233
+
234
+ ## Configuration
235
+
236
+ ### Initialize
237
+ ```bash
238
+ procler config init # Creates .procler/ directory
239
+ procler config validate # Validates config.yaml
240
+ procler config path # Shows resolved paths
241
+ procler config explain # Plain-language explanation
242
+ ```
243
+
244
+ ### Config Structure
245
+ ```
246
+ .procler/
247
+ ├── config.yaml # Version-controllable definitions
248
+ ├── changelog.log # Audit trail of operations
249
+ └── state.db # Runtime state (auto-gitignored)
250
+ ```
251
+
252
+ ### Full Config Example
253
+ ```yaml
254
+ version: 1
255
+
256
+ processes:
257
+ redis:
258
+ command: redis-server
259
+ context: local
260
+ tags: [database, cache]
261
+
262
+ api:
263
+ command: uvicorn main:app --reload
264
+ context: local
265
+ cwd: /home/user/myapp
266
+ tags: [backend]
267
+ healthcheck:
268
+ test: "curl -f http://localhost:8000/health"
269
+ interval: 10s
270
+ timeout: 5s
271
+ retries: 3
272
+ start_period: 30s
273
+ depends_on:
274
+ - redis
275
+
276
+ worker:
277
+ command: celery -A tasks worker
278
+ context: docker
279
+ container: myapp-worker
280
+ depends_on:
281
+ - name: api
282
+ condition: healthy
283
+
284
+ groups:
285
+ backend:
286
+ description: "Full backend stack"
287
+ processes: [redis, api, worker]
288
+
289
+ recipes:
290
+ deploy:
291
+ description: "Zero-downtime deployment"
292
+ on_error: stop
293
+ steps:
294
+ - stop: worker
295
+ - stop: api
296
+ - exec: "alembic upgrade head"
297
+ - start: api
298
+ - start: worker
299
+
300
+ snippets:
301
+ rebuild:
302
+ command: docker compose build --no-cache
303
+ description: "Rebuild all containers"
304
+ tags: [docker, build]
305
+ ```
306
+
307
+ ---
308
+
309
+ ## Web Server & API
310
+
311
+ ```bash
312
+ procler serve # localhost:8000
313
+ procler serve --host 0.0.0.0 --port 8080
314
+ procler serve --reload # Development mode
315
+ ```
316
+
317
+ ### REST API Endpoints
318
+ | Method | Endpoint | Description |
319
+ |--------|----------|-------------|
320
+ | GET | /api/processes | List all processes |
321
+ | GET | /api/processes/{name} | Get process details |
322
+ | POST | /api/processes | Create process |
323
+ | DELETE | /api/processes/{name} | Remove process |
324
+ | POST | /api/processes/{name}/start | Start process |
325
+ | POST | /api/processes/{name}/stop | Stop process |
326
+ | POST | /api/processes/{name}/restart | Restart process |
327
+ | GET | /api/logs/{name} | Get process logs |
328
+ | GET | /api/groups | List groups |
329
+ | POST | /api/groups/{name}/start | Start group |
330
+ | POST | /api/groups/{name}/stop | Stop group |
331
+ | GET | /api/recipes | List recipes |
332
+ | POST | /api/recipes/{name}/run | Run recipe |
333
+ | GET | /api/health | Health check |
334
+
335
+ ### WebSocket
336
+ Connect to `ws://localhost:8000/api/ws` for real-time updates:
337
+ ```json
338
+ {"action": "subscribe_logs", "process_id": 1}
339
+ {"action": "subscribe_status", "process_id": 1}
340
+ {"action": "subscribe_status"} // All processes
341
+ ```
342
+
343
+ ---
344
+
345
+ ## Common Workflows
346
+
347
+ ### Start Development Environment
348
+ ```bash
349
+ procler group start backend
350
+ procler status
351
+ ```
352
+
353
+ ### Debug Failing Process
354
+ ```bash
355
+ procler status api # Check status and Linux state
356
+ procler logs api --tail 100 # View recent logs
357
+ procler restart api --clear-logs
358
+ ```
359
+
360
+ ### Graceful Deployment
361
+ ```bash
362
+ procler recipe run deploy --dry-run # Preview
363
+ procler recipe run deploy # Execute
364
+ ```
365
+
366
+ ### Quick Command Execution
367
+ ```bash
368
+ procler exec "npm run build" --cwd /app
369
+ procler exec "python manage.py migrate" --context docker --container myapp
370
+ ```
371
+
372
+ ---
373
+
374
+ ## Environment Variables
375
+
376
+ | Variable | Default | Description |
377
+ |----------|---------|-------------|
378
+ | `PROCLER_LOG_LEVEL` | `INFO` | DEBUG, INFO, WARNING, ERROR |
379
+ | `PROCLER_LOG_FILE` | - | Log file path (auto-rotates) |
380
+ | `PROCLER_LOG_ROTATION_INTERVAL` | `3600` | Seconds between log rotation |
381
+ | `PROCLER_MAX_LOGS_PER_PROCESS` | `10000` | Max log entries per process |
382
+ | `PROCLER_CONFIG_DIR` | `.procler/` | Config directory path |
383
+ | `PROCLER_DB_PATH` | `.procler/state.db` | Database path |
384
+ | `PROCLER_CORS_ORIGINS` | localhost | Allowed CORS origins |
385
+ | `PROCLER_DEBUG` | - | Enable detailed error messages |
386
+
387
+ ---
388
+
389
+ ## Error Codes
390
+
391
+ | Code | Description | Recovery |
392
+ |------|-------------|----------|
393
+ | `process_not_found` | Process doesn't exist | Run `procler list` |
394
+ | `process_exists` | Process name already taken | Choose different name or remove first |
395
+ | `process_running` | Operation invalid while running | Stop first |
396
+ | `process_stopped` | Operation invalid while stopped | Start first |
397
+ | `missing_container` | Docker context requires container | Add `--container` |
398
+ | `config_not_found` | No config.yaml | Run `procler config init` |
399
+ | `config_exists` | Config already exists | Use `--force` |
400
+ | `validation_failed` | Invalid config | Check error details |
401
+ | `group_not_found` | Group not in config | Check config.yaml |
402
+ | `recipe_not_found` | Recipe not in config | Check config.yaml |
403
+
404
+ ---
405
+
406
+ ## Docker Deployment
407
+
408
+ ```bash
409
+ # Using Docker Compose
410
+ docker compose up -d
411
+
412
+ # Manual
413
+ docker build -t procler .
414
+ docker run -d -p 8000:8000 -v procler-data:/home/procler/.procler procler
415
+ ```
416
+
417
+ ### Production Features
418
+ - **Process Recovery**: Detects orphaned processes on startup
419
+ - **Graceful Shutdown**: SIGTERM/SIGINT triggers orderly process shutdown
420
+ - **Log Rotation**: Background task rotates logs hourly
421
+ - **Health Check**: `/api/health` endpoint for container health
422
+
423
+ ---
424
+
425
+ ## Tips for Agents
426
+
427
+ 1. **Always parse JSON output** - Never assume command success from exit code alone
428
+ 2. **Use `capabilities` for discovery** - Dynamically learn available commands
429
+ 3. **Check `suggestion` on errors** - Contains actionable recovery steps
430
+ 4. **Leverage idempotency** - Safe to retry start/stop operations
431
+ 5. **Use `--dry-run` for recipes** - Preview destructive operations
432
+ 6. **Monitor Linux state** - D and Z states require special handling
433
+ 7. **Use groups for complex startups** - Dependencies are resolved automatically
434
+ 8. **Clear logs on restart** - Use `--clear-logs` when debugging fresh starts
@@ -0,0 +1,84 @@
1
+ # Changelog
2
+
3
+ All notable changes to Procler will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Fixed
11
+
12
+ - Fixed graceful shutdown loop when pressing Ctrl+C multiple times
13
+ - Fixed log rotation to use correct `cleanup_all_logs()` method
14
+ - Fixed process recovery query to use proper sqler API
15
+ - Fixed graceful shutdown to use `status()` instead of non-existent `list_processes()`
16
+
17
+ ### Changed
18
+
19
+ - Frontend static files now bundled in repository for easier deployment
20
+ - Updated `.gitignore` to track `procler/static/` directory
21
+
22
+ ### Added
23
+
24
+ - Test coverage for application lifespan startup/shutdown
25
+
26
+ ## [0.1.0] - 2026-01-08
27
+
28
+ ### Added
29
+
30
+ - **Process Management**
31
+ - Define, start, stop, restart, remove processes via CLI
32
+ - Local subprocess execution with process groups
33
+ - Docker container execution via docker-py SDK
34
+ - PID-based process verification across sessions
35
+ - Idempotent operations (start running process = no-op)
36
+
37
+ - **Logging**
38
+ - Automatic stdout/stderr capture to SQLite
39
+ - Log retrieval with `--tail` and `--since` filters
40
+ - Log rotation and cleanup per process
41
+
42
+ - **Snippets**
43
+ - Save reusable commands with descriptions and tags
44
+ - Tag filtering for snippet organization
45
+ - Execute snippets in local or Docker context
46
+
47
+ - **REST API**
48
+ - Full CRUD operations for processes and snippets
49
+ - Log retrieval endpoint
50
+ - Health check endpoint
51
+ - OpenAPI documentation at `/api/docs`
52
+
53
+ - **WebSocket Real-time**
54
+ - Live log streaming subscription
55
+ - Status change broadcasts
56
+ - Connection management with automatic cleanup
57
+
58
+ - **Vue 3 Frontend**
59
+ - Process list with start/stop/restart controls
60
+ - Process detail view with live log streaming
61
+ - Snippets management UI
62
+ - Cyberpunk design system (Naive UI + custom theme)
63
+
64
+ - **CLI**
65
+ - JSON-native output for all commands
66
+ - `capabilities` command for LLM discovery
67
+ - Rich error context with suggestions
68
+ - Exit codes for scripting
69
+
70
+ - **Production Features**
71
+ - Build script for Vue to static files
72
+ - FastAPI serves frontend in production
73
+ - CORS configuration via environment variable
74
+ - Global exception handler
75
+
76
+ ### Technical Details
77
+
78
+ - Python 3.12+ required
79
+ - SQLite via sqler for persistence
80
+ - FastAPI for REST API and WebSocket
81
+ - Click for CLI
82
+ - Vue 3 + Vite + Pinia + Naive UI for frontend
83
+
84
+ [0.1.0]: https://github.com/gabu-quest/procler/releases/tag/v0.1.0
@@ -0,0 +1,70 @@
1
+ # Procler - LLM-first process manager
2
+ # Multi-stage build for smaller image
3
+
4
+ # Build frontend
5
+ FROM node:20-alpine AS frontend-builder
6
+
7
+ WORKDIR /app/frontend
8
+ COPY frontend/package*.json ./
9
+ RUN npm ci
10
+
11
+ COPY frontend/ ./
12
+ RUN npm run build
13
+
14
+ # Build Python app
15
+ FROM python:3.12-slim AS builder
16
+
17
+ # Install uv for fast dependency resolution
18
+ RUN pip install uv
19
+
20
+ WORKDIR /app
21
+ COPY pyproject.toml ./
22
+ COPY procler/ ./procler/
23
+
24
+ # Install dependencies
25
+ RUN uv pip install --system --no-cache .
26
+
27
+ # Final image
28
+ FROM python:3.12-slim
29
+
30
+ # Install runtime dependencies
31
+ RUN apt-get update && apt-get install -y --no-install-recommends \
32
+ curl \
33
+ && rm -rf /var/lib/apt/lists/*
34
+
35
+ # Create non-root user
36
+ RUN useradd --create-home --shell /bin/bash procler
37
+ USER procler
38
+ WORKDIR /home/procler
39
+
40
+ # Copy installed packages from builder
41
+ COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
42
+ COPY --from=builder /usr/local/bin/procler /usr/local/bin/procler
43
+
44
+ # Copy frontend build
45
+ COPY --from=frontend-builder /app/frontend/dist /home/procler/static
46
+
47
+ # Copy application
48
+ COPY --chown=procler:procler procler/ /home/procler/procler/
49
+
50
+ # Copy static files to the right location
51
+ RUN mkdir -p /home/procler/procler/static && \
52
+ cp -r /home/procler/static/* /home/procler/procler/static/ 2>/dev/null || true
53
+
54
+ # Environment variables
55
+ ENV PROCLER_LOG_LEVEL=INFO
56
+ ENV PROCLER_LOG_ROTATION_INTERVAL=3600
57
+ ENV PROCLER_MAX_LOGS_PER_PROCESS=10000
58
+
59
+ # Data directory (mount as volume for persistence)
60
+ VOLUME /home/procler/.procler
61
+
62
+ # Expose port
63
+ EXPOSE 8000
64
+
65
+ # Health check
66
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \
67
+ CMD curl -f http://localhost:8000/api/health || exit 1
68
+
69
+ # Run the server
70
+ CMD ["python", "-m", "procler", "serve", "--host", "0.0.0.0", "--port", "8000"]