@yamanzyan/monitorx 1.0.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 ADDED
@@ -0,0 +1,236 @@
1
+ # MonitorX
2
+
3
+ A lightweight Node.js process manager with built-in cluster support. Run, monitor, and manage your Node.js processes from the command line.
4
+
5
+ ## Features
6
+
7
+ - Start and manage multiple processes
8
+ - Node.js cluster mode — share a port across N workers with zero code changes
9
+ - Persistent state — processes restore automatically after daemon restart
10
+ - Live log streaming
11
+ - Per-process CPU and memory usage
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install -g monitorx
17
+ ```
18
+
19
+ The install script starts the MonitorX daemon in the background automatically.
20
+ This also installs two binaries:
21
+
22
+ | Binary | Purpose |
23
+ |---|---|
24
+ | `monitorx` | CLI — send commands to the daemon |
25
+ | `monitorx-daemon` | Daemon — background process that manages your apps |
26
+
27
+ ## Quick Start
28
+
29
+ **Start a process:**
30
+
31
+ ```bash
32
+ # Start a script directly
33
+ monitorx start server.js
34
+
35
+ # Start using a config file
36
+ monitorx start
37
+
38
+ # List running processes
39
+ monitorx ls
40
+ ```
41
+
42
+ If the daemon is not running, start it manually:
43
+
44
+ ```bash
45
+ monitorx-daemon --daemonize
46
+ ```
47
+
48
+ ## Commands
49
+
50
+ ### `monitorx start`
51
+
52
+ Start one or more processes.
53
+
54
+ ```bash
55
+ # Start all processes defined in monitorx.config.js
56
+ monitorx start
57
+
58
+ # Start a specific script file
59
+ monitorx start server.js
60
+
61
+ # Start a script with a custom name
62
+ monitorx start server.js -n api
63
+
64
+ # Start a stopped process by name
65
+ monitorx start api
66
+
67
+ # Start a stopped process by ID
68
+ monitorx start 3
69
+
70
+ # Start script as a cluster with 4 workers
71
+ monitorx start server.js -i 4
72
+
73
+ # Start cluster with a custom name
74
+ monitorx start server.js -n api -i 4
75
+ ```
76
+
77
+ **Flags:**
78
+
79
+ | Flag | Alias | Description |
80
+ |---|---|---|
81
+ | `-i <count>` | `--instances` | Number of cluster workers. Values > 1 enable cluster mode |
82
+ | `-n <name>` | `--name` | Custom name for the process (only for direct script starts) |
83
+
84
+ ### `monitorx stop`
85
+
86
+ Stop one or more running processes.
87
+
88
+ ```bash
89
+ # Stop all processes
90
+ monitorx stop
91
+
92
+ # Stop by name (stops all workers if cluster)
93
+ monitorx stop api
94
+
95
+ # Stop a specific process or cluster worker by ID
96
+ monitorx stop 2
97
+ ```
98
+
99
+ ### `monitorx restart`
100
+
101
+ Restart a process.
102
+
103
+ ```bash
104
+ # Restart all processes named "api"
105
+ monitorx restart api
106
+
107
+ # Restart a specific process by ID
108
+ monitorx restart 2
109
+ ```
110
+
111
+ ### `monitorx delete`
112
+
113
+ Remove processes from the registry (stops them first if running).
114
+
115
+ ```bash
116
+ # Delete all processes
117
+ monitorx delete
118
+
119
+ # Delete by name
120
+ monitorx delete api
121
+
122
+ # Delete by ID
123
+ monitorx delete 2
124
+ ```
125
+
126
+ ### `monitorx ls`
127
+
128
+ List all processes:
129
+
130
+ ```
131
+ ┌────┬──────────────────┬──────────┬───────┬─────────┬──────────────┬───────────┬──────────────┐
132
+ │ ID │ Process Name │ PID │ Mode │ Status │ Time Running │ CPU Usage │ Memory Usage │
133
+ ├────┼──────────────────┼──────────┼───────┼─────────┼──────────────┼───────────┼──────────────┤
134
+ │ 1 │ api │ 12340 │ fork │ Running │ 120s │ 0.05s │ 48 MB │
135
+ │ 2 │ worker │ 12341 │ cluster│ Running │ 60s │ 0.02s │ 32 MB │
136
+ │ 3 │ worker │ 12342 │ cluster│ Running │ 60s │ 0.02s │ 32 MB │
137
+ │ 4 │ worker │ 12343 │ cluster│ Running │ 60s │ 0.02s │ 32 MB │
138
+ └────┴──────────────────┴──────────┴───────┴─────────┴──────────────┴───────────┴──────────────┘
139
+ ```
140
+
141
+ **Mode** column:
142
+ - `fork` — single independent process
143
+ - `cluster` — Node.js cluster worker (all workers with the same name share one port)
144
+
145
+ ### `monitorx logs`
146
+
147
+ Stream live output from processes.
148
+
149
+ ```bash
150
+ # Stream all process logs
151
+ monitorx logs
152
+
153
+ # Stream logs from a specific process
154
+ monitorx logs api
155
+
156
+ # Stream logs from a specific worker by ID
157
+ monitorx logs 3
158
+ ```
159
+
160
+ Press `Ctrl+C` to stop streaming.
161
+
162
+ ### `monitorx help`
163
+
164
+ ```bash
165
+ # Show all commands
166
+ monitorx help
167
+
168
+ # Show detailed help for a command
169
+ monitorx help start
170
+ ```
171
+
172
+ ## Config File
173
+
174
+ Create `monitorx.config.js` in your project root:
175
+
176
+ ```js
177
+ export default {
178
+ processes: [
179
+ // Simple fork process
180
+ { name: 'api', script: 'node src/server.js' },
181
+
182
+ // Cluster mode — 4 workers sharing the same port
183
+ { name: 'worker', script: 'node src/worker.js', instances: 4 },
184
+ ],
185
+ };
186
+ ```
187
+
188
+ Then run:
189
+
190
+ ```bash
191
+ monitorx start
192
+ ```
193
+
194
+ ### Config fields
195
+
196
+ | Field | Type | Required | Description |
197
+ |---|---|---|---|
198
+ | `name` | string | yes | Identifier shown in `monitorx ls` |
199
+ | `script` | string | yes | Shell command to run (e.g. `node src/app.js`) |
200
+ | `instances` | number | no | Workers to spawn. Values > 1 enable cluster mode |
201
+
202
+ ## Cluster Mode
203
+
204
+ MonitorX uses Node.js's built-in `cluster` module. The daemon acts as the cluster primary — each worker is a separate entry in `monitorx ls` with its own ID and PID.
205
+
206
+ Workers share a port without any changes to your application code:
207
+
208
+ ```js
209
+ // server.js — no cluster code needed
210
+ import http from 'node:http';
211
+
212
+ http.createServer((req, res) => {
213
+ res.end(`hello from PID ${process.pid}\n`);
214
+ }).listen(3000);
215
+ ```
216
+
217
+ ```bash
218
+ monitorx start server.js -i 4
219
+ # Starts 4 workers, all listening on :3000
220
+ # Incoming connections are distributed round-robin
221
+ ```
222
+
223
+ **Crash recovery:** if a cluster worker crashes unexpectedly, MonitorX automatically forks a replacement. Workers stopped via `monitorx stop` are not restarted.
224
+
225
+ ## State Persistence
226
+
227
+ MonitorX saves process state to `~/.monitorx/process_state.json`. When the daemon restarts, all processes that were running are automatically relaunched (including cluster workers).
228
+
229
+ ## Data Directory
230
+
231
+ All MonitorX files live in `~/.monitorx/`:
232
+
233
+ | File | Purpose |
234
+ |---|---|
235
+ | `daemon.sock` | Unix socket for CLI ↔ daemon communication |
236
+ | `process_state.json` | Persisted process registry |
@@ -0,0 +1,3 @@
1
+ import net from "node:net";
2
+ declare const commands: Record<string, (client: net.Socket, arg1?: string | number, ...args: string[]) => Promise<void>>;
3
+ export { commands };
@@ -0,0 +1,183 @@
1
+ // --- Command handlers ---
2
+ import fs from "node:fs";
3
+ import logger from "../logger.js";
4
+ import { MessageType, SCRIPT_SERVER } from "../protocol.js";
5
+ import { send } from "./data-handler.js";
6
+ import { printHelp } from "./help.js";
7
+ const flags = ['-i', '--instances', '-n', '--name'];
8
+ const commands = {
9
+ async start(client, arg1, ...args) {
10
+ let flagArgs = [];
11
+ if (args.length > 0) {
12
+ for (let i = 0; i < args.length; i++) {
13
+ const arg = args[i];
14
+ if (flags.includes(arg) && i + 1 < args.length) {
15
+ flagArgs.push([arg, args[i + 1]]);
16
+ i++;
17
+ }
18
+ else {
19
+ logger.error(`Unknown flag: ${arg}`);
20
+ return;
21
+ }
22
+ }
23
+ }
24
+ const instancesFlag = flagArgs.find(([flag]) => flag === "-i" || flag === "--instances");
25
+ const instances = instancesFlag ? parseInt(instancesFlag[1], 10) : undefined;
26
+ const nameFlag = flagArgs.find(([flag]) => flag === "-n" || flag === "--name");
27
+ const name = nameFlag ? nameFlag[1] : undefined;
28
+ if (instances !== undefined && (isNaN(instances) || instances < 1)) {
29
+ logger.error("Invalid value for -i flag: must be a positive integer");
30
+ return;
31
+ }
32
+ // Case 2: monitorx start <id> — send id to daemon, it handles restarting stopped process
33
+ if (arg1 && !isNaN(Number(arg1))) {
34
+ send(client, {
35
+ type: MessageType.START,
36
+ processes: [],
37
+ id: Number(arg1),
38
+ cwd: process.cwd(),
39
+ });
40
+ return;
41
+ }
42
+ // Case 3: pmon start <script> — file exists, start it directly
43
+ if (arg1) {
44
+ const processPath = `${process.cwd()}/${arg1}`;
45
+ if (fs.existsSync(processPath)) {
46
+ send(client, {
47
+ type: MessageType.START,
48
+ processes: [
49
+ {
50
+ name: name ?? SCRIPT_SERVER,
51
+ script: `node ${processPath}`,
52
+ instances,
53
+ },
54
+ ],
55
+ byScript: true,
56
+ cwd: process.cwd(),
57
+ });
58
+ return;
59
+ }
60
+ }
61
+ // Case 4: pmon start <name> — start stopped processes with that name
62
+ // Also check monitorx.config.js for the process config so daemon can start it fresh if needed
63
+ if (arg1) {
64
+ const processConfigFile = `${process.cwd()}/monitorx.config.js`;
65
+ let processes = [];
66
+ if (fs.existsSync(processConfigFile)) {
67
+ const processConfig = await import(processConfigFile);
68
+ const data = processConfig.default;
69
+ if (data.processes && Array.isArray(data.processes)) {
70
+ processes = data.processes
71
+ .filter((proc) => proc.name === arg1)
72
+ .map((proc) => ({
73
+ ...proc,
74
+ instances: instances ?? proc.instances,
75
+ }));
76
+ }
77
+ }
78
+ send(client, {
79
+ type: MessageType.START,
80
+ processes,
81
+ name: arg1,
82
+ cwd: process.cwd(),
83
+ });
84
+ return;
85
+ }
86
+ // Case 1: pmon start — use monitorx.config.js
87
+ const processConfigFile = `${process.cwd()}/monitorx.config.js`;
88
+ if (!fs.existsSync(processConfigFile)) {
89
+ logger.error("No process config file found");
90
+ logger.info("Please create a monitorx.config.js file in the current working directory");
91
+ return;
92
+ }
93
+ const processConfig = await import(processConfigFile);
94
+ const data = processConfig.default;
95
+ if (!data.processes || !Array.isArray(data.processes)) {
96
+ logger.error("Invalid process config file format");
97
+ logger.info("Please ensure monitorx.config.js exports an object with a 'processes' array");
98
+ return;
99
+ }
100
+ send(client, {
101
+ type: MessageType.START,
102
+ processes: data.processes,
103
+ cwd: process.cwd(),
104
+ });
105
+ },
106
+ /**
107
+ * Logs process output to console.
108
+ *
109
+ * @param client
110
+ * @param subcommand
111
+ */
112
+ async logs(client, arg1) {
113
+ console.log(`Subscribing to logs for process: ${arg1 ?? "(all)"}`);
114
+ if (!isNaN(Number(arg1))) {
115
+ send(client, { type: MessageType.LOGS, id: Number(arg1) });
116
+ }
117
+ else {
118
+ send(client, { type: MessageType.LOGS, name: arg1 });
119
+ }
120
+ },
121
+ /**
122
+ * Stops a process by name, or all processes if no name is provided.
123
+ * @param client
124
+ * @param subcommand
125
+ */
126
+ async stop(client, arg1) {
127
+ console.log(`Stopping process: ${arg1 ?? "(all)"}`);
128
+ const id = Number(arg1);
129
+ if (!isNaN(id)) {
130
+ console.log(`Stopping process with id: ${id}`);
131
+ send(client, { type: MessageType.STOP, id });
132
+ return;
133
+ }
134
+ console.log(`Stopping all processes named: ${arg1}`);
135
+ send(client, { type: MessageType.STOP, name: arg1 });
136
+ },
137
+ async restart(client, arg1) {
138
+ if (!arg1) {
139
+ logger.error("Please provide a process name or id to restart");
140
+ client.unref();
141
+ return;
142
+ }
143
+ const id = Number(arg1);
144
+ if (!isNaN(id)) {
145
+ console.log(`Restarting process with id: ${id}`);
146
+ send(client, { type: MessageType.RESTART, id });
147
+ }
148
+ else {
149
+ console.log(`Restarting all processes named: ${arg1}`);
150
+ send(client, { type: MessageType.RESTART, name: arg1 });
151
+ }
152
+ },
153
+ async delete(client, arg1) {
154
+ if (!arg1) {
155
+ console.log("Deleting all processes...");
156
+ send(client, { type: MessageType.DELETE });
157
+ return;
158
+ }
159
+ const id = Number(arg1);
160
+ if (!isNaN(id)) {
161
+ console.log(`Deleting process with id: ${id}`);
162
+ send(client, { type: MessageType.DELETE, id });
163
+ }
164
+ else {
165
+ console.log(`Deleting all processes named: ${arg1}`);
166
+ send(client, { type: MessageType.DELETE, name: arg1 });
167
+ }
168
+ },
169
+ /**
170
+ * Lists all processes with their status and resource usage.
171
+ * @param client
172
+ */
173
+ async ls(client) {
174
+ console.log("Listing processes...");
175
+ send(client, { type: MessageType.LS });
176
+ },
177
+ async help(_client, arg1) {
178
+ printHelp(arg1);
179
+ _client.unref();
180
+ },
181
+ };
182
+ export { commands };
183
+ //# sourceMappingURL=commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commands.js","sourceRoot":"","sources":["../../src/cli/commands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { ResponseMessage } from "../protocol.js";
2
+ import net from "node:net";
3
+ declare function send(client: net.Socket, payload: object): void;
4
+ /**
5
+ * Handles responses which are sent by the daemon in response to commands.
6
+ * This includes log output, process lists, and error messages.
7
+ *
8
+ * @param message
9
+ * @param client
10
+ */
11
+ declare function handleResponse(message: ResponseMessage, client: net.Socket): void;
12
+ export { send, handleResponse };
@@ -0,0 +1,59 @@
1
+ import { MessageType } from "../protocol.js";
2
+ import Table from "cli-table3";
3
+ function send(client, payload) {
4
+ client.write(JSON.stringify(payload) + "\n");
5
+ }
6
+ // --- Response handler ---
7
+ /**
8
+ * Handles responses which are sent by the daemon in response to commands.
9
+ * This includes log output, process lists, and error messages.
10
+ *
11
+ * @param message
12
+ * @param client
13
+ */
14
+ function handleResponse(message, client) {
15
+ switch (message.type) {
16
+ case MessageType.LOG:
17
+ process.stdout.write(message.data);
18
+ break;
19
+ case MessageType.LS:
20
+ let table = new Table({
21
+ head: [
22
+ "ID",
23
+ "Process Name",
24
+ "PID",
25
+ "Mode",
26
+ "Status",
27
+ "Time Running",
28
+ "CPU Usage",
29
+ "Memory Usage",
30
+ ],
31
+ });
32
+ message.data.forEach((proc) => {
33
+ const status = proc.status;
34
+ const mode = proc.mode === "cluster" ? "cluster" : "fork";
35
+ const timeRunning = proc.startTime
36
+ ? `${Math.floor((Date.now() - proc.startTime) / 1000)}s`
37
+ : "-";
38
+ const cpu = proc.usage?.cpu ?? "-";
39
+ const memory = proc.usage?.memory ?? "-";
40
+ table.push([
41
+ proc.id,
42
+ proc.name,
43
+ proc.pid ?? "Not running",
44
+ mode,
45
+ status,
46
+ timeRunning,
47
+ cpu,
48
+ memory,
49
+ ]);
50
+ });
51
+ console.log(table.toString());
52
+ client.unref();
53
+ break;
54
+ default:
55
+ console.log("received", message);
56
+ }
57
+ }
58
+ export { send, handleResponse };
59
+ //# sourceMappingURL=data-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-handler.js","sourceRoot":"","sources":["../../src/cli/data-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAmB,MAAM,gBAAgB,CAAC;AAE9D,OAAO,KAAK,MAAM,YAAY,CAAC;AAE/B,SAAS,IAAI,CAAC,MAAkB,EAAE,OAAe;IAChD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AAC9C,CAAC;AAGD,2BAA2B;AAC3B;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,OAAwB,EAAE,MAAkB;IACnE,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,WAAW,CAAC,GAAG;YACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACnC,MAAM;QACP,KAAK,WAAW,CAAC,EAAE;YAClB,IAAI,KAAK,GAAG,IAAI,KAAK,CAAC;gBACrB,IAAI,EAAE;oBACL,IAAI;oBACJ,cAAc;oBACd,KAAK;oBACL,MAAM;oBACN,QAAQ;oBACR,cAAc;oBACd,WAAW;oBACX,cAAc;iBACd;aACD,CAAC,CAAC;YAEH,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;gBAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;gBAC1D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS;oBACjC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,GAAG;oBACxD,CAAC,CAAC,GAAG,CAAC;gBACP,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,GAAG,CAAC;gBACnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,CAAC;gBACzC,KAAK,CAAC,IAAI,CAAC;oBACV,IAAI,CAAC,EAAE;oBACP,IAAI,CAAC,IAAI;oBACT,IAAI,CAAC,GAAG,IAAI,aAAa;oBACzB,IAAI;oBACJ,MAAM;oBACN,WAAW;oBACX,GAAG;oBACH,MAAM;iBACN,CAAC,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC9B,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,MAAM;QACP;YACC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;AACF,CAAC;AAED,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ declare function printHelp(command?: string): void;
2
+ export { printHelp };
@@ -0,0 +1,115 @@
1
+ // --- Help ---
2
+ const COMMAND_HELP = {
3
+ start: {
4
+ usage: "monitorx start [name|id|script] [-i <count>] [-n <name>]",
5
+ description: "Start one or more processes.",
6
+ details: [
7
+ " monitorx start Read monitorx.config.js and start all configured processes",
8
+ " monitorx start <name> Start stopped process(es) matching <name>",
9
+ " monitorx start <id> Restart a stopped process by its numeric ID",
10
+ " monitorx start <script.js> Start a script file directly (registered as 'server')",
11
+ " monitorx start <script.js> -i 4 Start script as a cluster with 4 workers",
12
+ " monitorx start <script.js> -n api -i 4 Start cluster named 'api' with 4 workers",
13
+ "",
14
+ "Flags:",
15
+ " -i, --instances <count> Number of cluster workers (>1 enables cluster mode)",
16
+ " -n, --name <name> Custom process name (only for direct script start)",
17
+ "",
18
+ "Config file format (monitorx.config.js):",
19
+ " export default {",
20
+ " processes: [",
21
+ " { name: 'api', script: 'node src/server.js' },",
22
+ " { name: 'worker', script: 'node src/worker.js', instances: 4 },",
23
+ " ]",
24
+ " };",
25
+ ],
26
+ },
27
+ stop: {
28
+ usage: "monitorx stop [name|id]",
29
+ description: "Stop one or more running processes.",
30
+ details: [
31
+ " monitorx stop Stop all running processes",
32
+ " monitorx stop <name> Stop all processes matching <name>",
33
+ " monitorx stop <id> Stop process by numeric ID",
34
+ ],
35
+ },
36
+ restart: {
37
+ usage: "monitorx restart <name|id>",
38
+ description: "Restart a running or stopped process.",
39
+ details: [
40
+ " monitorx restart <name> Restart all processes matching <name>",
41
+ " monitorx restart <id> Restart process by numeric ID",
42
+ "",
43
+ "Note: <name> or <id> is required.",
44
+ ],
45
+ },
46
+ delete: {
47
+ usage: "monitorx delete [name|id]",
48
+ description: "Remove process(es) from monitorx's registry.",
49
+ details: [
50
+ " monitorx delete Delete all processes",
51
+ " monitorx delete <name> Delete all processes matching <name>",
52
+ " monitorx delete <id> Delete process by numeric ID",
53
+ "",
54
+ "Note: Stops the process before deleting if it is running.",
55
+ ],
56
+ },
57
+ logs: {
58
+ usage: "monitorx logs [name]",
59
+ description: "Stream log output from a process.",
60
+ details: [
61
+ " monitorx logs Stream logs from all processes",
62
+ " monitorx logs <name> Stream logs from processes matching <name>",
63
+ "",
64
+ "Note: Output streams live until you press Ctrl+C.",
65
+ ],
66
+ },
67
+ ls: {
68
+ usage: "monitorx ls",
69
+ description: "List all processes with status and resource usage.",
70
+ details: [
71
+ " monitorx ls Show table: ID, name, PID, mode, status, uptime, CPU, memory",
72
+ "",
73
+ "Mode values:",
74
+ " fork Single process (default)",
75
+ " cluster Node.js cluster worker (shares port with siblings)",
76
+ "",
77
+ "Status values:",
78
+ " Running Process is active",
79
+ " Stopped Process has exited or was stopped",
80
+ " Errored Process exited with non-zero code",
81
+ ],
82
+ },
83
+ help: {
84
+ usage: "monitorx help [command]",
85
+ description: "Show help for monitorx or a specific command.",
86
+ details: [
87
+ " monitorx help Show all available commands",
88
+ " monitorx help <command> Show detailed manual for <command>",
89
+ ],
90
+ },
91
+ };
92
+ function printHelp(command) {
93
+ if (command && COMMAND_HELP[command]) {
94
+ const h = COMMAND_HELP[command];
95
+ console.log(`\nUsage: ${h.usage}`);
96
+ console.log(`\n${h.description}\n`);
97
+ h.details.forEach((line) => console.log(line));
98
+ console.log();
99
+ return;
100
+ }
101
+ if (command) {
102
+ console.log(`Unknown command: ${command}`);
103
+ console.log("Run 'monitorx help' to see all available commands.\n");
104
+ return;
105
+ }
106
+ console.log("\nUsage: monitorx <command> [args]\n");
107
+ console.log("Commands:\n");
108
+ const maxLen = Math.max(...Object.keys(COMMAND_HELP).map((k) => k.length));
109
+ for (const [cmd, h] of Object.entries(COMMAND_HELP)) {
110
+ console.log(` ${cmd.padEnd(maxLen + 2)}${h.description}`);
111
+ }
112
+ console.log("\nRun 'monitorx help <command>' for detailed usage.\n");
113
+ }
114
+ export { printHelp };
115
+ //# sourceMappingURL=help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};