taskmux 0.2.7__tar.gz → 0.3.1__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.
taskmux-0.3.1/PKG-INFO ADDED
@@ -0,0 +1,581 @@
1
+ Metadata-Version: 2.4
2
+ Name: taskmux
3
+ Version: 0.3.1
4
+ Summary: Modern tmux-based task manager for LLM development tools
5
+ Project-URL: Homepage, https://github.com/nc9/taskmux
6
+ Project-URL: Repository, https://github.com/nc9/taskmux
7
+ Project-URL: Issues, https://github.com/nc9/taskmux/issues
8
+ Author-email: Nik Cubrilovic <git@nikcub.me>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: daemon,development,manager,monitoring,session,terminal,tmux
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 :: MacOS
17
+ Classifier: Operating System :: POSIX :: Linux
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Build Tools
22
+ Classifier: Topic :: System :: Monitoring
23
+ Classifier: Topic :: Terminals
24
+ Requires-Python: >=3.11
25
+ Requires-Dist: aiofiles>=23.0.0
26
+ Requires-Dist: aiohttp>=3.9.0
27
+ Requires-Dist: libtmux>=0.37.0
28
+ Requires-Dist: pydantic>=2.0
29
+ Requires-Dist: rich>=13.0.0
30
+ Requires-Dist: tomlkit>=0.13
31
+ Requires-Dist: typer>=0.12.0
32
+ Requires-Dist: watchdog>=3.0.0
33
+ Requires-Dist: websockets>=12.0
34
+ Description-Content-Type: text/markdown
35
+
36
+ # Taskmux
37
+
38
+ A modern tmux session manager for LLM development tools with persistent logs, JSON output, health monitoring, restart policies, event history, and WebSocket API.
39
+
40
+ ## Why Taskmux?
41
+
42
+ LLM coding tools like Claude Code and Cursor struggle with background tasks. Taskmux provides an LLM-friendly CLI for managing multiple background processes — restarting, checking status, reading logs — all from within your AI coding environment. Every command supports `--json` for programmatic consumption, logs persist to disk with timestamps, and all lifecycle events are recorded for debugging.
43
+
44
+ ## Installation
45
+
46
+ ### Prerequisites
47
+
48
+ - [tmux](https://github.com/tmux/tmux)
49
+ - [uv](https://docs.astral.sh/uv/) (Python 3.11+)
50
+
51
+ ### Install
52
+
53
+ ```bash
54
+ # Recommended (global install)
55
+ uv tool install taskmux
56
+
57
+ # From source
58
+ git clone https://github.com/nc9/taskmux
59
+ cd taskmux
60
+ uv tool install .
61
+ ```
62
+
63
+ ## Quick Start
64
+
65
+ ```bash
66
+ # Initialize in your project (creates taskmux.toml, injects agent context)
67
+ taskmux init
68
+
69
+ # Add tasks
70
+ taskmux add server "npm run dev"
71
+ taskmux add build "npm run build:watch"
72
+ taskmux add db "docker compose up postgres"
73
+
74
+ # Start all auto_start tasks
75
+ taskmux start
76
+
77
+ # Check status
78
+ taskmux status
79
+ ```
80
+
81
+ Or create a `taskmux.toml` manually:
82
+
83
+ ```toml
84
+ name = "myproject"
85
+
86
+ [hooks]
87
+ before_start = "echo starting stack"
88
+ after_stop = "echo stack stopped"
89
+
90
+ [tasks.server]
91
+ command = "npm run dev"
92
+
93
+ [tasks.server.hooks]
94
+ before_start = "npm run build"
95
+
96
+ [tasks.build]
97
+ command = "npm run build:watch"
98
+
99
+ [tasks.test]
100
+ command = "npm run test:watch"
101
+
102
+ [tasks.db]
103
+ command = "docker compose up postgres"
104
+ auto_start = false
105
+ ```
106
+
107
+ ## Full Example
108
+
109
+ A full-stack app with a database, API server, and frontend — using health checks to ensure each service is ready before starting its dependents:
110
+
111
+ ```toml
112
+ name = "fullstack-app"
113
+
114
+ [tasks.db]
115
+ command = "docker compose up postgres redis"
116
+ health_check = "pg_isready -h localhost -p 5432"
117
+ health_interval = 3
118
+
119
+ [tasks.migrate]
120
+ command = "python manage.py migrate && echo 'done' && sleep infinity"
121
+ cwd = "apps/api"
122
+ depends_on = ["db"]
123
+ health_check = "test -f .migrate-complete"
124
+
125
+ [tasks.api]
126
+ command = "python manage.py runserver 0.0.0.0:8000"
127
+ cwd = "apps/api"
128
+ port = 8000
129
+ depends_on = ["migrate"]
130
+ health_check = "curl -sf http://localhost:8000/health"
131
+ stop_grace_period = 10
132
+
133
+ [tasks.worker]
134
+ command = "celery -A myapp worker -l info"
135
+ cwd = "apps/api"
136
+ depends_on = ["db"]
137
+ restart_policy = "always"
138
+ max_restarts = 10
139
+ restart_backoff = 3.0
140
+
141
+ [tasks.web]
142
+ command = "bun dev"
143
+ cwd = "apps/web"
144
+ port = 3000
145
+ depends_on = ["api"]
146
+ health_check = "curl -sf http://localhost:3000"
147
+
148
+ [tasks.storybook]
149
+ command = "bun storybook"
150
+ cwd = "apps/web"
151
+ auto_start = false
152
+ ```
153
+
154
+ What happens on `taskmux start`:
155
+
156
+ 1. **db** starts first (no dependencies)
157
+ 2. **migrate** and **worker** wait for db's health check (`pg_isready`) to pass
158
+ 3. **api** waits for migrate's health check
159
+ 4. **web** waits for api's health check (`curl localhost:8000/health`)
160
+ 5. **storybook** is skipped (`auto_start = false`) — start it manually with `taskmux start storybook`
161
+
162
+ ```bash
163
+ taskmux start # Starts everything in dependency order
164
+ taskmux logs # Interleaved logs from all tasks (persistent, timestamped)
165
+ taskmux logs -g "ERROR" # Grep all tasks for errors
166
+ taskmux logs api --since 5m # API logs from last 5 minutes
167
+ taskmux logs -f api # Follow API logs live
168
+ taskmux status --json # Machine-readable status for agents
169
+ taskmux health --json # Health check as JSON
170
+ taskmux events --task worker # Lifecycle events for the worker
171
+ taskmux inspect api # JSON state for a single task
172
+ taskmux restart worker # Restart just the worker
173
+ taskmux start storybook # Start a manual task
174
+ ```
175
+
176
+ ## Commands
177
+
178
+ All commands support `--json` for machine-readable output (see [JSON Output](#json-output)).
179
+
180
+ ```bash
181
+ # Session lifecycle
182
+ taskmux start # Start all auto_start tasks in dependency order
183
+ taskmux start <task> [task2...] # Start specific tasks
184
+ taskmux start -m # Start + stay in foreground monitoring health/restarting
185
+ taskmux stop # Stop all (C-c → SIGTERM → SIGKILL), prevents auto-restart
186
+ taskmux stop <task> [task2...] # Stop specific tasks
187
+ taskmux restart # Restart all tasks
188
+ taskmux restart <task> [task2...] # Restart specific tasks, re-enables auto-restart
189
+
190
+ # Task management
191
+ taskmux kill <task> # Hard-kill (SIGKILL + destroy window), prevents auto-restart
192
+ taskmux add <task> "<command>" # Add task to taskmux.toml
193
+ taskmux remove <task> # Remove task (kills if running)
194
+ taskmux inspect <task> # JSON state: pid, health, restart_policy, pane info
195
+
196
+ # Status & health
197
+ taskmux status # Session + task overview (aliases: list, ls)
198
+ taskmux health # Health check table for all tasks
199
+
200
+ # Logs (persistent, timestamped — stored at ~/.taskmux/logs/)
201
+ taskmux logs # Interleaved logs from all tasks
202
+ taskmux logs <task> # Recent logs for a task
203
+ taskmux logs -f [task] # Follow logs live (colored prefixes)
204
+ taskmux logs -n 200 <task> # Last N lines
205
+ taskmux logs -g "error" # Grep all tasks
206
+ taskmux logs <task> -g "err" -C 5 # Grep one task with context
207
+ taskmux logs --since 5m # Logs from last 5 minutes
208
+ taskmux logs --since "2024-01-01T14:00" # Logs since timestamp
209
+ taskmux logs-clean # Delete all log files for this session
210
+ taskmux logs-clean <task> # Delete logs for a specific task
211
+
212
+ # Event history (stored at ~/.taskmux/events.jsonl)
213
+ taskmux events # Recent lifecycle events (last 50)
214
+ taskmux events --task server # Filter by task
215
+ taskmux events --since 1h # Events from last hour
216
+ taskmux events -n 100 # Show more events
217
+
218
+ # Setup & monitoring
219
+ taskmux init # Interactive project setup + agent context injection
220
+ taskmux init --defaults # Non-interactive setup
221
+ taskmux watch # Watch taskmux.toml, reload on change
222
+ taskmux daemon --port 8765 # Daemon mode: WebSocket API + health monitoring
223
+ ```
224
+
225
+ ### stop vs kill vs restart
226
+
227
+ | Command | Signal | Window | Auto-restart |
228
+ |---------|--------|--------|--------------|
229
+ | `stop` | C-c → SIGTERM → SIGKILL (graceful) | Stays alive | Blocked (manually stopped) |
230
+ | `kill` | SIGKILL (immediate) | Destroyed | Blocked (manually stopped) |
231
+ | `restart` | Full stop + restart | Reused | Re-enabled |
232
+
233
+ Both `stop` and `kill` mark the task as **manually stopped**, preventing auto-restart even with `restart_policy = "always"`. Use `restart` or `start` to clear this flag and re-enable auto-restart.
234
+
235
+ ## Configuration
236
+
237
+ ### Format
238
+
239
+ Config file is `taskmux.toml` in the current directory:
240
+
241
+ ```toml
242
+ name = "session-name"
243
+ auto_start = true # global toggle, default true
244
+
245
+ [hooks]
246
+ before_start = "echo starting"
247
+ after_stop = "echo done"
248
+
249
+ [tasks.server]
250
+ command = "python manage.py runserver"
251
+ cwd = "apps/api"
252
+ port = 8000
253
+ health_check = "curl -sf http://localhost:8000/health"
254
+ stop_grace_period = 10
255
+ depends_on = ["db"]
256
+
257
+ [tasks.server.hooks]
258
+ before_start = "python manage.py migrate"
259
+
260
+ [tasks.db]
261
+ command = "docker compose up postgres"
262
+ health_check = "pg_isready -h localhost"
263
+
264
+ [tasks.worker]
265
+ command = "celery worker -A myapp"
266
+ depends_on = ["db"]
267
+ restart_policy = "always"
268
+ max_restarts = 10
269
+
270
+ [tasks.tailwind]
271
+ command = "npx tailwindcss -w"
272
+ auto_start = false
273
+ restart_policy = "no"
274
+ ```
275
+
276
+ ### Fields
277
+
278
+ | Field | Default | Description |
279
+ |-------|---------|-------------|
280
+ | `name` | `"taskmux"` | tmux session name |
281
+ | `auto_start` | `true` | Global toggle — if false, `start` creates session but launches nothing |
282
+ | `hooks.before_start` | — | Run before starting tasks |
283
+ | `hooks.after_start` | — | Run after starting tasks |
284
+ | `hooks.before_stop` | — | Run before stopping tasks |
285
+ | `hooks.after_stop` | — | Run after stopping tasks |
286
+ | `tasks.<name>.command` | — | Shell command to run |
287
+ | `tasks.<name>.auto_start` | `true` | Start with `taskmux start` |
288
+ | `tasks.<name>.cwd` | — | Working directory for the task |
289
+ | `tasks.<name>.port` | — | Port to clean up before starting (kills orphaned listeners) |
290
+ | `tasks.<name>.health_check` | — | Shell command to check health (exit 0 = healthy) |
291
+ | `tasks.<name>.health_interval` | `10` | Seconds between health checks |
292
+ | `tasks.<name>.health_timeout` | `5` | Seconds before health check times out |
293
+ | `tasks.<name>.health_retries` | `3` | Consecutive health failures before triggering a restart |
294
+ | `tasks.<name>.stop_grace_period` | `5` | Seconds to wait after C-c before escalating to SIGTERM |
295
+ | `tasks.<name>.restart_policy` | `"on-failure"` | When to auto-restart: `"no"`, `"on-failure"`, or `"always"` (see below) |
296
+ | `tasks.<name>.max_restarts` | `5` | Max auto-restarts before giving up (resets after 60s healthy) |
297
+ | `tasks.<name>.restart_backoff` | `2.0` | Exponential backoff base for restart delay (1s, 2s, 4s… capped at 60s) |
298
+ | `tasks.<name>.log_file` | — | Override log file path (default: `~/.taskmux/logs/{session}/{task}.log`) |
299
+ | `tasks.<name>.log_max_size` | `"10MB"` | Max log file size before rotation (e.g. `"500KB"`, `"1GB"`) |
300
+ | `tasks.<name>.log_max_files` | `3` | Number of rotated log files to keep |
301
+ | `tasks.<name>.depends_on` | `[]` | Task names that must be healthy before this task starts |
302
+ | `tasks.<name>.hooks.*` | — | Per-task lifecycle hooks (same fields as global) |
303
+
304
+ ### Dependency Ordering
305
+
306
+ Tasks with `depends_on` are started in topological order. Before starting a task, taskmux waits for each dependency's health check to pass (up to `health_retries * health_interval` seconds). If a dependency never becomes healthy, the dependent task is skipped with a warning.
307
+
308
+ Circular dependencies and references to nonexistent tasks are rejected at config load time.
309
+
310
+ When starting a single task with `taskmux start <task>`, dependencies are not auto-started — you get a warning if they aren't running.
311
+
312
+ ### Restart Policies
313
+
314
+ Each task has a `restart_policy` that controls automatic restart behavior. Restart policies are enforced by `taskmux start --monitor` and `taskmux daemon`.
315
+
316
+ | Policy | Behavior |
317
+ |--------|----------|
318
+ | `"no"` | Never auto-restart. Task stays stopped after crash or health failure. |
319
+ | `"on-failure"` | **(default)** Restart on crash (process exits) or after `health_retries` consecutive health check failures. |
320
+ | `"always"` | Restart whenever the task stops, including clean exits. |
321
+
322
+ **Manual stops override all policies.** Running `taskmux stop` or `taskmux kill` marks the task as manually stopped — it will not auto-restart even with `restart_policy = "always"`. Use `taskmux restart` or `taskmux start` to clear this flag.
323
+
324
+ **`restart_policy` vs `auto_start`** — these are orthogonal. `auto_start` controls whether a task launches on `taskmux start`. `restart_policy` controls what happens after a running task exits or fails. A task with `auto_start = false` and `restart_policy = "always"` won't start automatically, but once started manually, it will auto-restart on exit.
325
+
326
+ | `restart_policy` | `auto_start` | Behavior |
327
+ |---|---|---|
328
+ | `"no"` | `true` | Starts with session, never auto-restarts |
329
+ | `"no"` | `false` | Manual start only, never auto-restarts |
330
+ | `"on-failure"` | `true` | Starts with session, restarts on crash/health failure |
331
+ | `"on-failure"` | `false` | Manual start, restarts on crash/health failure once running |
332
+ | `"always"` | `true` | Starts with session, restarts on any exit |
333
+ | `"always"` | `false` | Manual start, restarts on any exit once running |
334
+
335
+ **Backoff & limits:** When a task keeps failing, restart delays increase exponentially: `restart_backoff ^ attempt` seconds (capped at 60s). After `max_restarts` consecutive restarts, the task is left stopped. The restart counter resets after 60 seconds of healthy uptime.
336
+
337
+ ### Health Checks
338
+
339
+ If `health_check` is set, taskmux runs it as a shell command. Exit code 0 means healthy. If not set, taskmux falls back to checking if the tmux pane has a running process (not just a shell prompt).
340
+
341
+ A task must fail `health_retries` consecutive health checks (default 3) before being considered unhealthy and triggering a restart. If the task becomes healthy again, the failure counter resets.
342
+
343
+ Health checks are used by:
344
+ - `taskmux health` — shows a table of all task health
345
+ - `taskmux start` — waits for dependencies to be healthy before starting dependents
346
+ - `taskmux start --monitor` — continuously monitors and auto-restarts per restart_policy
347
+ - `taskmux daemon` — same as --monitor, plus WebSocket API and config watching
348
+
349
+ ### Hook Cascade
350
+
351
+ Hooks fire in this order:
352
+ 1. **Start**: global `before_start` → task `before_start` → _run command_ → task `after_start` → global `after_start`
353
+ 2. **Stop**: global `before_stop` → task `before_stop` → _send C-c_ → task `after_stop` → global `after_stop`
354
+
355
+ If a `before_*` hook fails (non-zero exit), the action is aborted.
356
+
357
+ ### Process Lifecycle
358
+
359
+ Taskmux ensures processes are fully stopped before restarting and that orphaned port listeners don't block new starts.
360
+
361
+ **Stop escalation** (`stop`, `restart`):
362
+
363
+ 1. **C-c** (SIGINT) — waits `stop_grace_period` seconds (default 5)
364
+ 2. **SIGTERM** to process group — waits 3 seconds
365
+ 3. **SIGKILL** to process group — force kill
366
+
367
+ **Port cleanup** (`start`, `restart`): If `port` is configured, taskmux kills any process listening on that port before starting. This handles orphaned processes from crashed sessions.
368
+
369
+ **Auto-restart** (`start --monitor`, `daemon`): Tasks with `restart_policy = "on-failure"` or `"always"` are automatically restarted. Health checks must fail `health_retries` times before triggering a restart. Restart delays increase exponentially (`restart_backoff` base, capped at 60s). After `max_restarts` failures, the task is left stopped. The counter resets after 60 seconds of healthy uptime.
370
+
371
+ ### Init & Agent Context
372
+
373
+ `taskmux init` bootstraps your project:
374
+ 1. Creates `taskmux.toml` with session name (defaults to directory name)
375
+ 2. Detects installed AI coding agents (Claude, Codex, OpenCode)
376
+ 3. Injects taskmux usage instructions into agent context files:
377
+ - Claude: `.claude/rules/taskmux.md`
378
+ - Codex/OpenCode: `AGENTS.md`
379
+
380
+ Use `--defaults` to skip prompts (CI/automation).
381
+
382
+ ### Inspect
383
+
384
+ `taskmux inspect <task>` returns JSON with task state:
385
+
386
+ ```json
387
+ {
388
+ "name": "api",
389
+ "command": "python manage.py runserver 0.0.0.0:8000",
390
+ "auto_start": true,
391
+ "restart_policy": "on-failure",
392
+ "log_file": "/home/user/.taskmux/logs/myproject/api.log",
393
+ "cwd": "apps/api",
394
+ "health_check": "curl -sf http://localhost:8000/health",
395
+ "depends_on": ["db"],
396
+ "running": true,
397
+ "healthy": true,
398
+ "pid": "12345",
399
+ "pane_current_command": "python",
400
+ "pane_current_path": "/home/user/project/apps/api",
401
+ "window_id": "@1",
402
+ "pane_id": "%1"
403
+ }
404
+ ```
405
+
406
+ ### Persistent Logs
407
+
408
+ Task output is automatically piped to timestamped log files at `~/.taskmux/logs/{session}/{task}.log` using tmux's `pipe-pane`. Logs persist after session kill, survive tmux scrollback overflow, and include UTC timestamps on every line:
409
+
410
+ ```
411
+ 2024-01-01T14:00:00.123 Server started on port 3000
412
+ 2024-01-01T14:00:01.456 GET /health 200 2ms
413
+ 2024-01-01T14:00:05.789 Connected to database
414
+ ```
415
+
416
+ **Time-based filtering** with `--since`:
417
+
418
+ ```bash
419
+ taskmux logs server --since 5m # last 5 minutes
420
+ taskmux logs --since 1h # all tasks, last hour
421
+ taskmux logs api --since "2024-01-01T14:00" # since ISO timestamp
422
+ ```
423
+
424
+ **Log rotation:** When a log file exceeds `log_max_size` (default 10MB), it rotates: `task.log` → `task.log.1` → `task.log.2`, keeping up to `log_max_files` (default 3) rotated files.
425
+
426
+ **Cleanup:**
427
+
428
+ ```bash
429
+ taskmux logs-clean # delete all logs for this session
430
+ taskmux logs-clean server # delete only server's logs
431
+ ```
432
+
433
+ When log files exist, `taskmux logs` reads from them (full history with timestamps). Falls back to tmux scrollback for tasks started before log persistence was enabled.
434
+
435
+ ### JSON Output
436
+
437
+ Every command supports `--json` for machine-readable output. This makes taskmux fully programmable by coding agents and scripts.
438
+
439
+ ```bash
440
+ taskmux status --json
441
+ taskmux health --json
442
+ taskmux start server --json
443
+ taskmux logs server --json
444
+ taskmux events --json
445
+ ```
446
+
447
+ **Status:**
448
+
449
+ ```json
450
+ {
451
+ "session": "myproject",
452
+ "running": true,
453
+ "active_tasks": 3,
454
+ "tasks": [
455
+ {
456
+ "name": "server",
457
+ "running": true,
458
+ "healthy": true,
459
+ "command": "npm run dev",
460
+ "port": 3000,
461
+ "restart_policy": "on-failure"
462
+ }
463
+ ]
464
+ }
465
+ ```
466
+
467
+ **Health:**
468
+
469
+ ```json
470
+ {
471
+ "healthy_count": 2,
472
+ "total_count": 3,
473
+ "tasks": [
474
+ {"name": "server", "healthy": true},
475
+ {"name": "worker", "healthy": false}
476
+ ]
477
+ }
478
+ ```
479
+
480
+ **Action commands** (`start`, `stop`, `restart`, `kill`, `add`, `remove`):
481
+
482
+ ```json
483
+ {"ok": true, "task": "server", "action": "started"}
484
+ ```
485
+
486
+ **Logs** (non-follow):
487
+
488
+ ```json
489
+ {"task": "server", "lines": ["2024-01-01T14:00:00.123 Listening on :3000"]}
490
+ ```
491
+
492
+ **Errors:**
493
+
494
+ ```json
495
+ {"ok": false, "error": "Task 'ghost' not found in config"}
496
+ ```
497
+
498
+ ### Event History
499
+
500
+ Taskmux records lifecycle events to `~/.taskmux/events.jsonl`:
501
+
502
+ ```bash
503
+ taskmux events # recent events
504
+ taskmux events --task server # filter by task
505
+ taskmux events --since 10m # last 10 minutes
506
+ taskmux events -n 100 --json # last 100 as JSON
507
+ ```
508
+
509
+ **Recorded events:**
510
+
511
+ | Event | Trigger |
512
+ |-------|---------|
513
+ | `task_started` | `start` command |
514
+ | `task_stopped` | `stop` command |
515
+ | `task_restarted` | `restart` command |
516
+ | `task_killed` | `kill` command |
517
+ | `session_started` | `start` (all tasks) |
518
+ | `session_stopped` | `stop` (all tasks) |
519
+ | `health_check_failed` | Health check fails (includes attempt count) |
520
+ | `auto_restart` | Auto-restart triggered (includes reason) |
521
+ | `max_restarts_reached` | Task hit max_restarts limit |
522
+ | `config_reloaded` | Config file changed (daemon/watch mode) |
523
+
524
+ **Example output:**
525
+
526
+ ```
527
+ 2024-01-01T14:00:00 [server] task_started
528
+ 2024-01-01T14:05:00 [server] health_check_failed (attempt=1)
529
+ 2024-01-01T14:05:30 [server] health_check_failed (attempt=2)
530
+ 2024-01-01T14:06:00 [server] health_check_failed (attempt=3)
531
+ 2024-01-01T14:06:00 [server] auto_restart (reason=health_retries_exceeded)
532
+ ```
533
+
534
+ The events file auto-rotates, trimming to 10,000 lines when it exceeds 15,000.
535
+
536
+ ## Monitoring & Auto-restart
537
+
538
+ ### start --monitor (lightweight)
539
+
540
+ Start tasks and stay in the foreground monitoring health:
541
+
542
+ ```bash
543
+ taskmux start --monitor # or: taskmux start -m
544
+ ```
545
+
546
+ Checks health every 30 seconds and auto-restarts tasks according to their `restart_policy`. No WebSocket API — just monitoring and restart. Press Ctrl+C to stop monitoring (tasks keep running).
547
+
548
+ ### Daemon Mode (full)
549
+
550
+ Run as a background daemon with WebSocket API, config watching, and auto-restart:
551
+
552
+ ```bash
553
+ taskmux daemon # Default port 8765
554
+ taskmux daemon --port 9000 # Custom port
555
+ ```
556
+
557
+ The daemon monitors task health every 30 seconds. Tasks are restarted per their `restart_policy` with exponential backoff (controlled by `restart_backoff` and `max_restarts`). Tasks that stay healthy for 60+ seconds have their restart counter reset. Config file changes are detected and applied automatically.
558
+
559
+ WebSocket API:
560
+
561
+ ```javascript
562
+ const ws = new WebSocket('ws://localhost:8765');
563
+
564
+ ws.send(JSON.stringify({ command: "status" }));
565
+ ws.send(JSON.stringify({ command: "restart", params: { task: "server" } }));
566
+ ws.send(JSON.stringify({ command: "logs", params: { task: "server", lines: 50 } }));
567
+ ```
568
+
569
+ ## Tmux Integration
570
+
571
+ Taskmux creates standard tmux sessions — all tmux commands work:
572
+
573
+ ```bash
574
+ tmux attach-session -t myproject # Attach to session
575
+ tmux list-sessions # List all sessions
576
+ # Ctrl+b 1/2/3 to switch windows, Ctrl+b d to detach
577
+ ```
578
+
579
+ ## License
580
+
581
+ MIT