numux 2.9.0 → 2.10.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
@@ -256,6 +256,7 @@ Each process accepts:
256
256
  | `readyTimeout` | `number` | — | Milliseconds to wait for `readyPattern` before failing |
257
257
  | `maxRestarts` | `number` | `0` | Max auto-restart attempts on non-zero exit (0 = no restarts) |
258
258
  | `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 |
259
260
  | `condition` | `string` | — | Env var name; process skipped if falsy. Prefix with `!` to negate |
260
261
  | `platform` | `string \| string[]` | — | OS(es) this process runs on (e.g. `'darwin'`, `'linux'`). Non-matching processes are removed; dependents still start |
261
262
  | `stopSignal` | `string` | `SIGTERM` | Signal for graceful stop (`SIGTERM`, `SIGINT`, or `SIGHUP`) |
@@ -360,6 +361,24 @@ export default defineConfig({
360
361
 
361
362
  Falsy values: unset, empty string, `"0"`, `"false"`, `"no"`, `"off"` (case-insensitive). If a conditional process is skipped, its dependents are also skipped.
362
363
 
364
+ ### Optional processes
365
+
366
+ Use `optional` for tools you want visible in tabs but not auto-started (e.g. Prisma Studio, debug servers):
367
+
368
+ ```ts
369
+ export default defineConfig({
370
+ processes: {
371
+ app: { command: 'bun run dev' },
372
+ studio: {
373
+ command: 'bunx prisma studio',
374
+ optional: true, // shows as stopped tab, start with Alt+S
375
+ },
376
+ },
377
+ })
378
+ ```
379
+
380
+ Unlike `condition`, optional processes don't cascade — their dependents still start normally.
381
+
363
382
  ### Dependency orchestration
364
383
 
365
384
  Each process starts as soon as its declared `dependsOn` dependencies are ready — it does not wait for unrelated processes. If a process fails, its dependents are skipped.
package/dist/numux.js CHANGED
@@ -37,7 +37,7 @@ var __require = import.meta.require;
37
37
  var require_package = __commonJS((exports, module) => {
38
38
  module.exports = {
39
39
  name: "numux",
40
- version: "2.9.0",
40
+ version: "2.10.0",
41
41
  description: "Terminal multiplexer with dependency orchestration",
42
42
  type: "module",
43
43
  license: "MIT",
@@ -1237,6 +1237,7 @@ function validateConfig(raw, _warnings) {
1237
1237
  const processWatch = validateStringOrStringArray(p.watch);
1238
1238
  validated[name] = {
1239
1239
  command: p.command,
1240
+ ...p.optional === true ? { optional: true } : {},
1240
1241
  cwd: processCwd ?? globalCwd,
1241
1242
  env: globalEnv || processEnv ? { ...globalEnv, ...processEnv } : undefined,
1242
1243
  envFile: processEnvFile ?? globalEnvFile,
@@ -1967,6 +1968,12 @@ class ProcessManager {
1967
1968
  const launches = this.tiers.flat().map(async (name) => {
1968
1969
  const proc = this.config.processes[name];
1969
1970
  const resolve8 = readyResolvers.get(name);
1971
+ if (proc.optional) {
1972
+ this.updateStatus(name, "stopped");
1973
+ this.createRunner(name);
1974
+ resolve8();
1975
+ return;
1976
+ }
1970
1977
  const deps = proc.dependsOn ?? [];
1971
1978
  if (deps.length > 0) {
1972
1979
  await Promise.all(deps.map((d) => readyPromises.get(d)));
@@ -3529,8 +3536,8 @@ class PrefixDisplay {
3529
3536
  this.shutdown();
3530
3537
  });
3531
3538
  process.on("unhandledRejection", (reason) => {
3532
- const message = reason instanceof Error ? reason.message : String(reason);
3533
- process.stderr.write(`numux: unhandled rejection: ${message}
3539
+ const stack = reason instanceof Error ? reason.stack : String(reason);
3540
+ process.stderr.write(`numux: unhandled rejection: ${stack}
3534
3541
  `);
3535
3542
  this.shutdown();
3536
3543
  });
@@ -3941,10 +3948,10 @@ function setupShutdownHandlers(app, logWriter) {
3941
3948
  });
3942
3949
  });
3943
3950
  process.on("unhandledRejection", (reason) => {
3944
- const message = reason instanceof Error ? reason.message : String(reason);
3945
- log("Unhandled rejection:", message);
3951
+ const stack = reason instanceof Error ? reason.stack : String(reason);
3952
+ log("Unhandled rejection:", stack);
3946
3953
  app.shutdown().finally(() => {
3947
- process.stderr.write(`numux: unhandled rejection: ${message}
3954
+ process.stderr.write(`numux: unhandled rejection: ${stack}
3948
3955
  `);
3949
3956
  logWriter?.cleanup();
3950
3957
  process.exit(1);
package/dist/types.d.ts CHANGED
@@ -43,6 +43,8 @@ export interface NumuxProcessConfig<K extends string = string> {
43
43
  * @default false
44
44
  */
45
45
  interactive?: boolean;
46
+ /** Process is visible but not started automatically. Use Alt+S to start manually */
47
+ optional?: boolean;
46
48
  /** `true` = detect ANSI red output, string = regex pattern */
47
49
  errorMatcher?: boolean | string;
48
50
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "numux",
3
- "version": "2.9.0",
3
+ "version": "2.10.0",
4
4
  "description": "Terminal multiplexer with dependency orchestration",
5
5
  "type": "module",
6
6
  "license": "MIT",