@navop/cli 0.2.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,24 @@
1
+ # @navop/cli
2
+
3
+ Terminal CLI and bundled Agent Skill for operating resources exposed by a running Navop desktop application.
4
+
5
+ Install the latest published CLI globally, then use the `navop` executable:
6
+
7
+ ```bash
8
+ npm install -g @navop/cli@latest
9
+ navop --help
10
+ navop status --json
11
+ ```
12
+
13
+ The CLI discovers live tools and schemas from Navop and calls the authenticated Public MCP runtime. Navop remains authoritative for Tool Exposure, permissions, approvals, connection/session IDs, results, and auditing. SSH, SFTP, terminal, database, Redis, and MongoDB behavior stays in Navop; this package only maps command-line arguments to host schemas.
14
+
15
+ Check and update the installed client with npm:
16
+
17
+ ```bash
18
+ npm view @navop/cli version
19
+ npm update -g @navop/cli
20
+ navop --version
21
+ navop status --json
22
+ ```
23
+
24
+ The bundled `navop` Skill requires this global CLI and explains how to keep a compact command workflow in Agent context instead of carrying the complete MCP tool catalog in every turn.
@@ -0,0 +1,608 @@
1
+ // src/arguments.ts
2
+ import { NavopError } from "@navop/client";
3
+ function buildToolArguments(argv, schema, fixed = {}) {
4
+ const properties = schema.properties ?? {};
5
+ const collected = collectFlags(argv, properties);
6
+ const result = { ...fixed };
7
+ for (const [flag, values] of collected) {
8
+ const name = flag.replaceAll("-", "_");
9
+ if (fixed[name] !== void 0) {
10
+ throw new NavopError("invalid_arguments", `option --${flag} is fixed by this command`);
11
+ }
12
+ const property = properties[name];
13
+ if (!property) throw new NavopError("invalid_arguments", `unknown option --${flag}`);
14
+ result[name] = convertValues(flag, values, property);
15
+ }
16
+ for (const required of schema.required ?? []) {
17
+ if (result[required] === void 0) {
18
+ throw new NavopError("invalid_arguments", `missing required option --${required.replaceAll("_", "-")}`);
19
+ }
20
+ }
21
+ return result;
22
+ }
23
+ function collectFlags(argv, properties) {
24
+ const flags = /* @__PURE__ */ new Map();
25
+ for (let index = 0; index < argv.length; index += 1) {
26
+ const token = argv[index];
27
+ if (!token.startsWith("--")) throw new NavopError("invalid_arguments", `unexpected argument: ${token}`);
28
+ const negative = token.startsWith("--no-");
29
+ const name = token.slice(negative ? 5 : 2);
30
+ const inline = name.split("=", 2);
31
+ const key = inline[0];
32
+ const property = properties[key.replaceAll("-", "_")];
33
+ if (!property) throw new NavopError("invalid_arguments", `unknown option --${key}`);
34
+ if (negative && primaryType(property.type) !== "boolean") {
35
+ throw new NavopError("invalid_arguments", `option --no-${key} is only valid for booleans`);
36
+ }
37
+ let value = negative ? "false" : inline[1];
38
+ if (value === void 0 && argv[index + 1]?.startsWith("--") !== false) {
39
+ if (primaryType(property.type) !== "boolean") {
40
+ throw new NavopError("invalid_arguments", `--${key} requires a value`);
41
+ }
42
+ value = "true";
43
+ } else if (value === void 0) value = argv[++index];
44
+ const existing = flags.get(key) ?? [];
45
+ existing.push(value);
46
+ flags.set(key, existing);
47
+ }
48
+ return flags;
49
+ }
50
+ function convertValues(flag, values, schema) {
51
+ const type = primaryType(schema.type);
52
+ if (type === "array") return values.map((value) => convertScalar(flag, value, schema.items ?? {}));
53
+ if (values.length > 1) throw new NavopError("invalid_arguments", `option --${flag} was provided more than once`);
54
+ const converted = convertScalar(flag, values[0], schema);
55
+ if (schema.enum && !schema.enum.includes(converted)) {
56
+ throw new NavopError("invalid_arguments", `option --${flag} must be one of: ${schema.enum.join(", ")}`);
57
+ }
58
+ return converted;
59
+ }
60
+ function convertScalar(flag, value, schema) {
61
+ const type = primaryType(schema.type);
62
+ if (type === "boolean") {
63
+ if (value === "true") return true;
64
+ if (value === "false") return false;
65
+ throw invalidType(flag, "boolean");
66
+ }
67
+ if (type === "integer") {
68
+ const number = Number(value);
69
+ if (Number.isSafeInteger(number)) return number;
70
+ throw invalidType(flag, "integer");
71
+ }
72
+ if (type === "number") {
73
+ const number = Number(value);
74
+ if (Number.isFinite(number)) return number;
75
+ throw invalidType(flag, "number");
76
+ }
77
+ if (type === "object") {
78
+ try {
79
+ return JSON.parse(value);
80
+ } catch {
81
+ throw invalidType(flag, "JSON object");
82
+ }
83
+ }
84
+ return value;
85
+ }
86
+ function primaryType(type) {
87
+ if (Array.isArray(type)) return type.find((value) => value !== "null") ?? "string";
88
+ return type ?? "string";
89
+ }
90
+ function invalidType(flag, expected) {
91
+ return new NavopError("invalid_arguments", `option --${flag} must be a ${expected}`);
92
+ }
93
+
94
+ // src/catalog.ts
95
+ import { NavopError as NavopError2 } from "@navop/client";
96
+ var DOMAIN_COMMANDS = [
97
+ command("ssh exec", "ssh.exec", "Execute a command on an active SSH session"),
98
+ command("ssh diagnostics", "ssh.session_diagnostics", "Inspect an active SSH session"),
99
+ command("ssh command poll", "ssh.command.poll", "Poll a tracked SSH command"),
100
+ command("ssh command output", "ssh.command.output", "Read tracked SSH command output"),
101
+ command("ssh command cancel", "ssh.command.cancel", "Cancel a tracked SSH command"),
102
+ command("terminal read", "terminal.read", "Read visible terminal output"),
103
+ command("terminal exec", "terminal.exec", "Execute in a visible terminal"),
104
+ command("terminal interrupt", "terminal.control", "Interrupt a visible terminal", { action: "interrupt" }),
105
+ command("db schema", "db.schema", "Read database schema metadata"),
106
+ command("db tables", "db.tables", "List database tables"),
107
+ command("db describe", "db.describe_table", "Describe a database table"),
108
+ command("db sample", "db.sample_rows", "Read sample rows"),
109
+ command("db query", "db.query", "Run a read-only SQL query"),
110
+ command("db exec", "db.exec", "Execute a write-capable SQL script"),
111
+ command("redis connections", "redis.list_connections", "List active Redis connections"),
112
+ command("redis command", "redis.command", "Execute a Redis command"),
113
+ command("redis keys", "redis.keys", "List matching Redis keys"),
114
+ command("redis get", "redis.get", "Read a Redis value"),
115
+ command("redis set", "redis.set", "Write a Redis value"),
116
+ command("mongo connections", "mongo.list_connections", "List active MongoDB connections"),
117
+ command("mongo databases", "mongo.list_databases", "List MongoDB databases"),
118
+ command("mongo collections", "mongo.list_collections", "List MongoDB collections"),
119
+ command("mongo find", "mongo.find", "Find MongoDB documents"),
120
+ command("mongo aggregate", "mongo.aggregate", "Aggregate MongoDB documents"),
121
+ command("mongo count", "mongo.count", "Count MongoDB documents"),
122
+ command("mongo indexes", "mongo.list_indexes", "List MongoDB indexes"),
123
+ command("mongo index create", "mongo.create_index", "Create a MongoDB index"),
124
+ command("mongo index drop", "mongo.drop_index", "Drop a MongoDB index"),
125
+ command("mongo collection create", "mongo.create_collection", "Create a MongoDB collection"),
126
+ command("mongo database drop", "mongo.drop_database", "Drop a MongoDB database"),
127
+ command("mongo validation get", "mongo.get_validation", "Read MongoDB collection validation"),
128
+ command("mongo validation set", "mongo.set_validation", "Set MongoDB collection validation"),
129
+ command("mongo insert", "mongo.insert", "Insert a MongoDB document"),
130
+ command("mongo replace", "mongo.replace", "Replace a MongoDB document"),
131
+ command("mongo update", "mongo.update", "Update MongoDB document fields"),
132
+ command("mongo delete", "mongo.delete", "Delete a MongoDB document"),
133
+ command("mongo explain", "mongo.explain", "Explain a MongoDB find operation"),
134
+ command("sftp list", "sftp.list", "List a remote directory"),
135
+ command("sftp read", "sftp.read", "Read a remote file"),
136
+ command("sftp write", "sftp.write", "Write a remote file"),
137
+ command("sftp stat", "sftp.stat", "Inspect a remote path"),
138
+ command("sftp upload", "sftp.upload", "Upload a local path"),
139
+ command("sftp download", "sftp.download", "Download a remote path"),
140
+ command("connections list", "connections.list", "List saved connections"),
141
+ command("connections show", "connections.show", "Show a saved connection"),
142
+ command("connections find", "connections.find", "Find saved connections"),
143
+ command("connections kinds", "connections.list_kinds", "List connection kinds"),
144
+ command("connections schema", "connections.get_schema", "Get a connection kind schema"),
145
+ command("connections validate", "connections.validate", "Validate connection input"),
146
+ command("connections save", "connections.save", "Create or update a connection"),
147
+ command("connections delete", "connections.delete", "Delete a saved connection"),
148
+ command("connections test", "connections.test", "Test a saved connection"),
149
+ command("connections open", "connections.open_session", "Open a connection session"),
150
+ command("connections sessions", "connections.list_sessions", "List active sessions"),
151
+ command("workspace list", "workspaces.list", "List workspaces"),
152
+ command("workspace show", "workspaces.show", "Show a workspace"),
153
+ command("functions list", "internal_functions.list", "List Navop internal functions"),
154
+ command("functions call", "internal_functions.call", "Call a Navop internal function")
155
+ ];
156
+ function resolveDomainCommand(tokens) {
157
+ const matches = DOMAIN_COMMANDS.filter((candidate) => prefixMatches(tokens, candidate.path));
158
+ const exact = matches.find((candidate) => candidate.path.length === tokens.length);
159
+ if (exact) return exact;
160
+ throw new NavopError2("invalid_arguments", `unknown command: navop ${tokens.join(" ")}`);
161
+ }
162
+ function commandChildren(path2) {
163
+ return DOMAIN_COMMANDS.filter((candidate) => prefixMatches(path2, candidate.path));
164
+ }
165
+ function command(path2, tool, summary, fixedArguments) {
166
+ return { path: path2.split(" "), tool, summary, ...fixedArguments ? { fixedArguments } : {} };
167
+ }
168
+ function prefixMatches(prefix, value) {
169
+ return prefix.every((token, index) => value[index] === token);
170
+ }
171
+
172
+ // src/help.ts
173
+ var DOMAINS = [
174
+ ["status", "Show Navop runtime and MCP status"],
175
+ ["ssh", "Execute and manage SSH commands"],
176
+ ["terminal", "Operate visible Navop terminals"],
177
+ ["db", "Query and modify databases"],
178
+ ["redis", "Inspect and modify Redis"],
179
+ ["mongo", "Inspect and modify MongoDB"],
180
+ ["sftp", "Operate remote files over SFTP"],
181
+ ["connections", "Discover and manage saved connections"],
182
+ ["workspace", "Inspect Navop workspaces"],
183
+ ["functions", "List and call Navop internal functions"],
184
+ ["skill", "Print or install the Navop Agent Skill"],
185
+ ["tool", "Access a low-level Navop host tool"],
186
+ ["tools", "List tools reported by the running Navop host"],
187
+ ["schema", "Read one live host tool schema"],
188
+ ["call", "Call one live host tool"]
189
+ ];
190
+ function rootHelp() {
191
+ return `Usage: navop <command> [options]
192
+
193
+ Operate tools exposed by a running Navop desktop application.
194
+
195
+ Commands:
196
+ ${DOMAINS.map(([name, summary]) => ` ${name.padEnd(16)}${summary}`).join("\n")}
197
+
198
+ Global options:
199
+ --discovery <path> Use an explicit discovery file
200
+ --json Emit a stable JSON response
201
+ --timeout <ms> Set the request timeout
202
+ -h, --help Show help
203
+ -V, --version Show version
204
+ `;
205
+ }
206
+ function commandHelp(path2) {
207
+ const special = specialHelp(path2);
208
+ if (special) return special;
209
+ const children = commandChildren(path2);
210
+ const exact = DOMAIN_COMMANDS.find((candidate) => candidate.path.join(" ") === path2.join(" "));
211
+ if (exact) {
212
+ return `Usage: navop ${path2.join(" ")} [options]
213
+
214
+ ${exact.summary}.
215
+
216
+ Options are validated against the schema exposed by the running Navop application.
217
+ --json Emit a stable JSON response
218
+ --discovery <path> Use an explicit discovery file
219
+ --timeout <ms> Set the MCP request timeout
220
+ -h, --help Show help
221
+ `;
222
+ }
223
+ const direct = /* @__PURE__ */ new Map();
224
+ for (const candidate of children) {
225
+ const name = candidate.path[path2.length];
226
+ if (name) direct.set(name, candidate.summary);
227
+ }
228
+ if (direct.size === 0) return rootHelp();
229
+ return `Usage: navop ${path2.join(" ")} <command> [options]
230
+
231
+ Commands:
232
+ ${[...direct].map(([name, summary]) => ` ${name.padEnd(16)}${summary}`).join("\n")}
233
+ `;
234
+ }
235
+ function specialHelp(path2) {
236
+ const key = path2.join(" ");
237
+ const values = {
238
+ status: "Usage: navop status [--json] [--discovery <path>] [--timeout <ms>]\n",
239
+ skill: "Usage: navop skill print|install [--target codex|agents] [--scope user|project] [--force]\n",
240
+ tool: "Usage: navop tool list|schema <tool>|call <tool> [--arguments <json>|--file <path>|--stdin]\n"
241
+ };
242
+ return values[key];
243
+ }
244
+ function schemaHelp(path2, summary, schema, fixed = {}) {
245
+ const required = new Set(schema.required ?? []);
246
+ const properties = Object.entries(schema.properties ?? {}).filter(([name]) => fixed[name] === void 0);
247
+ const lines = properties.map(([name, property]) => {
248
+ const flag = `--${name.replaceAll("_", "-")}`;
249
+ const type = schemaType(property);
250
+ const marker = required.has(name) ? " (required)" : "";
251
+ const choices = property.enum ? ` [${property.enum.join("|")}]` : "";
252
+ return ` ${`${flag} <${type}>`.padEnd(28)}${property.description ?? ""}${choices}${marker}`.trimEnd();
253
+ });
254
+ return `Usage: navop ${path2.join(" ")} [options]
255
+
256
+ ${summary}.
257
+
258
+ Options:
259
+ ${lines.join("\n")}
260
+ --json Emit a stable JSON response
261
+ --discovery <path> Use an explicit discovery file
262
+ --timeout <ms> Set the MCP request timeout
263
+ -h, --help Show help
264
+ `;
265
+ }
266
+ function schemaType(property) {
267
+ const type = Array.isArray(property.type) ? property.type.find((value) => value !== "null") : property.type;
268
+ if (type === "integer") return "integer";
269
+ if (type === "number") return "number";
270
+ if (type === "boolean") return "boolean";
271
+ if (type === "array") return property.items?.type ?? "value";
272
+ if (type === "object") return "json";
273
+ return "string";
274
+ }
275
+
276
+ // src/skill.ts
277
+ import { cp, mkdir, readFile, rm } from "fs/promises";
278
+ import os from "os";
279
+ import path from "path";
280
+ import { fileURLToPath } from "url";
281
+ import { NavopError as NavopError3 } from "@navop/client";
282
+ var SKILL_ROOT = fileURLToPath(new URL("../skills/navop", import.meta.url));
283
+ async function printSkill() {
284
+ return readFile(path.join(SKILL_ROOT, "SKILL.md"), "utf8");
285
+ }
286
+ async function installSkill(options) {
287
+ const root = options.scope === "user" ? options.home ?? os.homedir() : options.cwd ?? process.cwd();
288
+ const target = path.join(root, options.target === "codex" ? ".codex" : ".agents", "skills", "navop");
289
+ await mkdir(path.dirname(target), { recursive: true });
290
+ try {
291
+ await mkdir(target, { recursive: false });
292
+ } catch (error) {
293
+ if (error?.code !== "EEXIST") throw error;
294
+ if (!options.force) throw new NavopError3("skill_exists", `Navop Skill already exists at ${target}`);
295
+ await rm(target, { recursive: true, force: true });
296
+ await mkdir(target, { recursive: true });
297
+ }
298
+ await cp(SKILL_ROOT, target, { recursive: true, force: false });
299
+ return target;
300
+ }
301
+
302
+ // src/runner.ts
303
+ import { readFile as readFile2 } from "fs/promises";
304
+ import { McpConnection, NavopError as NavopError4, readDiscovery, resolveDiscoveryPath } from "@navop/client";
305
+ async function runCli(argv) {
306
+ const { args, options } = parseGlobalOptions(argv);
307
+ if (args.length === 0) return { text: rootHelp(), json: false };
308
+ if (hasHelp(args)) return { text: await helpFor(args, options), json: false };
309
+ if (args[0] === "status") return { result: await status(options), json: options.json };
310
+ if (args[0] === "tools") return { result: await toolCommand(["list", ...args.slice(1)], options), json: options.json };
311
+ if (args[0] === "schema") return { result: await toolCommand(["schema", ...args.slice(1)], options), json: options.json };
312
+ if (args[0] === "call") return { result: await toolCommand(["call", ...args.slice(1)], options), json: options.json };
313
+ if (args[0] === "skill") return { result: await skillCommand(args.slice(1)), json: options.json };
314
+ if (args[0] === "tool") return { result: await toolCommand(args.slice(1), options), json: options.json };
315
+ if (args.every((value) => !value.startsWith("--")) && commandChildren(args).some((candidate) => candidate.path.length > args.length)) {
316
+ return { text: commandHelp(args), json: false };
317
+ }
318
+ return { result: await domainCommand(args, options), json: options.json };
319
+ }
320
+ async function domainCommand(args, options) {
321
+ const flagIndex = args.findIndex((value) => value.startsWith("--"));
322
+ const commandTokens = flagIndex < 0 ? args : args.slice(0, flagIndex);
323
+ let toolArgs = flagIndex < 0 ? [] : args.slice(flagIndex);
324
+ const command2 = resolveDomainCommand(commandTokens);
325
+ const connection = await openConnection(options);
326
+ try {
327
+ const tool = await findTool(connection, command2.tool);
328
+ toolArgs = await expandConvenienceArguments(command2.tool, toolArgs);
329
+ const parsed = buildToolArguments(toolArgs, tool.inputSchema ?? {}, command2.fixedArguments);
330
+ return callTool(connection, command2.tool, parsed);
331
+ } finally {
332
+ connection.close();
333
+ }
334
+ }
335
+ async function status(options) {
336
+ const discoveryPath = await resolveDiscoveryPath(options.discovery);
337
+ const discovery = await readDiscovery(discoveryPath);
338
+ const connection = await McpConnection.connect(discovery, { ...timeoutOption(options), initialize: false });
339
+ try {
340
+ const server = await connection.initialize();
341
+ const tools = await listTools(connection);
342
+ const availableTools = tools.map((tool) => String(tool.name)).sort();
343
+ const runtime = await runtimeStatus(connection, tools);
344
+ const permissionMode = permissionModeFromServer(server);
345
+ const toolGroups = Array.isArray(runtime?.toolGroups) ? runtime.toolGroups : [];
346
+ const disabledToolGroups = toolGroups.filter((group) => group?.enabled === false);
347
+ return {
348
+ running: true,
349
+ discovery: { path: discoveryPath, app: discovery.app, pid: discovery.pid, host: discovery.host, port: discovery.port, mode: discovery.mode },
350
+ server,
351
+ toolCount: tools.length,
352
+ permissionMode,
353
+ availableTools,
354
+ runtime: runtime ?? null,
355
+ toolGroups,
356
+ disabledToolGroups,
357
+ guidance: capabilityGuidance(permissionMode, disabledToolGroups)
358
+ };
359
+ } finally {
360
+ connection.close();
361
+ }
362
+ }
363
+ async function toolCommand(args, options) {
364
+ const action = args[0];
365
+ const connection = await openConnection(options);
366
+ try {
367
+ if (action === "list") return listTools(connection);
368
+ const name = args[1];
369
+ if (!name) throw new NavopError4("invalid_arguments", `navop tool ${action ?? ""} requires a tool name`);
370
+ if (action === "schema") return findTool(connection, name);
371
+ if (action === "call") {
372
+ await findTool(connection, name);
373
+ return callTool(connection, name, await rawArguments(args.slice(2)));
374
+ }
375
+ throw new NavopError4("invalid_arguments", "Usage: navop tool list|schema <tool>|call <tool>");
376
+ } finally {
377
+ connection.close();
378
+ }
379
+ }
380
+ async function skillCommand(args) {
381
+ if (args[0] === "print") return { content: await printSkill() };
382
+ if (args[0] !== "install") throw new NavopError4("invalid_arguments", "Usage: navop skill print|install");
383
+ const options = simpleOptions(args.slice(1));
384
+ const target = options.get("target") ?? "codex";
385
+ const scope = options.get("scope") ?? "user";
386
+ if (target !== "codex" && target !== "agents") throw new NavopError4("invalid_arguments", "--target must be codex or agents");
387
+ if (scope !== "user" && scope !== "project") throw new NavopError4("invalid_arguments", "--scope must be user or project");
388
+ return { path: await installSkill({ target, scope, force: options.has("force") }) };
389
+ }
390
+ async function openConnection(options) {
391
+ const discovery = await readDiscovery(await resolveDiscoveryPath(options.discovery));
392
+ return McpConnection.connect(discovery, timeoutOption(options));
393
+ }
394
+ function timeoutOption(options) {
395
+ return options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs };
396
+ }
397
+ async function listTools(connection) {
398
+ const tools = [];
399
+ let cursor;
400
+ do {
401
+ const result = await connection.request("tools/list", cursor ? { cursor } : {});
402
+ tools.push(...result.tools ?? []);
403
+ cursor = result.nextCursor;
404
+ } while (cursor);
405
+ return tools;
406
+ }
407
+ async function findTool(connection, name) {
408
+ const tools = await listTools(connection);
409
+ const tool = tools.find((candidate) => candidate.name === name);
410
+ if (!tool) {
411
+ const runtime = await runtimeStatus(connection, tools);
412
+ const groupId = toolGroupForName(name);
413
+ const group = Array.isArray(runtime?.toolGroups) ? runtime.toolGroups.find((candidate) => candidate?.id === groupId) : void 0;
414
+ const groupAction = group?.enabled === false ? `Enable the ${groupId} tool group in ${runtime?.settingsPath ?? "Navop Settings > General > Tool Exposure"}` : `Inspect ${runtime?.settingsPath ?? "Navop Settings > General > Tool Exposure"} and the required connection/session`;
415
+ throw new NavopError4(
416
+ "tool_not_found",
417
+ `Navop tool is not available from the running host: ${name}. ${groupAction}, then retry discovery.`,
418
+ {
419
+ requiredTool: name,
420
+ requiredToolGroup: groupId,
421
+ toolGroup: group ?? null,
422
+ availableTools: tools.map((candidate) => candidate.name).sort(),
423
+ actions: [
424
+ "Enable MCP Server in Navop Settings > General > MCP",
425
+ groupAction,
426
+ "Open the connection or session required by the requested tool",
427
+ "Run navop status --json and navop tool list --json again"
428
+ ]
429
+ }
430
+ );
431
+ }
432
+ return tool;
433
+ }
434
+ async function runtimeStatus(connection, tools) {
435
+ if (!tools.some((tool) => tool?.name === "navop.runtime_status")) return void 0;
436
+ const result = await connection.request("tools/call", {
437
+ name: "navop.runtime_status",
438
+ arguments: {}
439
+ });
440
+ if (result?.isError) return void 0;
441
+ return result?.structuredContent ?? result;
442
+ }
443
+ function toolGroupForName(name) {
444
+ const prefix = name.split(".", 1)[0] ?? name;
445
+ if (prefix === "ssh") return "ssh";
446
+ if (prefix === "terminal") return "terminal_exec";
447
+ if (prefix === "db") return "database";
448
+ if (prefix === "mongo" || prefix === "mongodb") return "mongodb";
449
+ if (prefix === "internal_functions" || prefix === "functions") return "internal_functions";
450
+ return prefix;
451
+ }
452
+ function permissionModeFromServer(server) {
453
+ const instructions = typeof server?.instructions === "string" ? server.instructions : "";
454
+ const match = instructions.match(/permission_mode=(deny|ask|allow)/);
455
+ return match?.[1] ?? "unknown";
456
+ }
457
+ function capabilityGuidance(permissionMode, disabledToolGroups) {
458
+ const guidance = [
459
+ "Tool names and schemas come from the running Navop host through tools/list; the CLI and Skill are not capability authorities.",
460
+ "Tool availability also depends on Navop Tool Exposure settings and active connection sessions."
461
+ ];
462
+ if (disabledToolGroups.length > 0) {
463
+ guidance.push(
464
+ `Disabled host tool groups: ${disabledToolGroups.map((group) => group.id).join(", ")}. Enable only the groups needed by the user.`
465
+ );
466
+ }
467
+ if (permissionMode === "deny") guidance.push("Mutating tools are denied by the current permission mode.");
468
+ else if (permissionMode === "ask") guidance.push("Mutating tools require approval in Navop; never bypass a rejection.");
469
+ else if (permissionMode === "allow") guidance.push("Mutating tools run automatically; confirm user intent before destructive actions.");
470
+ else guidance.push("Inspect the Navop MCP permission profile before attempting mutations.");
471
+ return guidance;
472
+ }
473
+ async function callTool(connection, name, args) {
474
+ const result = await connection.request("tools/call", { name, arguments: args });
475
+ if (result?.isError) throw new NavopError4("tool_failed", toolMessage(result), result);
476
+ return result?.structuredContent ?? result;
477
+ }
478
+ function parseGlobalOptions(argv) {
479
+ const args = [];
480
+ const options = { json: false };
481
+ for (let index = 0; index < argv.length; index += 1) {
482
+ const token = argv[index];
483
+ if (token === "--json") options.json = true;
484
+ else if (token === "--discovery") options.discovery = requiredValue(argv, ++index, token);
485
+ else if (token === "--timeout") options.timeoutMs = positiveInteger(requiredValue(argv, ++index, token), token);
486
+ else args.push(token);
487
+ }
488
+ return { args, options };
489
+ }
490
+ async function helpFor(args, options) {
491
+ const path2 = args.filter((value) => value !== "--help" && value !== "-h");
492
+ if (path2.length === 0) return rootHelp();
493
+ let command2;
494
+ try {
495
+ command2 = resolveDomainCommand(path2);
496
+ } catch {
497
+ return commandHelp(path2);
498
+ }
499
+ try {
500
+ const connection = await openConnection(options);
501
+ try {
502
+ const tool = await findTool(connection, command2.tool);
503
+ return schemaHelp(path2, command2.summary, tool.inputSchema ?? {}, command2.fixedArguments);
504
+ } finally {
505
+ connection.close();
506
+ }
507
+ } catch {
508
+ return commandHelp(path2);
509
+ }
510
+ }
511
+ function hasHelp(args) {
512
+ return args.includes("--help") || args.includes("-h");
513
+ }
514
+ async function expandConvenienceArguments(tool, args) {
515
+ let expanded = args;
516
+ if (tool.startsWith("db.") || tool.startsWith("sftp.")) {
517
+ expanded = replaceFlagAlias(expanded, "--connection", "--target");
518
+ }
519
+ if (tool.startsWith("redis.")) {
520
+ expanded = replaceFlagAlias(expanded, "--connection-id", "--target");
521
+ }
522
+ if (tool.startsWith("mongo.")) {
523
+ expanded = replaceFlagAlias(expanded, "--connection-id", "--target");
524
+ }
525
+ if (tool !== "sftp.write") return expanded;
526
+ const stdinIndex = expanded.indexOf("--stdin");
527
+ const fileIndex = expanded.indexOf("--content-file");
528
+ if (stdinIndex >= 0 && fileIndex >= 0) throw new NavopError4("invalid_arguments", "use only one of --stdin or --content-file");
529
+ if (stdinIndex >= 0) return replaceWithContent(expanded, stdinIndex, 1, await readStdin());
530
+ if (fileIndex >= 0) return replaceWithContent(expanded, fileIndex, 2, await readFile2(requiredValue(expanded, fileIndex + 1, "--content-file")));
531
+ return expanded;
532
+ }
533
+ function replaceFlagAlias(args, alias, canonical) {
534
+ const aliasIndex = args.indexOf(alias);
535
+ if (aliasIndex < 0) return args;
536
+ if (args.includes(canonical)) {
537
+ throw new NavopError4("invalid_arguments", `use only one of ${alias} or ${canonical}`);
538
+ }
539
+ const next = [...args];
540
+ next[aliasIndex] = canonical;
541
+ return next;
542
+ }
543
+ function replaceWithContent(args, index, count, content) {
544
+ const next = [...args];
545
+ next.splice(index, count, "--content-base64", Buffer.from(content).toString("base64"));
546
+ return next;
547
+ }
548
+ async function rawArguments(args) {
549
+ const options = simpleOptions(args);
550
+ const sources = [options.has("arguments"), options.has("file"), options.has("stdin")].filter(Boolean).length;
551
+ if (sources > 1) throw new NavopError4("invalid_arguments", "use only one of --arguments, --file, or --stdin");
552
+ let text = options.get("arguments") ?? "{}";
553
+ if (options.has("file")) text = await readFile2(options.get("file"), "utf8");
554
+ if (options.has("stdin")) text = await readStdin();
555
+ try {
556
+ const value = JSON.parse(text);
557
+ if (!value || Array.isArray(value) || typeof value !== "object") throw new Error();
558
+ return value;
559
+ } catch {
560
+ throw new NavopError4("invalid_arguments", "tool arguments must be a JSON object");
561
+ }
562
+ }
563
+ function simpleOptions(args) {
564
+ const options = /* @__PURE__ */ new Map();
565
+ for (let index = 0; index < args.length; index += 1) {
566
+ const token = args[index];
567
+ if (!token.startsWith("--")) throw new NavopError4("invalid_arguments", `unexpected argument: ${token}`);
568
+ const name = token.slice(2);
569
+ if (["force", "stdin"].includes(name)) options.set(name, "true");
570
+ else options.set(name, requiredValue(args, ++index, token));
571
+ }
572
+ return options;
573
+ }
574
+ function requiredValue(args, index, option) {
575
+ const value = args[index];
576
+ if (!value || value.startsWith("--")) throw new NavopError4("invalid_arguments", `${option} requires a value`);
577
+ return value;
578
+ }
579
+ function positiveInteger(value, option) {
580
+ const parsed = Number(value);
581
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) throw new NavopError4("invalid_arguments", `${option} must be a positive integer`);
582
+ return parsed;
583
+ }
584
+ function readStdin() {
585
+ return new Promise((resolve, reject) => {
586
+ let text = "";
587
+ process.stdin.setEncoding("utf8");
588
+ process.stdin.on("data", (chunk) => {
589
+ text += chunk;
590
+ });
591
+ process.stdin.on("end", () => resolve(text));
592
+ process.stdin.on("error", reject);
593
+ });
594
+ }
595
+ function toolMessage(result) {
596
+ return result?.structuredContent?.message ?? result?.content?.[0]?.text ?? "Navop tool call failed";
597
+ }
598
+
599
+ export {
600
+ buildToolArguments,
601
+ DOMAIN_COMMANDS,
602
+ resolveDomainCommand,
603
+ rootHelp,
604
+ printSkill,
605
+ installSkill,
606
+ runCli
607
+ };
608
+ //# sourceMappingURL=chunk-QRRIPLVN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/arguments.ts","../src/catalog.ts","../src/help.ts","../src/skill.ts","../src/runner.ts"],"sourcesContent":["import { NavopError } from \"@navop/client\";\n\ninterface JsonSchema {\n type?: string | string[];\n properties?: Record<string, JsonSchema>;\n required?: string[];\n items?: JsonSchema;\n enum?: unknown[];\n}\n\nexport function buildToolArguments(\n argv: string[],\n schema: JsonSchema,\n fixed: Record<string, unknown> = {},\n): Record<string, unknown> {\n const properties = schema.properties ?? {};\n const collected = collectFlags(argv, properties);\n const result: Record<string, unknown> = { ...fixed };\n for (const [flag, values] of collected) {\n const name = flag.replaceAll(\"-\", \"_\");\n if (fixed[name] !== undefined) {\n throw new NavopError(\"invalid_arguments\", `option --${flag} is fixed by this command`);\n }\n const property = properties[name];\n if (!property) throw new NavopError(\"invalid_arguments\", `unknown option --${flag}`);\n result[name] = convertValues(flag, values, property);\n }\n for (const required of schema.required ?? []) {\n if (result[required] === undefined) {\n throw new NavopError(\"invalid_arguments\", `missing required option --${required.replaceAll(\"_\", \"-\")}`);\n }\n }\n return result;\n}\n\nfunction collectFlags(argv: string[], properties: Record<string, JsonSchema>): Map<string, string[]> {\n const flags = new Map<string, string[]>();\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index]!;\n if (!token.startsWith(\"--\")) throw new NavopError(\"invalid_arguments\", `unexpected argument: ${token}`);\n const negative = token.startsWith(\"--no-\");\n const name = token.slice(negative ? 5 : 2);\n const inline = name.split(\"=\", 2);\n const key = inline[0]!;\n const property = properties[key.replaceAll(\"-\", \"_\")];\n if (!property) throw new NavopError(\"invalid_arguments\", `unknown option --${key}`);\n if (negative && primaryType(property.type) !== \"boolean\") {\n throw new NavopError(\"invalid_arguments\", `option --no-${key} is only valid for booleans`);\n }\n let value = negative ? \"false\" : inline[1];\n if (value === undefined && argv[index + 1]?.startsWith(\"--\") !== false) {\n if (primaryType(property.type) !== \"boolean\") {\n throw new NavopError(\"invalid_arguments\", `--${key} requires a value`);\n }\n value = \"true\";\n }\n else if (value === undefined) value = argv[++index];\n const existing = flags.get(key) ?? [];\n existing.push(value!);\n flags.set(key, existing);\n }\n return flags;\n}\n\nfunction convertValues(flag: string, values: string[], schema: JsonSchema): unknown {\n const type = primaryType(schema.type);\n if (type === \"array\") return values.map((value) => convertScalar(flag, value, schema.items ?? {}));\n if (values.length > 1) throw new NavopError(\"invalid_arguments\", `option --${flag} was provided more than once`);\n const converted = convertScalar(flag, values[0]!, schema);\n if (schema.enum && !schema.enum.includes(converted)) {\n throw new NavopError(\"invalid_arguments\", `option --${flag} must be one of: ${schema.enum.join(\", \")}`);\n }\n return converted;\n}\n\nfunction convertScalar(flag: string, value: string, schema: JsonSchema): unknown {\n const type = primaryType(schema.type);\n if (type === \"boolean\") {\n if (value === \"true\") return true;\n if (value === \"false\") return false;\n throw invalidType(flag, \"boolean\");\n }\n if (type === \"integer\") {\n const number = Number(value);\n if (Number.isSafeInteger(number)) return number;\n throw invalidType(flag, \"integer\");\n }\n if (type === \"number\") {\n const number = Number(value);\n if (Number.isFinite(number)) return number;\n throw invalidType(flag, \"number\");\n }\n if (type === \"object\") {\n try { return JSON.parse(value); } catch { throw invalidType(flag, \"JSON object\"); }\n }\n return value;\n}\n\nfunction primaryType(type: JsonSchema[\"type\"]): string {\n if (Array.isArray(type)) return type.find((value) => value !== \"null\") ?? \"string\";\n return type ?? \"string\";\n}\n\nfunction invalidType(flag: string, expected: string): NavopError {\n return new NavopError(\"invalid_arguments\", `option --${flag} must be a ${expected}`);\n}\n","import { NavopError } from \"@navop/client\";\n\nexport interface DomainCommand {\n path: string[];\n tool: string;\n summary: string;\n fixedArguments?: Record<string, unknown>;\n}\n\nexport const DOMAIN_COMMANDS: DomainCommand[] = [\n command(\"ssh exec\", \"ssh.exec\", \"Execute a command on an active SSH session\"),\n command(\"ssh diagnostics\", \"ssh.session_diagnostics\", \"Inspect an active SSH session\"),\n command(\"ssh command poll\", \"ssh.command.poll\", \"Poll a tracked SSH command\"),\n command(\"ssh command output\", \"ssh.command.output\", \"Read tracked SSH command output\"),\n command(\"ssh command cancel\", \"ssh.command.cancel\", \"Cancel a tracked SSH command\"),\n command(\"terminal read\", \"terminal.read\", \"Read visible terminal output\"),\n command(\"terminal exec\", \"terminal.exec\", \"Execute in a visible terminal\"),\n command(\"terminal interrupt\", \"terminal.control\", \"Interrupt a visible terminal\", { action: \"interrupt\" }),\n command(\"db schema\", \"db.schema\", \"Read database schema metadata\"),\n command(\"db tables\", \"db.tables\", \"List database tables\"),\n command(\"db describe\", \"db.describe_table\", \"Describe a database table\"),\n command(\"db sample\", \"db.sample_rows\", \"Read sample rows\"),\n command(\"db query\", \"db.query\", \"Run a read-only SQL query\"),\n command(\"db exec\", \"db.exec\", \"Execute a write-capable SQL script\"),\n command(\"redis connections\", \"redis.list_connections\", \"List active Redis connections\"),\n command(\"redis command\", \"redis.command\", \"Execute a Redis command\"),\n command(\"redis keys\", \"redis.keys\", \"List matching Redis keys\"),\n command(\"redis get\", \"redis.get\", \"Read a Redis value\"),\n command(\"redis set\", \"redis.set\", \"Write a Redis value\"),\n command(\"mongo connections\", \"mongo.list_connections\", \"List active MongoDB connections\"),\n command(\"mongo databases\", \"mongo.list_databases\", \"List MongoDB databases\"),\n command(\"mongo collections\", \"mongo.list_collections\", \"List MongoDB collections\"),\n command(\"mongo find\", \"mongo.find\", \"Find MongoDB documents\"),\n command(\"mongo aggregate\", \"mongo.aggregate\", \"Aggregate MongoDB documents\"),\n command(\"mongo count\", \"mongo.count\", \"Count MongoDB documents\"),\n command(\"mongo indexes\", \"mongo.list_indexes\", \"List MongoDB indexes\"),\n command(\"mongo index create\", \"mongo.create_index\", \"Create a MongoDB index\"),\n command(\"mongo index drop\", \"mongo.drop_index\", \"Drop a MongoDB index\"),\n command(\"mongo collection create\", \"mongo.create_collection\", \"Create a MongoDB collection\"),\n command(\"mongo database drop\", \"mongo.drop_database\", \"Drop a MongoDB database\"),\n command(\"mongo validation get\", \"mongo.get_validation\", \"Read MongoDB collection validation\"),\n command(\"mongo validation set\", \"mongo.set_validation\", \"Set MongoDB collection validation\"),\n command(\"mongo insert\", \"mongo.insert\", \"Insert a MongoDB document\"),\n command(\"mongo replace\", \"mongo.replace\", \"Replace a MongoDB document\"),\n command(\"mongo update\", \"mongo.update\", \"Update MongoDB document fields\"),\n command(\"mongo delete\", \"mongo.delete\", \"Delete a MongoDB document\"),\n command(\"mongo explain\", \"mongo.explain\", \"Explain a MongoDB find operation\"),\n command(\"sftp list\", \"sftp.list\", \"List a remote directory\"),\n command(\"sftp read\", \"sftp.read\", \"Read a remote file\"),\n command(\"sftp write\", \"sftp.write\", \"Write a remote file\"),\n command(\"sftp stat\", \"sftp.stat\", \"Inspect a remote path\"),\n command(\"sftp upload\", \"sftp.upload\", \"Upload a local path\"),\n command(\"sftp download\", \"sftp.download\", \"Download a remote path\"),\n command(\"connections list\", \"connections.list\", \"List saved connections\"),\n command(\"connections show\", \"connections.show\", \"Show a saved connection\"),\n command(\"connections find\", \"connections.find\", \"Find saved connections\"),\n command(\"connections kinds\", \"connections.list_kinds\", \"List connection kinds\"),\n command(\"connections schema\", \"connections.get_schema\", \"Get a connection kind schema\"),\n command(\"connections validate\", \"connections.validate\", \"Validate connection input\"),\n command(\"connections save\", \"connections.save\", \"Create or update a connection\"),\n command(\"connections delete\", \"connections.delete\", \"Delete a saved connection\"),\n command(\"connections test\", \"connections.test\", \"Test a saved connection\"),\n command(\"connections open\", \"connections.open_session\", \"Open a connection session\"),\n command(\"connections sessions\", \"connections.list_sessions\", \"List active sessions\"),\n command(\"workspace list\", \"workspaces.list\", \"List workspaces\"),\n command(\"workspace show\", \"workspaces.show\", \"Show a workspace\"),\n command(\"functions list\", \"internal_functions.list\", \"List Navop internal functions\"),\n command(\"functions call\", \"internal_functions.call\", \"Call a Navop internal function\"),\n];\n\nexport function resolveDomainCommand(tokens: string[]): DomainCommand {\n const matches = DOMAIN_COMMANDS.filter((candidate) => prefixMatches(tokens, candidate.path));\n const exact = matches.find((candidate) => candidate.path.length === tokens.length);\n if (exact) return exact;\n throw new NavopError(\"invalid_arguments\", `unknown command: navop ${tokens.join(\" \")}`);\n}\n\nexport function commandChildren(path: string[]): DomainCommand[] {\n return DOMAIN_COMMANDS.filter((candidate) => prefixMatches(path, candidate.path));\n}\n\nfunction command(path: string, tool: string, summary: string, fixedArguments?: Record<string, unknown>): DomainCommand {\n return { path: path.split(\" \"), tool, summary, ...(fixedArguments ? { fixedArguments } : {}) };\n}\n\nfunction prefixMatches(prefix: string[], value: string[]): boolean {\n return prefix.every((token, index) => value[index] === token);\n}\n","import { commandChildren, DOMAIN_COMMANDS } from \"./catalog.js\";\n\nconst DOMAINS: Array<[string, string]> = [\n [\"status\", \"Show Navop runtime and MCP status\"],\n [\"ssh\", \"Execute and manage SSH commands\"],\n [\"terminal\", \"Operate visible Navop terminals\"],\n [\"db\", \"Query and modify databases\"],\n [\"redis\", \"Inspect and modify Redis\"],\n [\"mongo\", \"Inspect and modify MongoDB\"],\n [\"sftp\", \"Operate remote files over SFTP\"],\n [\"connections\", \"Discover and manage saved connections\"],\n [\"workspace\", \"Inspect Navop workspaces\"],\n [\"functions\", \"List and call Navop internal functions\"],\n [\"skill\", \"Print or install the Navop Agent Skill\"],\n [\"tool\", \"Access a low-level Navop host tool\"],\n [\"tools\", \"List tools reported by the running Navop host\"],\n [\"schema\", \"Read one live host tool schema\"],\n [\"call\", \"Call one live host tool\"],\n];\n\nexport function rootHelp(): string {\n return `Usage: navop <command> [options]\\n\\nOperate tools exposed by a running Navop desktop application.\\n\\nCommands:\\n${DOMAINS.map(([name, summary]) => ` ${name.padEnd(16)}${summary}`).join(\"\\n\")}\\n\\nGlobal options:\\n --discovery <path> Use an explicit discovery file\\n --json Emit a stable JSON response\\n --timeout <ms> Set the request timeout\\n -h, --help Show help\\n -V, --version Show version\\n`;\n}\n\nexport function commandHelp(path: string[]): string {\n const special = specialHelp(path);\n if (special) return special;\n const children = commandChildren(path);\n const exact = DOMAIN_COMMANDS.find((candidate) => candidate.path.join(\" \") === path.join(\" \"));\n if (exact) {\n return `Usage: navop ${path.join(\" \")} [options]\\n\\n${exact.summary}.\\n\\nOptions are validated against the schema exposed by the running Navop application.\\n --json Emit a stable JSON response\\n --discovery <path> Use an explicit discovery file\\n --timeout <ms> Set the MCP request timeout\\n -h, --help Show help\\n`;\n }\n const direct = new Map<string, string>();\n for (const candidate of children) {\n const name = candidate.path[path.length];\n if (name) direct.set(name, candidate.summary);\n }\n if (direct.size === 0) return rootHelp();\n return `Usage: navop ${path.join(\" \")} <command> [options]\\n\\nCommands:\\n${[...direct].map(([name, summary]) => ` ${name.padEnd(16)}${summary}`).join(\"\\n\")}\\n`;\n}\n\nfunction specialHelp(path: string[]): string | undefined {\n const key = path.join(\" \");\n const values: Record<string, string> = {\n status: \"Usage: navop status [--json] [--discovery <path>] [--timeout <ms>]\\n\",\n skill: \"Usage: navop skill print|install [--target codex|agents] [--scope user|project] [--force]\\n\",\n tool: \"Usage: navop tool list|schema <tool>|call <tool> [--arguments <json>|--file <path>|--stdin]\\n\",\n };\n return values[key];\n}\n\nexport function allCommandPaths(): string[] {\n return DOMAIN_COMMANDS.map((command) => command.path.join(\" \"));\n}\n\nexport function schemaHelp(path: string[], summary: string, schema: any, fixed: Record<string, unknown> = {}): string {\n const required = new Set<string>(schema.required ?? []);\n const properties = Object.entries<any>(schema.properties ?? {}).filter(([name]) => fixed[name] === undefined);\n const lines = properties.map(([name, property]) => {\n const flag = `--${name.replaceAll(\"_\", \"-\")}`;\n const type = schemaType(property);\n const marker = required.has(name) ? \" (required)\" : \"\";\n const choices = property.enum ? ` [${property.enum.join(\"|\")}]` : \"\";\n return ` ${`${flag} <${type}>`.padEnd(28)}${property.description ?? \"\"}${choices}${marker}`.trimEnd();\n });\n return `Usage: navop ${path.join(\" \")} [options]\\n\\n${summary}.\\n\\nOptions:\\n${lines.join(\"\\n\")}\\n --json Emit a stable JSON response\\n --discovery <path> Use an explicit discovery file\\n --timeout <ms> Set the MCP request timeout\\n -h, --help Show help\\n`;\n}\n\nfunction schemaType(property: any): string {\n const type = Array.isArray(property.type) ? property.type.find((value: string) => value !== \"null\") : property.type;\n if (type === \"integer\") return \"integer\";\n if (type === \"number\") return \"number\";\n if (type === \"boolean\") return \"boolean\";\n if (type === \"array\") return property.items?.type ?? \"value\";\n if (type === \"object\") return \"json\";\n return \"string\";\n}\n","import { cp, mkdir, readFile, rm } from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport { NavopError } from \"@navop/client\";\n\nexport interface SkillInstallOptions {\n target: \"codex\" | \"agents\";\n scope: \"user\" | \"project\";\n force: boolean;\n home?: string;\n cwd?: string;\n}\n\nconst SKILL_ROOT = fileURLToPath(new URL(\"../skills/navop\", import.meta.url));\n\nexport async function printSkill(): Promise<string> {\n return readFile(path.join(SKILL_ROOT, \"SKILL.md\"), \"utf8\");\n}\n\nexport async function installSkill(options: SkillInstallOptions): Promise<string> {\n const root = options.scope === \"user\" ? options.home ?? os.homedir() : options.cwd ?? process.cwd();\n const target = path.join(root, options.target === \"codex\" ? \".codex\" : \".agents\", \"skills\", \"navop\");\n await mkdir(path.dirname(target), { recursive: true });\n try {\n await mkdir(target, { recursive: false });\n } catch (error: any) {\n if (error?.code !== \"EEXIST\") throw error;\n if (!options.force) throw new NavopError(\"skill_exists\", `Navop Skill already exists at ${target}`);\n await rm(target, { recursive: true, force: true });\n await mkdir(target, { recursive: true });\n }\n await cp(SKILL_ROOT, target, { recursive: true, force: false });\n return target;\n}\n","import { readFile } from \"node:fs/promises\";\n\nimport { buildToolArguments } from \"./arguments.js\";\nimport { commandChildren, resolveDomainCommand } from \"./catalog.js\";\nimport { McpConnection, NavopError, readDiscovery, resolveDiscoveryPath } from \"@navop/client\";\nimport { commandHelp, rootHelp, schemaHelp } from \"./help.js\";\nimport { installSkill, printSkill } from \"./skill.js\";\n\ninterface GlobalOptions {\n json: boolean;\n discovery?: string;\n timeoutMs?: number;\n}\n\nexport async function runCli(argv: string[]): Promise<{ result?: unknown; text?: string; json: boolean }> {\n const { args, options } = parseGlobalOptions(argv);\n if (args.length === 0) return { text: rootHelp(), json: false };\n if (hasHelp(args)) return { text: await helpFor(args, options), json: false };\n if (args[0] === \"status\") return { result: await status(options), json: options.json };\n if (args[0] === \"tools\") return { result: await toolCommand([\"list\", ...args.slice(1)], options), json: options.json };\n if (args[0] === \"schema\") return { result: await toolCommand([\"schema\", ...args.slice(1)], options), json: options.json };\n if (args[0] === \"call\") return { result: await toolCommand([\"call\", ...args.slice(1)], options), json: options.json };\n if (args[0] === \"skill\") return { result: await skillCommand(args.slice(1)), json: options.json };\n if (args[0] === \"tool\") return { result: await toolCommand(args.slice(1), options), json: options.json };\n if (\n args.every((value) => !value.startsWith(\"--\"))\n && commandChildren(args).some((candidate) => candidate.path.length > args.length)\n ) {\n return { text: commandHelp(args), json: false };\n }\n return { result: await domainCommand(args, options), json: options.json };\n}\n\nasync function domainCommand(args: string[], options: GlobalOptions): Promise<unknown> {\n const flagIndex = args.findIndex((value) => value.startsWith(\"--\"));\n const commandTokens = flagIndex < 0 ? args : args.slice(0, flagIndex);\n let toolArgs = flagIndex < 0 ? [] : args.slice(flagIndex);\n const command = resolveDomainCommand(commandTokens);\n const connection = await openConnection(options);\n try {\n const tool = await findTool(connection, command.tool);\n toolArgs = await expandConvenienceArguments(command.tool, toolArgs);\n const parsed = buildToolArguments(toolArgs, tool.inputSchema ?? {}, command.fixedArguments);\n return callTool(connection, command.tool, parsed);\n } finally {\n connection.close();\n }\n}\n\nasync function status(options: GlobalOptions): Promise<unknown> {\n const discoveryPath = await resolveDiscoveryPath(options.discovery);\n const discovery = await readDiscovery(discoveryPath);\n const connection = await McpConnection.connect(discovery, { ...timeoutOption(options), initialize: false });\n try {\n const server = await connection.initialize();\n const tools = await listTools(connection);\n const availableTools = tools.map((tool) => String(tool.name)).sort();\n const runtime = await runtimeStatus(connection, tools);\n const permissionMode = permissionModeFromServer(server);\n const toolGroups = Array.isArray(runtime?.toolGroups) ? runtime.toolGroups : [];\n const disabledToolGroups = toolGroups.filter((group: any) => group?.enabled === false);\n return {\n running: true,\n discovery: { path: discoveryPath, app: discovery.app, pid: discovery.pid, host: discovery.host, port: discovery.port, mode: discovery.mode },\n server,\n toolCount: tools.length,\n permissionMode,\n availableTools,\n runtime: runtime ?? null,\n toolGroups,\n disabledToolGroups,\n guidance: capabilityGuidance(permissionMode, disabledToolGroups),\n };\n } finally {\n connection.close();\n }\n}\n\nasync function toolCommand(args: string[], options: GlobalOptions): Promise<unknown> {\n const action = args[0];\n const connection = await openConnection(options);\n try {\n if (action === \"list\") return listTools(connection);\n const name = args[1];\n if (!name) throw new NavopError(\"invalid_arguments\", `navop tool ${action ?? \"\"} requires a tool name`);\n if (action === \"schema\") return findTool(connection, name);\n if (action === \"call\") {\n await findTool(connection, name);\n return callTool(connection, name, await rawArguments(args.slice(2)));\n }\n throw new NavopError(\"invalid_arguments\", \"Usage: navop tool list|schema <tool>|call <tool>\");\n } finally {\n connection.close();\n }\n}\n\nasync function skillCommand(args: string[]): Promise<unknown> {\n if (args[0] === \"print\") return { content: await printSkill() };\n if (args[0] !== \"install\") throw new NavopError(\"invalid_arguments\", \"Usage: navop skill print|install\");\n const options = simpleOptions(args.slice(1));\n const target = options.get(\"target\") ?? \"codex\";\n const scope = options.get(\"scope\") ?? \"user\";\n if (target !== \"codex\" && target !== \"agents\") throw new NavopError(\"invalid_arguments\", \"--target must be codex or agents\");\n if (scope !== \"user\" && scope !== \"project\") throw new NavopError(\"invalid_arguments\", \"--scope must be user or project\");\n return { path: await installSkill({ target, scope, force: options.has(\"force\") }) };\n}\n\nasync function openConnection(options: GlobalOptions): Promise<McpConnection> {\n const discovery = await readDiscovery(await resolveDiscoveryPath(options.discovery));\n return McpConnection.connect(discovery, timeoutOption(options));\n}\n\nfunction timeoutOption(options: GlobalOptions): { timeoutMs?: number } {\n return options.timeoutMs === undefined ? {} : { timeoutMs: options.timeoutMs };\n}\n\nasync function listTools(connection: McpConnection): Promise<any[]> {\n const tools: any[] = [];\n let cursor: string | undefined;\n do {\n const result = await connection.request(\"tools/list\", cursor ? { cursor } : {});\n tools.push(...(result.tools ?? []));\n cursor = result.nextCursor;\n } while (cursor);\n return tools;\n}\n\nasync function findTool(connection: McpConnection, name: string): Promise<any> {\n const tools = await listTools(connection);\n const tool = tools.find((candidate) => candidate.name === name);\n if (!tool) {\n const runtime = await runtimeStatus(connection, tools);\n const groupId = toolGroupForName(name);\n const group = Array.isArray(runtime?.toolGroups)\n ? runtime.toolGroups.find((candidate: any) => candidate?.id === groupId)\n : undefined;\n const groupAction = group?.enabled === false\n ? `Enable the ${groupId} tool group in ${runtime?.settingsPath ?? \"Navop Settings > General > Tool Exposure\"}`\n : `Inspect ${runtime?.settingsPath ?? \"Navop Settings > General > Tool Exposure\"} and the required connection/session`;\n throw new NavopError(\n \"tool_not_found\",\n `Navop tool is not available from the running host: ${name}. ${groupAction}, then retry discovery.`,\n {\n requiredTool: name,\n requiredToolGroup: groupId,\n toolGroup: group ?? null,\n availableTools: tools.map((candidate) => candidate.name).sort(),\n actions: [\n \"Enable MCP Server in Navop Settings > General > MCP\",\n groupAction,\n \"Open the connection or session required by the requested tool\",\n \"Run navop status --json and navop tool list --json again\",\n ],\n },\n );\n }\n return tool;\n}\n\nasync function runtimeStatus(connection: McpConnection, tools: any[]): Promise<any | undefined> {\n if (!tools.some((tool) => tool?.name === \"navop.runtime_status\")) return undefined;\n const result = await connection.request(\"tools/call\", {\n name: \"navop.runtime_status\",\n arguments: {},\n });\n if (result?.isError) return undefined;\n return result?.structuredContent ?? result;\n}\n\nfunction toolGroupForName(name: string): string {\n const prefix = name.split(\".\", 1)[0] ?? name;\n if (prefix === \"ssh\") return \"ssh\";\n if (prefix === \"terminal\") return \"terminal_exec\";\n if (prefix === \"db\") return \"database\";\n if (prefix === \"mongo\" || prefix === \"mongodb\") return \"mongodb\";\n if (prefix === \"internal_functions\" || prefix === \"functions\") return \"internal_functions\";\n return prefix;\n}\n\nfunction permissionModeFromServer(server: any): \"deny\" | \"ask\" | \"allow\" | \"unknown\" {\n const instructions = typeof server?.instructions === \"string\" ? server.instructions : \"\";\n const match = instructions.match(/permission_mode=(deny|ask|allow)/);\n return (match?.[1] as \"deny\" | \"ask\" | \"allow\" | undefined) ?? \"unknown\";\n}\n\nfunction capabilityGuidance(permissionMode: string, disabledToolGroups: any[]): string[] {\n const guidance = [\n \"Tool names and schemas come from the running Navop host through tools/list; the CLI and Skill are not capability authorities.\",\n \"Tool availability also depends on Navop Tool Exposure settings and active connection sessions.\",\n ];\n if (disabledToolGroups.length > 0) {\n guidance.push(\n `Disabled host tool groups: ${disabledToolGroups.map((group: any) => group.id).join(\", \")}. Enable only the groups needed by the user.`,\n );\n }\n if (permissionMode === \"deny\") guidance.push(\"Mutating tools are denied by the current permission mode.\");\n else if (permissionMode === \"ask\") guidance.push(\"Mutating tools require approval in Navop; never bypass a rejection.\");\n else if (permissionMode === \"allow\") guidance.push(\"Mutating tools run automatically; confirm user intent before destructive actions.\");\n else guidance.push(\"Inspect the Navop MCP permission profile before attempting mutations.\");\n return guidance;\n}\n\nasync function callTool(connection: McpConnection, name: string, args: Record<string, unknown>): Promise<unknown> {\n const result = await connection.request(\"tools/call\", { name, arguments: args });\n if (result?.isError) throw new NavopError(\"tool_failed\", toolMessage(result), result);\n return result?.structuredContent ?? result;\n}\n\nfunction parseGlobalOptions(argv: string[]): { args: string[]; options: GlobalOptions } {\n const args: string[] = [];\n const options: GlobalOptions = { json: false };\n for (let index = 0; index < argv.length; index += 1) {\n const token = argv[index]!;\n if (token === \"--json\") options.json = true;\n else if (token === \"--discovery\") options.discovery = requiredValue(argv, ++index, token);\n else if (token === \"--timeout\") options.timeoutMs = positiveInteger(requiredValue(argv, ++index, token), token);\n else args.push(token);\n }\n return { args, options };\n}\n\nasync function helpFor(args: string[], options: GlobalOptions): Promise<string> {\n const path = args.filter((value) => value !== \"--help\" && value !== \"-h\");\n if (path.length === 0) return rootHelp();\n let command;\n try { command = resolveDomainCommand(path); } catch { return commandHelp(path); }\n try {\n const connection = await openConnection(options);\n try {\n const tool = await findTool(connection, command.tool);\n return schemaHelp(path, command.summary, tool.inputSchema ?? {}, command.fixedArguments);\n } finally { connection.close(); }\n } catch { return commandHelp(path); }\n}\n\nfunction hasHelp(args: string[]): boolean {\n return args.includes(\"--help\") || args.includes(\"-h\");\n}\n\nasync function expandConvenienceArguments(tool: string, args: string[]): Promise<string[]> {\n let expanded = args;\n if (tool.startsWith(\"db.\") || tool.startsWith(\"sftp.\")) {\n expanded = replaceFlagAlias(expanded, \"--connection\", \"--target\");\n }\n if (tool.startsWith(\"redis.\")) {\n expanded = replaceFlagAlias(expanded, \"--connection-id\", \"--target\");\n }\n if (tool.startsWith(\"mongo.\")) {\n expanded = replaceFlagAlias(expanded, \"--connection-id\", \"--target\");\n }\n if (tool !== \"sftp.write\") return expanded;\n const stdinIndex = expanded.indexOf(\"--stdin\");\n const fileIndex = expanded.indexOf(\"--content-file\");\n if (stdinIndex >= 0 && fileIndex >= 0) throw new NavopError(\"invalid_arguments\", \"use only one of --stdin or --content-file\");\n if (stdinIndex >= 0) return replaceWithContent(expanded, stdinIndex, 1, await readStdin());\n if (fileIndex >= 0) return replaceWithContent(expanded, fileIndex, 2, await readFile(requiredValue(expanded, fileIndex + 1, \"--content-file\")));\n return expanded;\n}\n\nfunction replaceFlagAlias(args: string[], alias: string, canonical: string): string[] {\n const aliasIndex = args.indexOf(alias);\n if (aliasIndex < 0) return args;\n if (args.includes(canonical)) {\n throw new NavopError(\"invalid_arguments\", `use only one of ${alias} or ${canonical}`);\n }\n const next = [...args];\n next[aliasIndex] = canonical;\n return next;\n}\n\nfunction replaceWithContent(args: string[], index: number, count: number, content: string | Buffer): string[] {\n const next = [...args];\n next.splice(index, count, \"--content-base64\", Buffer.from(content).toString(\"base64\"));\n return next;\n}\n\nasync function rawArguments(args: string[]): Promise<Record<string, unknown>> {\n const options = simpleOptions(args);\n const sources = [options.has(\"arguments\"), options.has(\"file\"), options.has(\"stdin\")].filter(Boolean).length;\n if (sources > 1) throw new NavopError(\"invalid_arguments\", \"use only one of --arguments, --file, or --stdin\");\n let text = options.get(\"arguments\") ?? \"{}\";\n if (options.has(\"file\")) text = await readFile(options.get(\"file\")!, \"utf8\");\n if (options.has(\"stdin\")) text = await readStdin();\n try {\n const value = JSON.parse(text);\n if (!value || Array.isArray(value) || typeof value !== \"object\") throw new Error();\n return value;\n } catch { throw new NavopError(\"invalid_arguments\", \"tool arguments must be a JSON object\"); }\n}\n\nfunction simpleOptions(args: string[]): Map<string, string> {\n const options = new Map<string, string>();\n for (let index = 0; index < args.length; index += 1) {\n const token = args[index]!;\n if (!token.startsWith(\"--\")) throw new NavopError(\"invalid_arguments\", `unexpected argument: ${token}`);\n const name = token.slice(2);\n if ([\"force\", \"stdin\"].includes(name)) options.set(name, \"true\");\n else options.set(name, requiredValue(args, ++index, token));\n }\n return options;\n}\n\nfunction requiredValue(args: string[], index: number, option: string): string {\n const value = args[index];\n if (!value || value.startsWith(\"--\")) throw new NavopError(\"invalid_arguments\", `${option} requires a value`);\n return value;\n}\n\nfunction positiveInteger(value: string, option: string): number {\n const parsed = Number(value);\n if (!Number.isSafeInteger(parsed) || parsed <= 0) throw new NavopError(\"invalid_arguments\", `${option} must be a positive integer`);\n return parsed;\n}\n\nfunction readStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n let text = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk) => { text += chunk; });\n process.stdin.on(\"end\", () => resolve(text));\n process.stdin.on(\"error\", reject);\n });\n}\n\nfunction toolMessage(result: any): string {\n return result?.structuredContent?.message ?? result?.content?.[0]?.text ?? \"Navop tool call failed\";\n}\n"],"mappings":"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","names":["NavopError","path","path","path","NavopError","readFile","NavopError","command","NavopError","path","readFile"]}
@@ -0,0 +1,37 @@
1
+ interface JsonSchema {
2
+ type?: string | string[];
3
+ properties?: Record<string, JsonSchema>;
4
+ required?: string[];
5
+ items?: JsonSchema;
6
+ enum?: unknown[];
7
+ }
8
+ declare function buildToolArguments(argv: string[], schema: JsonSchema, fixed?: Record<string, unknown>): Record<string, unknown>;
9
+
10
+ interface DomainCommand {
11
+ path: string[];
12
+ tool: string;
13
+ summary: string;
14
+ fixedArguments?: Record<string, unknown>;
15
+ }
16
+ declare const DOMAIN_COMMANDS: DomainCommand[];
17
+ declare function resolveDomainCommand(tokens: string[]): DomainCommand;
18
+
19
+ declare function rootHelp(): string;
20
+
21
+ declare function runCli(argv: string[]): Promise<{
22
+ result?: unknown;
23
+ text?: string;
24
+ json: boolean;
25
+ }>;
26
+
27
+ interface SkillInstallOptions {
28
+ target: "codex" | "agents";
29
+ scope: "user" | "project";
30
+ force: boolean;
31
+ home?: string;
32
+ cwd?: string;
33
+ }
34
+ declare function printSkill(): Promise<string>;
35
+ declare function installSkill(options: SkillInstallOptions): Promise<string>;
36
+
37
+ export { DOMAIN_COMMANDS, buildToolArguments, installSkill, printSkill, resolveDomainCommand, rootHelp, runCli };
package/dist/index.js ADDED
@@ -0,0 +1,19 @@
1
+ import {
2
+ DOMAIN_COMMANDS,
3
+ buildToolArguments,
4
+ installSkill,
5
+ printSkill,
6
+ resolveDomainCommand,
7
+ rootHelp,
8
+ runCli
9
+ } from "./chunk-QRRIPLVN.js";
10
+ export {
11
+ DOMAIN_COMMANDS,
12
+ buildToolArguments,
13
+ installSkill,
14
+ printSkill,
15
+ resolveDomainCommand,
16
+ rootHelp,
17
+ runCli
18
+ };
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/navop.js ADDED
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ runCli
4
+ } from "./chunk-QRRIPLVN.js";
5
+
6
+ // src/navop.ts
7
+ import { exitCode } from "@navop/client";
8
+
9
+ // src/output.ts
10
+ import { NavopError } from "@navop/client";
11
+ function success(result) {
12
+ return JSON.stringify({ ok: true, result });
13
+ }
14
+ function failure(error) {
15
+ const normalized = error instanceof NavopError ? error : new NavopError("protocol_error", error instanceof Error ? error.message : String(error));
16
+ return JSON.stringify({
17
+ ok: false,
18
+ code: normalized.code,
19
+ message: normalized.message,
20
+ ...normalized.details === void 0 ? {} : { details: normalized.details }
21
+ });
22
+ }
23
+
24
+ // package.json
25
+ var package_default = {
26
+ name: "@navop/cli",
27
+ version: "0.2.0",
28
+ description: "Terminal CLI and Agent Skill for operating resources in a running Navop desktop application",
29
+ type: "module",
30
+ bin: { navop: "dist/navop.js" },
31
+ exports: "./dist/index.js",
32
+ types: "./dist/index.d.ts",
33
+ files: ["dist", "skills", "README.md"],
34
+ engines: { node: ">=20" },
35
+ publishConfig: { access: "public" },
36
+ scripts: {
37
+ build: "tsup src/navop.ts src/index.ts --format esm --platform node --target node20 --clean --sourcemap --dts"
38
+ },
39
+ dependencies: { "@navop/client": "0.2.0" },
40
+ license: "MIT",
41
+ repository: { type: "git", url: "git+https://github.com/feigeCode/navop-mcp.git", directory: "packages/cli" },
42
+ keywords: ["navop", "cli", "terminal", "skill", "agent"]
43
+ };
44
+
45
+ // src/version.ts
46
+ var PACKAGE_VERSION = package_default.version;
47
+
48
+ // src/navop.ts
49
+ async function main(argv) {
50
+ if (argv.includes("--version") || argv.includes("-V")) {
51
+ process.stdout.write(`${PACKAGE_VERSION}
52
+ `);
53
+ return;
54
+ }
55
+ try {
56
+ const output = await runCli(argv);
57
+ if (output.text !== void 0) process.stdout.write(output.text);
58
+ else process.stdout.write(`${output.json ? success(output.result) : formatHuman(output.result)}
59
+ `);
60
+ } catch (error) {
61
+ const json = argv.includes("--json");
62
+ (json ? process.stdout : process.stderr).write(`${json ? failure(error) : error instanceof Error ? error.message : String(error)}
63
+ `);
64
+ process.exitCode = exitCode(error);
65
+ }
66
+ }
67
+ function formatHuman(value) {
68
+ if (value && typeof value === "object" && "content" in value) return String(value.content);
69
+ return typeof value === "string" ? value : JSON.stringify(value, null, 2);
70
+ }
71
+ main(process.argv.slice(2)).catch((error) => {
72
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}
73
+ `);
74
+ process.exitCode = exitCode(error);
75
+ });
76
+ //# sourceMappingURL=navop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/navop.ts","../src/output.ts","../package.json","../src/version.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { exitCode } from \"@navop/client\";\nimport { failure, success } from \"./output.js\";\nimport { runCli } from \"./runner.js\";\nimport { PACKAGE_VERSION } from \"./version.js\";\n\nasync function main(argv: string[]): Promise<void> {\n if (argv.includes(\"--version\") || argv.includes(\"-V\")) {\n process.stdout.write(`${PACKAGE_VERSION}\\n`);\n return;\n }\n try {\n const output = await runCli(argv);\n if (output.text !== undefined) process.stdout.write(output.text);\n else process.stdout.write(`${output.json ? success(output.result) : formatHuman(output.result)}\\n`);\n } catch (error) {\n const json = argv.includes(\"--json\");\n (json ? process.stdout : process.stderr).write(`${json ? failure(error) : error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = exitCode(error);\n }\n}\n\nfunction formatHuman(value: unknown): string {\n if (value && typeof value === \"object\" && \"content\" in value) return String((value as { content: unknown }).content);\n return typeof value === \"string\" ? value : JSON.stringify(value, null, 2);\n}\n\nmain(process.argv.slice(2)).catch((error) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = exitCode(error);\n});\n","import { NavopError } from \"@navop/client\";\n\nexport function success(result: unknown): string {\n return JSON.stringify({ ok: true, result });\n}\n\nexport function failure(error: unknown): string {\n const normalized = error instanceof NavopError\n ? error\n : new NavopError(\"protocol_error\", error instanceof Error ? error.message : String(error));\n return JSON.stringify({\n ok: false,\n code: normalized.code,\n message: normalized.message,\n ...(normalized.details === undefined ? {} : { details: normalized.details }),\n });\n}\n","{\n \"name\": \"@navop/cli\",\n \"version\": \"0.2.0\",\n \"description\": \"Terminal CLI and Agent Skill for operating resources in a running Navop desktop application\",\n \"type\": \"module\",\n \"bin\": { \"navop\": \"dist/navop.js\" },\n \"exports\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"files\": [\"dist\", \"skills\", \"README.md\"],\n \"engines\": { \"node\": \">=20\" },\n \"publishConfig\": { \"access\": \"public\" },\n \"scripts\": {\n \"build\": \"tsup src/navop.ts src/index.ts --format esm --platform node --target node20 --clean --sourcemap --dts\"\n },\n \"dependencies\": { \"@navop/client\": \"0.2.0\" },\n \"license\": \"MIT\",\n \"repository\": { \"type\": \"git\", \"url\": \"git+https://github.com/feigeCode/navop-mcp.git\", \"directory\": \"packages/cli\" },\n \"keywords\": [\"navop\", \"cli\", \"terminal\", \"skill\", \"agent\"]\n}\n","import packageJson from \"../package.json\" with { type: \"json\" };\n\nexport const PACKAGE_VERSION = packageJson.version;\n"],"mappings":";;;;;;AACA,SAAS,gBAAgB;;;ACDzB,SAAS,kBAAkB;AAEpB,SAAS,QAAQ,QAAyB;AAC/C,SAAO,KAAK,UAAU,EAAE,IAAI,MAAM,OAAO,CAAC;AAC5C;AAEO,SAAS,QAAQ,OAAwB;AAC9C,QAAM,aAAa,iBAAiB,aAChC,QACA,IAAI,WAAW,kBAAkB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAC3F,SAAO,KAAK,UAAU;AAAA,IACpB,IAAI;AAAA,IACJ,MAAM,WAAW;AAAA,IACjB,SAAS,WAAW;AAAA,IACpB,GAAI,WAAW,YAAY,SAAY,CAAC,IAAI,EAAE,SAAS,WAAW,QAAQ;AAAA,EAC5E,CAAC;AACH;;;AChBA;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,KAAO,EAAE,OAAS,gBAAgB;AAAA,EAClC,SAAW;AAAA,EACX,OAAS;AAAA,EACT,OAAS,CAAC,QAAQ,UAAU,WAAW;AAAA,EACvC,SAAW,EAAE,MAAQ,OAAO;AAAA,EAC5B,eAAiB,EAAE,QAAU,SAAS;AAAA,EACtC,SAAW;AAAA,IACT,OAAS;AAAA,EACX;AAAA,EACA,cAAgB,EAAE,iBAAiB,QAAQ;AAAA,EAC3C,SAAW;AAAA,EACX,YAAc,EAAE,MAAQ,OAAO,KAAO,kDAAkD,WAAa,eAAe;AAAA,EACpH,UAAY,CAAC,SAAS,OAAO,YAAY,SAAS,OAAO;AAC3D;;;AChBO,IAAM,kBAAkB,gBAAY;;;AHI3C,eAAe,KAAK,MAA+B;AACjD,MAAI,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,IAAI,GAAG;AACrD,YAAQ,OAAO,MAAM,GAAG,eAAe;AAAA,CAAI;AAC3C;AAAA,EACF;AACA,MAAI;AACF,UAAM,SAAS,MAAM,OAAO,IAAI;AAChC,QAAI,OAAO,SAAS,OAAW,SAAQ,OAAO,MAAM,OAAO,IAAI;AAAA,QAC1D,SAAQ,OAAO,MAAM,GAAG,OAAO,OAAO,QAAQ,OAAO,MAAM,IAAI,YAAY,OAAO,MAAM,CAAC;AAAA,CAAI;AAAA,EACpG,SAAS,OAAO;AACd,UAAM,OAAO,KAAK,SAAS,QAAQ;AACnC,KAAC,OAAO,QAAQ,SAAS,QAAQ,QAAQ,MAAM,GAAG,OAAO,QAAQ,KAAK,IAAI,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,CAAI;AACpI,YAAQ,WAAW,SAAS,KAAK;AAAA,EACnC;AACF;AAEA,SAAS,YAAY,OAAwB;AAC3C,MAAI,SAAS,OAAO,UAAU,YAAY,aAAa,MAAO,QAAO,OAAQ,MAA+B,OAAO;AACnH,SAAO,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,OAAO,MAAM,CAAC;AAC1E;AAEA,KAAK,QAAQ,KAAK,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU;AAC3C,UAAQ,OAAO,MAAM,GAAG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,CAAI;AAClF,UAAQ,WAAW,SAAS,KAAK;AACnC,CAAC;","names":[]}
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@navop/cli",
3
+ "version": "0.2.0",
4
+ "description": "Terminal CLI and Agent Skill for operating resources in a running Navop desktop application",
5
+ "type": "module",
6
+ "bin": { "navop": "dist/navop.js" },
7
+ "exports": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "files": ["dist", "skills", "README.md"],
10
+ "engines": { "node": ">=20" },
11
+ "publishConfig": { "access": "public" },
12
+ "scripts": {
13
+ "build": "tsup src/navop.ts src/index.ts --format esm --platform node --target node20 --clean --sourcemap --dts"
14
+ },
15
+ "dependencies": { "@navop/client": "0.2.0" },
16
+ "license": "MIT",
17
+ "repository": { "type": "git", "url": "git+https://github.com/feigeCode/navop-mcp.git", "directory": "packages/cli" },
18
+ "keywords": ["navop", "cli", "terminal", "skill", "agent"]
19
+ }
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: navop
3
+ description: Use terminal commands to discover and operate resources exposed by a running Navop desktop application through its host-authoritative Public MCP runtime.
4
+ ---
5
+
6
+ # Navop
7
+
8
+ Use this Skill when an AI Agent needs to operate Navop resources from a terminal. It keeps a compact workflow in context and loads command help or live schemas only when needed, so the Agent does not carry the complete Navop tool catalog in every turn. This can reduce repeated tool-definition tokens and other context overhead; the amount depends on the client and the number of exposed tools.
9
+
10
+ The CLI still connects internally to Navop's authenticated loopback Public MCP runtime. Navop remains authoritative for Tool Exposure, permissions, approvals, resource IDs, sessions, results, and audit records. The CLI does not implement SSH, SFTP, terminal, database, Redis, or MongoDB business logic.
11
+
12
+ The Navop CLI must be installed globally before this Skill can operate resources. Check the command, and install the latest client when it is missing:
13
+
14
+ ```bash
15
+ navop --version
16
+ npm install -g @navop/cli@latest
17
+ navop --version
18
+ ```
19
+
20
+ Every Agent-initiated command must include `--json`. Start with:
21
+
22
+ ```bash
23
+ navop status --json
24
+ ```
25
+
26
+ Read the status result before choosing a tool:
27
+
28
+ - If Public MCP is unavailable, ask the user to start Navop and enable **Settings > General > MCP > MCP Server**.
29
+ - Inspect `permissionMode`, `availableTools`, `toolGroups`, `disabledToolGroups`, and `guidance`.
30
+ - Treat the running host's `tools/list` response and `navop.runtime_status` result as authoritative. The npm package and this Skill do not define the host's complete tool set.
31
+ - If a tool is unavailable, report its exact name and host-reported tool-group state. Ask the user to enable that group under the returned `settingsPath` and open the required connection or session.
32
+ - `deny` blocks mutations. `ask` requires approval in Navop. `allow` runs mutations automatically, but still requires clear user intent for destructive actions.
33
+ - Never claim a capability is enabled merely because the CLI has a convenience command; the live `availableTools` list is authoritative.
34
+
35
+ Discover the current client and available command surface when needed:
36
+
37
+ ```bash
38
+ navop --help
39
+ navop tool list --json
40
+ navop tool schema <tool-name> --json
41
+ navop db query --help
42
+ ```
43
+
44
+ If a domain command is exposed in help, use its help and then validate flags against the live schema. Otherwise call the exact host tool:
45
+
46
+ ```bash
47
+ navop tool call <tool-name> --arguments '<json-object-matching-live-schema>' --json
48
+ ```
49
+
50
+ Never invent a command, tool name, flag, argument, resource ID, or session ID from examples in this Skill. Discover resource and session methods from `tool list`, inspect their schemas, and use only IDs returned by Navop.
51
+
52
+ ## Updating the npm client
53
+
54
+ Check the registry and installed executable when diagnosing a stale client:
55
+
56
+ ```bash
57
+ npm view @navop/cli version
58
+ navop --version
59
+ ```
60
+
61
+ Update the installed CLI before using features that require a newer client:
62
+
63
+ ```bash
64
+ npm install -g @navop/cli@latest
65
+ npm update -g @navop/cli
66
+ navop --version
67
+ navop status --json
68
+ ```
69
+
70
+ Prefer reads before writes. Preserve Navop permission and approval decisions. Never work around a denial. Do not retry a mutating operation after timeout or connection loss because its outcome may be unknown. Do not interrupt or control a visible terminal unless the user explicitly requests that action.
71
+
72
+ Read these references as needed:
73
+
74
+ - [commands.md](references/commands.md): dynamic command discovery and Bash examples.
75
+ - [workflows.md](references/workflows.md): safe discovery and execution sequences.
76
+ - [safety.md](references/safety.md): approvals, writes, terminal ownership, and retry rules.
77
+ - [errors.md](references/errors.md): JSON envelope, exit codes, and recovery behavior.
@@ -0,0 +1,65 @@
1
+ # Dynamic command discovery
2
+
3
+ All Agent calls include `--json`. Add `--discovery <path>` only when the user or host supplies an explicit discovery file.
4
+
5
+ The running Navop host is authoritative for tool names, descriptions, annotations, and input schemas:
6
+
7
+ ```bash
8
+ navop status --json
9
+ navop --help
10
+ navop tool list --json
11
+ navop tool schema <tool-name> --json
12
+ navop tool call <tool-name> --arguments '<json-object-matching-live-schema>' --json
13
+ ```
14
+
15
+ Compatibility aliases are available when useful:
16
+
17
+ ```bash
18
+ navop tools --json
19
+ navop schema <tool-name> --json
20
+ navop call <tool-name> --arguments '<json-object>' --json
21
+ ```
22
+
23
+ ## Representative Bash commands
24
+
25
+ First discover the connection or session IDs with the live host tools. Replace every placeholder with an ID returned by Navop, and inspect the domain help/schema before executing:
26
+
27
+ ```bash
28
+ navop connections list --json
29
+ navop connections sessions --json
30
+
31
+ navop ssh exec \
32
+ --target <ssh-session-id> \
33
+ --command 'uname -a' \
34
+ --json
35
+
36
+ navop sftp list \
37
+ --connection <ssh-connection-id-or-name> \
38
+ --path /var/log \
39
+ --json
40
+
41
+ navop redis get \
42
+ --connection-id <redis-connection-id-or-name> \
43
+ --key app:status \
44
+ --json
45
+
46
+ navop mongo find \
47
+ --connection-id <mongo-session-id> \
48
+ --database app \
49
+ --collection users \
50
+ --filter '{"active":true}' \
51
+ --limit 20 \
52
+ --json
53
+
54
+ navop db query \
55
+ --connection <database-connection-id-or-name> \
56
+ --sql 'SELECT 1' \
57
+ --json
58
+
59
+ navop terminal read \
60
+ --target <terminal-session-id> \
61
+ --lines 80 \
62
+ --json
63
+ ```
64
+
65
+ These are convenience mappings, not a promise that every host exposes every domain. When a convenience command is absent or does not match the live schema, use `tool list`, `tool schema`, and `tool call`.
@@ -0,0 +1,26 @@
1
+ # JSON and errors
2
+
3
+ Successful `--json` output:
4
+
5
+ ```json
6
+ {"ok":true,"result":{}}
7
+ ```
8
+
9
+ Failed `--json` output:
10
+
11
+ ```json
12
+ {"ok":false,"code":"...","message":"...","details":{}}
13
+ ```
14
+
15
+ Exit codes:
16
+
17
+ - `0`: success
18
+ - `2`: invalid CLI arguments or an existing Skill target
19
+ - `3`: Navop is not running or Public MCP is unavailable
20
+ - `4`: discovery or MCP protocol error
21
+ - `5`: requested Navop tool is not exposed
22
+ - `6`: tool failure, permission denial, or approval rejection
23
+ - `8`: timeout
24
+ - `9`: connection closed
25
+
26
+ For exit `3`, ask the user to start Navop and enable **Settings > General > MCP > MCP Server**. For exit `5`, report the exact missing tool and ask the user to enable its group under **Settings > General > Tool Exposure** and open the relevant connection/session. For exit `6`, report the denial or tool error; never bypass it. For exits `8` or `9`, retry read-only discovery when appropriate, but do not retry mutations automatically.
@@ -0,0 +1,14 @@
1
+ # Safety and ownership
2
+
3
+ Navop is the only implementation, permission, approval, session, and audit boundary. The CLI must not bypass it.
4
+
5
+ - Respect approval rejection and permission denial as final for the attempted operation.
6
+ - Prefer read-only commands before mutations.
7
+ - Do not retry a mutation after timeout or connection loss; the outcome may be unknown.
8
+ - Do not send arbitrary bytes to a visible terminal.
9
+ - Do not map Agent cancellation to terminal interruption.
10
+ - Use `navop terminal interrupt ... --json` only after an explicit user request to interrupt the visible foreground process.
11
+ - Do not expose or print the discovery token.
12
+ - Do not guess connection or session identifiers.
13
+ - Do not silently overwrite a Skill or an SFTP/local file target.
14
+ - Do not use the low-level tool interface to bypass a safer domain workflow.
@@ -0,0 +1,16 @@
1
+ # Safe workflows
2
+
3
+ ## Discover a target
4
+
5
+ 1. Run `navop status --json`.
6
+ 2. Run `navop tool list --json` and identify a host-provided read-only resource or session discovery tool.
7
+ 3. Run `navop tool schema <tool-name> --json`.
8
+ 4. Call that discovery tool and use only an ID returned by Navop.
9
+
10
+ Never infer an ID from a title, hostname, tab label, or earlier conversation.
11
+
12
+ ## Choose an operation
13
+
14
+ Use live tool annotations and descriptions. Prefer a tool with `readOnlyHint=true` before a mutating tool. Inspect the live input schema instead of relying on remembered flags or examples.
15
+
16
+ If a call returns a command, job, or continuation ID, discover matching status/output methods from `tool list`; do not rerun the original mutation merely to retrieve its result.