numux 2.7.2 → 2.9.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
@@ -73,6 +73,7 @@ numux
73
73
  numux init # Create a starter numux.config.ts
74
74
  numux validate # Validate config and show process dependency graph
75
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
76
77
  numux completions <shell> # Generate shell completions (bash, zsh, fish)
77
78
  ```
78
79
 
@@ -85,6 +86,13 @@ numux exec api -- npx prisma migrate
85
86
  numux exec web npm run build
86
87
  ```
87
88
 
89
+ `logs` prints the log directory path, or a specific process's log contents:
90
+
91
+ ```sh
92
+ numux logs # Print log directory path
93
+ numux logs api # Print the api process log
94
+ ```
95
+
88
96
  Set up completions for your shell:
89
97
 
90
98
  ```sh
package/dist/numux.js CHANGED
@@ -31,12 +31,13 @@ var __toESM = (mod, isNodeMode, target) => {
31
31
  return to;
32
32
  };
33
33
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
+ var __require = import.meta.require;
34
35
 
35
36
  // package.json
36
37
  var require_package = __commonJS((exports, module) => {
37
38
  module.exports = {
38
39
  name: "numux",
39
- version: "2.7.2",
40
+ version: "2.9.0",
40
41
  description: "Terminal multiplexer with dependency orchestration",
41
42
  type: "module",
42
43
  license: "MIT",
@@ -95,7 +96,7 @@ var require_package = __commonJS((exports, module) => {
95
96
  });
96
97
 
97
98
  // src/index.ts
98
- import { existsSync as existsSync5, writeFileSync } from "fs";
99
+ import { existsSync as existsSync6, writeFileSync } from "fs";
99
100
  import { resolve as resolve8 } from "path";
100
101
 
101
102
  // src/cli-flags.ts
@@ -300,6 +301,20 @@ var SUBCOMMANDS = [
300
301
  return "break";
301
302
  }
302
303
  },
304
+ {
305
+ name: "logs",
306
+ description: "Open the log directory or a specific process log",
307
+ usage: "logs [name]",
308
+ parse: (args, i, result) => {
309
+ result.logs = true;
310
+ const next = args[i + 1];
311
+ if (next !== undefined && !next.startsWith("-")) {
312
+ result.logsProcess = next;
313
+ i++;
314
+ }
315
+ return i;
316
+ }
317
+ },
303
318
  {
304
319
  name: "completions",
305
320
  description: "Generate shell completions (bash, zsh, fish)",
@@ -364,6 +379,7 @@ function parseArgs(argv) {
364
379
  init: false,
365
380
  validate: false,
366
381
  exec: false,
382
+ logs: false,
367
383
  prefix: false,
368
384
  killOthers: false,
369
385
  killOthersOnFail: false,
@@ -3876,6 +3892,26 @@ class LogWriter {
3876
3892
  }
3877
3893
  }
3878
3894
 
3895
+ // src/utils/project-name.ts
3896
+ import { existsSync as existsSync5, readFileSync as readFileSync5 } from "fs";
3897
+ import { tmpdir as tmpdir2 } from "os";
3898
+ import { basename as basename3, join as join2 } from "path";
3899
+ function resolveProjectName(cwd) {
3900
+ try {
3901
+ const pkgPath = join2(cwd, "package.json");
3902
+ if (existsSync5(pkgPath)) {
3903
+ const pkg = JSON.parse(readFileSync5(pkgPath, "utf-8"));
3904
+ if (typeof pkg.name === "string" && pkg.name.trim()) {
3905
+ return pkg.name.replace(/^@[^/]+\//, "").trim();
3906
+ }
3907
+ }
3908
+ } catch {}
3909
+ return basename3(cwd);
3910
+ }
3911
+ function defaultLogDir(cwd) {
3912
+ return join2(tmpdir2(), "numux", resolveProjectName(cwd));
3913
+ }
3914
+
3879
3915
  // src/utils/shutdown.ts
3880
3916
  function setupShutdownHandlers(app, logWriter) {
3881
3917
  let shuttingDown = false;
@@ -3953,7 +3989,7 @@ async function main() {
3953
3989
  }
3954
3990
  if (parsed.init) {
3955
3991
  const target = resolve8("numux.config.ts");
3956
- if (existsSync5(target)) {
3992
+ if (existsSync6(target)) {
3957
3993
  console.error(`Already exists: ${target}`);
3958
3994
  process.exit(1);
3959
3995
  }
@@ -3965,6 +4001,28 @@ async function main() {
3965
4001
  console.info(generateCompletions(parsed.completions));
3966
4002
  process.exit(0);
3967
4003
  }
4004
+ if (parsed.logs) {
4005
+ const logDir2 = parsed.logDir ?? await resolveLogDir(parsed.configPath);
4006
+ const latestDir = resolve8(logDir2, "latest");
4007
+ const target = existsSync6(latestDir) ? latestDir : logDir2;
4008
+ if (parsed.logsProcess) {
4009
+ const logFile2 = resolve8(target, `${parsed.logsProcess}.log`);
4010
+ if (!existsSync6(logFile2)) {
4011
+ const { readdirSync } = await import("fs");
4012
+ const files = readdirSync(target).filter((f) => f.endsWith(".log")).map((f) => f.replace(/\.log$/, ""));
4013
+ const available = files.length > 0 ? `Available: ${files.join(", ")}` : "No log files found";
4014
+ console.error(`No log file for "${parsed.logsProcess}". ${available}`);
4015
+ process.exit(1);
4016
+ }
4017
+ const child = Bun.spawn(["cat", logFile2], {
4018
+ stdout: "inherit",
4019
+ stderr: "inherit"
4020
+ });
4021
+ process.exit(await child.exited);
4022
+ }
4023
+ console.info(target);
4024
+ process.exit(0);
4025
+ }
3968
4026
  if (parsed.validate) {
3969
4027
  const raw = expandWorkspaces(expandScriptPatterns(await loadConfig(parsed.configPath)));
3970
4028
  const warnings2 = [];
@@ -4114,8 +4172,8 @@ async function main() {
4114
4172
  }
4115
4173
  }
4116
4174
  const manager = new ProcessManager(config);
4117
- const logDir = parsed.logDir ?? config.logDir;
4118
- const logWriter = logDir ? LogWriter.createPersistent(logDir) : LogWriter.createTemp();
4175
+ const logDir = parsed.logDir ?? config.logDir ?? defaultLogDir(process.cwd());
4176
+ const logWriter = LogWriter.createPersistent(logDir);
4119
4177
  printWarnings(warnings);
4120
4178
  const timestamps = parsed.timestamps || config.timestamps;
4121
4179
  const usePrefix = parsed.prefix || config.prefix;
@@ -4141,6 +4199,15 @@ function printWarnings(warnings) {
4141
4199
  console.warn(`Warning: process "${w.process}": ${w.message}`);
4142
4200
  }
4143
4201
  }
4202
+ async function resolveLogDir(configPath) {
4203
+ try {
4204
+ const raw = await loadConfig(configPath);
4205
+ if (typeof raw.logDir === "string" && raw.logDir.trim()) {
4206
+ return resolve8(raw.logDir.trim());
4207
+ }
4208
+ } catch {}
4209
+ return defaultLogDir(process.cwd());
4210
+ }
4144
4211
  main().catch((err) => {
4145
4212
  console.error(err instanceof Error ? err.message : err);
4146
4213
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "numux",
3
- "version": "2.7.2",
3
+ "version": "2.9.0",
4
4
  "description": "Terminal multiplexer with dependency orchestration",
5
5
  "type": "module",
6
6
  "license": "MIT",