numux 2.10.3 → 2.11.0

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.
package/README.md CHANGED
@@ -69,13 +69,16 @@ numux
69
69
 
70
70
  ### Subcommands
71
71
 
72
+ <!-- generated:subcommands -->
72
73
  ```sh
73
- numux init # Create a starter numux.config.ts
74
- numux validate # Validate config and show process dependency graph
75
- numux exec <name> [--] <command> # Run a command in a process's environment
76
- numux logs [name] # Open log directory or view a process log
74
+ numux init # Create a starter config file
75
+ numux validate # Validate config and show process graph
76
+ numux exec <name> [--] <cmd> # Run a command in a process's environment
77
+ numux logs [name] # Open the log directory or a specific process log
77
78
  numux completions <shell> # Generate shell completions (bash, zsh, fish)
79
+ numux help [topic] # Show help for a topic
78
80
  ```
81
+ <!-- /generated:subcommands -->
79
82
 
80
83
  `validate` respects `--only`/`--exclude` filters and shows processes grouped by dependency tiers.
81
84
 
@@ -144,11 +147,45 @@ numux 'dev:*' # all scripts matching dev:*
144
147
  numux 'npm:*:dev' # explicit npm: prefix (same behavior)
145
148
  ```
146
149
 
147
- `*` does not match across `:` separators (like `/` in file paths), so `format:*` matches `format:store` but not `format:check:store`. Use `format:*:*` to match two levels deep.
150
+ <!-- generated:script-pattern-rules -->
151
+ ## Script pattern rules
148
152
 
149
- Append `^` to skip scripts that act as group runners scripts that have sub-scripts beneath them. For example, if `format:check` runs `numux 'format:check:*'` internally, then `format:*^` excludes it (because `format:check:store` and `format:check:odoo` exist as sub-scripts), avoiding duplicate runs.
153
+ **Recognition:** A process name is treated as a script reference when it:
154
+ - starts with `npm:` (e.g. `npm:dev:*`)
155
+ - contains glob metacharacters (`*`, `?`, `[`)
156
+ - contains a colon AND has no explicit `command` (e.g. `lint:eslint: {}`)
150
157
 
151
- Extra arguments after the pattern are forwarded to each matched command:
158
+ **Glob matching:** Patterns are matched against `package.json` scripts using
159
+ `Bun.Glob`. The `*` wildcard does NOT match across `:` separators — `dev:*`
160
+ matches `dev:web` but not `dev:web:hmr`. Use `dev:*:*` for two levels deep.
161
+
162
+ **Leaf-only (`^`):** Append `^` to skip scripts that are group runners —
163
+ scripts that have sub-scripts beneath them. E.g. if `format:check` has
164
+ `format:check:store` and `format:check:odoo` below it, `format:*^` excludes
165
+ `format:check` but keeps the leaf scripts.
166
+
167
+ **Extra args:** Anything after the first space in the pattern is forwarded
168
+ as extra arguments to each matched command: `lint:* --fix` → `bun run lint:js -- --fix`.
169
+
170
+ **Template inheritance:** Config properties on a pattern entry (color, env,
171
+ dependsOn, etc.) are inherited by all expanded processes. Color arrays are
172
+ distributed round-robin across matches.
173
+
174
+ **Display names:** The glob's literal prefix and suffix are stripped from
175
+ matched script names: `dev:*` + `dev:web` → display name `web`.
176
+
177
+ ## Auto-resolution
178
+
179
+ When a process has no `command` and its name matches a `package.json` script,
180
+ the command is auto-resolved to `<pm> run <name>`. This works for:
181
+ - `true` or `{}` shorthand: `lint: true` → `bun run lint`
182
+ - Objects without `command`: `typecheck: { dependsOn: ['db'] }` → `bun run typecheck`
183
+
184
+ ## npm: prefix
185
+
186
+ Commands starting with `npm:` are rewritten to use the detected package
187
+ manager: `npm:dev` → `bun run dev` (if bun is detected).
188
+ <!-- /generated:script-pattern-rules -->
152
189
 
153
190
  ```sh
154
191
  numux 'lint:* --fix' # → bun run lint:js --fix, bun run lint:ts --fix
@@ -165,9 +202,7 @@ export default defineConfig({
165
202
  })
166
203
  ```
167
204
 
168
- Template properties (color, env, dependsOn, etc.) are inherited by all matched processes. Colors given as an array are distributed round-robin.
169
-
170
- When a process has no command and its name matches a `package.json` script, the command is auto-resolved:
205
+ Auto-resolution example:
171
206
 
172
207
  ```ts
173
208
  export default defineConfig({
@@ -181,24 +216,29 @@ export default defineConfig({
181
216
 
182
217
  ### Options
183
218
 
219
+ <!-- generated:options -->
184
220
  | Flag | Description |
185
221
  |------|-------------|
186
- | `-w, --workspace <script>` | Run a script across all workspaces |
187
- | `-c, --config <path>` | Explicit config file path |
188
- | `-n, --name <name=cmd>` | Add a named process (repeatable) |
189
- | `-p, --prefix` | Prefixed output mode (no TUI, for CI/scripts) |
190
- | `--only <a,b,...>` | Only run these processes (+ their dependencies) |
191
- | `--exclude <a,b,...>` | Exclude these processes |
222
+ | `-s,` `--sort` `<config|alphabetical|topological>` | Tab display order |
223
+ | `-w,` `--workspace` `<script>` | Run a package.json script across all workspaces |
224
+ | `-n,` `--name` `<name=command>` | Add a named process |
225
+ | `-c,` `--color` `<colors>` | Comma-separated colors (hex or names: black, red, green, yellow, blue, magenta, cyan, white, gray, orange, purple) |
226
+ | `--colors` | Auto-assign colors to processes based on their name |
227
+ | `-e,` `--env-file` `<path|false>` | Env file path, or "false" to disable env file loading |
228
+ | `--config` `<path>` | Config file path (default: auto-detect) |
229
+ | `-p,` `--prefix` | Prefixed output mode (no TUI, for CI/scripts) |
230
+ | `--only` `<a,b,...>` | Only run these processes (+ their dependencies) |
231
+ | `--exclude` `<a,b,...>` | Exclude these processes |
192
232
  | `--kill-others` | Kill all processes when any exits (regardless of exit code) |
193
- | `--kill-others-on-fail` | Kill all processes when any exits with a non-zero exit code |
194
- | `--max-restarts <n>` | Max auto-restarts for crashed processes |
195
- | `-s, --sort <mode>` | Tab display order: `config` (default), `alphabetical`, `topological` |
196
- | `--no-watch` | Disable file watching even if config has `watch` patterns |
197
- | `-t, --timestamps [format]` | Add timestamps (default `HH:mm:ss`). Works in both prefix and TUI mode. Pass a format string for custom output (e.g. `HH:mm:ss.SSS`). Toggle in TUI with `T` |
198
- | `--log-dir <path>` | Persist logs to timestamped subdirs (`<path>/<timestamp>/<name>.log`) with a `latest` symlink. Path is printed on exit |
199
- | `--debug` | Log to `.numux/debug.log` |
200
- | `-h, --help` | Show help |
201
- | `-v, --version` | Show version |
233
+ | `--kill-others-on-fail` | Kill all processes when any exits with non-zero code |
234
+ | `--max-restarts` `<n>` | Max auto-restarts for crashed processes |
235
+ | `--no-watch` | Disable file watching even if config has watch patterns |
236
+ | `-t,` `--timestamps` `[<format>]` | Add timestamps to output (default HH:mm:ss, or pass a format string) |
237
+ | `--log-dir` `<path>` | Write per-process logs to directory |
238
+ | `--debug` | Enable debug logging to .numux/debug.log |
239
+ | `-h,` `--help` | Show this help |
240
+ | `-v,` `--version` | Show version |
241
+ <!-- /generated:options -->
202
242
 
203
243
  ### Prefix mode
204
244
 
@@ -216,18 +256,26 @@ Auto-exits when all processes finish. Exit code 1 if any process failed.
216
256
 
217
257
  Top-level options apply to all processes (process-level settings override):
218
258
 
259
+ <!-- generated:config-global -->
219
260
  | Field | Type | Description |
220
261
  |-------|------|-------------|
221
- | `cwd` | `string` | Working directory for all processes (process `cwd` overrides) |
222
- | `env` | `Record<string, string>` | Environment variables merged into all processes (process `env` overrides per key) |
223
- | `envFile` | `string \| string[] \| false` | `.env` file(s) for all processes (process `envFile` replaces if set; `false` disables) |
224
- | `showCommand` | `boolean` | Print the command being run as the first line of output (default: `true`) |
225
- | `maxRestarts` | `number` | Restart limit for all processes (default: `0`) |
226
- | `readyTimeout` | `number` | Ready timeout in ms for all processes |
227
- | `stopSignal` | `'SIGTERM' \| 'SIGINT' \| 'SIGHUP'` | Stop signal for all processes (default: `'SIGTERM'`) |
228
- | `errorMatcher` | `boolean \| string` | Error detection for all processes (`true` = ANSI red, string = regex) |
229
- | `watch` | `string \| string[]` | Watch patterns for all processes (process `watch` replaces if set) |
230
- | `sort` | `'config' \| 'alphabetical' \| 'topological'` | Tab display order (default: `'config'` definition order) |
262
+ | `cwd` | `string` | Global working directory, inherited by all processes |
263
+ | `env` | `Record<string, string>` | Global env vars, merged into each process (process-level overrides) |
264
+ | `envFile` | `string \| string[] \| false` | Global .env file(s), inherited by processes without their own envFile; `false` disables |
265
+ | `showCommand` | `boolean` | Global showCommand flag, inherited by all processes |
266
+ | `maxRestarts` | `number` | Global restart limit, inherited by all processes (only restarts on non-zero exit) |
267
+ | `readyTimeout` | `number` | Global ready timeout (ms), inherited by all processes |
268
+ | `stopSignal` | `'SIGTERM' \| 'SIGINT' \| 'SIGHUP'` | Global stop signal, inherited by all processes |
269
+ | `errorMatcher` | `boolean \| string` | Global error matcher, inherited by all processes. `true` = detect ANSI red output, string = regex |
270
+ | `watch` | `string \| string[]` | Global watch patterns, inherited by processes without their own watch |
271
+ | `sort` | `'config' \| 'alphabetical' \| 'topological'` | Tab display order. `'config'` preserves definition order (package.json script order for wildcards), `'alphabetical'` sorts by process name, `'topological'` sorts by dependency tiers. |
272
+ | `prefix` | `boolean` | Use prefixed output mode instead of TUI (for CI/scripts) |
273
+ | `timestamps` | `boolean \| string` | Add timestamps to output lines. `true` uses default `HH:mm:ss` format, or pass a format string (e.g. `"HH:mm:ss.SSS"`) |
274
+ | `killOthers` | `boolean` | Kill all processes when any one exits (regardless of exit code) |
275
+ | `killOthersOnFail` | `boolean` | Kill all processes when any one exits with a non-zero exit code |
276
+ | `noWatch` | `boolean` | Disable file watching even if processes have watch patterns |
277
+ | `logDir` | `string` | Directory to write per-process log files |
278
+ <!-- /generated:config-global -->
231
279
 
232
280
  ```ts
233
281
  export default defineConfig({
@@ -245,27 +293,29 @@ export default defineConfig({
245
293
 
246
294
  Each process accepts:
247
295
 
296
+ <!-- generated:config-process -->
248
297
  | Field | Type | Default | Description |
249
298
  |-------|------|---------|-------------|
250
299
  | `command` | `string` | *required* | Shell command to run. Supports `$dep.group` references from dependency capture groups |
251
- | `cwd` | `string` | `process.cwd()` | Working directory |
252
- | `env` | `Record<string, string>` | — | Extra environment variables. Values support `$dep.group` references from dependency capture groups |
253
- | `envFile` | `string \| string[] \| false` | — | `.env` file path(s) to load (relative to `cwd`); `false` disables inherited envFile |
254
- | `dependsOn` | `string[]` | — | Processes that must be ready first |
255
- | `readyPattern` | `string \| RegExp` | — | Regex matched against stdout to signal readiness. Use `RegExp` to capture groups (see below) |
256
- | `readyTimeout` | `number` | | Milliseconds to wait for `readyPattern` before failing |
257
- | `maxRestarts` | `number` | `0` | Max auto-restart attempts on non-zero exit (0 = no restarts) |
300
+ | `cwd` | `string` | | Working directory for the process |
301
+ | `env` | `Record<string, string>` | — | Extra environment variables. Values support `$dep.group` references from dependency capture groups. |
302
+ | `envFile` | `string \| string[] \| false` | — | .env file path(s) to load, or `false` to disable |
303
+ | `dependsOn` | `string \| string[]` | — | Processes that must be ready before this one starts |
304
+ | `readyPattern` | `string \| RegExp` | — | Regex matched against stdout to signal readiness. Use `RegExp` to capture groups for `$dep.group` expansion |
305
+ | `maxRestarts` | `number` | `0` | Limit auto-restart attempts (only restarts on non-zero exit) |
306
+ | `readyTimeout` | `number` | | Milliseconds to wait for readyPattern before failing |
258
307
  | `delay` | `number` | — | Milliseconds to wait before starting the process |
259
- | `optional` | `boolean` | `false` | Process is visible as a tab but not started automatically. Use Alt+S to start manually |
260
- | `condition` | `string` | — | Env var name; process skipped if falsy. Prefix with `!` to negate |
261
- | `platform` | `string \| string[]` | | OS(es) this process runs on (e.g. `'darwin'`, `'linux'`). Non-matching processes are removed; dependents still start |
262
- | `stopSignal` | `string` | `SIGTERM` | Signal for graceful stop (`SIGTERM`, `SIGINT`, or `SIGHUP`) |
263
- | `color` | `string \| string[]` | auto | Hex (e.g. `"#ff6600"`) or basic name: black, red, green, yellow, blue, magenta, cyan, white, gray, orange, purple |
308
+ | `condition` | `string` | | Env var name (prefix with `!` to negate); process skipped if condition is falsy |
309
+ | `platform` | `string \| string[]` | — | OS(es) this process runs on (e.g. `'darwin'`, `'linux'`). Non-matching processes are removed, their dependents still start |
310
+ | `stopSignal` | `'SIGTERM' \| 'SIGINT' \| 'SIGHUP'` | `'SIGTERM'` | Signal for graceful stop |
311
+ | `color` | `string \| string[]` | | Hex color (e.g. `"#ff6600"`) or color name. Array for round-robin in script patterns |
264
312
  | `watch` | `string \| string[]` | — | Glob patterns — restart process when matching files change |
265
- | `interactive` | `boolean` | `false` | When `true`, keyboard input is forwarded to the process |
266
- | `errorMatcher` | `boolean \| string` | — | `true` detects ANSI red output, string = regex pattern shows error indicator on tab |
313
+ | `interactive` | `boolean` | `false` | When true, keyboard input is forwarded to the process |
314
+ | `optional` | `boolean` | — | Process is visible but not started automatically. Use Alt+S to start manually |
315
+ | `errorMatcher` | `boolean \| string` | — | `true` = detect ANSI red output, string = regex pattern |
316
+ | `workspaces` | `boolean \| string \| string[]` | — | Run command in monorepo workspaces. `true` = all workspaces, string = specific workspace by name/path, string[] = multiple workspaces |
267
317
  | `showCommand` | `boolean` | `true` | Print the command being run as the first line of output |
268
- | `workspaces` | `boolean \| string \| string[]` | — | Run command in monorepo workspaces (see below) |
318
+ <!-- /generated:config-process -->
269
319
 
270
320
  ### Workspace expansion
271
321
 
@@ -417,25 +467,34 @@ Unmatched references are left as-is (the shell will expand `$db` as empty + `.po
417
467
 
418
468
  Keybindings are shown in the status bar at the bottom of the app. Panes are readonly by default — keyboard input is not forwarded to processes. Set `interactive: true` on processes that need stdin (REPLs, shells, etc.).
419
469
 
470
+ <!-- generated:keybindings -->
420
471
  | Key | Action |
421
472
  |-----|--------|
422
- | `←`/`→` or `1`-`9` | Switch tabs |
423
- | `F` | Search current pane |
424
- | `Tab` (in search) | Toggle between single-pane and all-process search |
473
+ | `←`/`→` or `1`-`9` | Tabs |
474
+ | `G/Shift+G` | Top/bottom |
475
+ | `R` | Restart |
476
+ | `S` | Stop/start |
477
+ | `F` | Search |
478
+ | `Y` | Copy all |
479
+ | `L` | Clear |
480
+ | `T` | Timestamps |
481
+ | `O` | Open logs |
482
+ | `Ctrl+Click` | Open link |
483
+ | `Ctrl+C` | Quit |
484
+ <!-- /generated:keybindings -->
485
+
486
+ Search mode (after pressing `F`):
487
+
488
+ | Key | Action |
489
+ |-----|--------|
490
+ | `Tab` | Toggle between single-pane and all-process search |
425
491
  | `Enter`/`Shift+Enter` | Next/previous match |
426
492
  | `Esc` | Exit search |
427
- | `R` | Restart current process |
428
- | `Shift+R` | Restart all processes |
429
- | `S` | Stop/start current process |
430
- | `Y` | Copy all output |
431
- | `L` | Clear pane |
432
- | `G`/`Shift+G` | Scroll to top/bottom |
433
493
  | `PageUp`/`PageDown` | Scroll by page |
434
- | `Ctrl+Click` | Open link |
435
- | `Ctrl+C` | Quit |
436
494
 
437
495
  ## Tab icons
438
496
 
497
+ <!-- generated:tab-icons -->
439
498
  | Icon | Status |
440
499
  |------|--------|
441
500
  | ○ | Pending |
@@ -444,8 +503,10 @@ Keybindings are shown in the status bar at the bottom of the app. Panes are read
444
503
  | ● | Ready |
445
504
  | ◑ | Stopping |
446
505
  | ■ | Stopped |
506
+ | ✓ | Finished |
447
507
  | ✖ | Failed |
448
508
  | ⊘ | Skipped |
509
+ <!-- /generated:tab-icons -->
449
510
 
450
511
  ## Dependencies
451
512