specli 0.0.30 → 0.0.32

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.
@@ -25,7 +25,7 @@ import { type SpecliOptions } from "../client/index.js";
25
25
  * tool already has the spec loaded and ready to use.
26
26
  */
27
27
  export declare function specliTool(options: SpecliOptions): Promise<import("ai").Tool<{
28
- command: "list" | "exec" | "help";
28
+ command: "list" | "help" | "exec";
29
29
  resource?: string | undefined;
30
30
  action?: string | undefined;
31
31
  args?: string[] | undefined;
package/dist/cli/main.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { readFileSync } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { Command } from "commander";
4
+ import { Command, Help } from "commander";
5
5
  import { getArgValue, hasAnyArg } from "./runtime/argv.js";
6
6
  import { collectRepeatable } from "./runtime/collect.js";
7
7
  /**
@@ -28,6 +28,7 @@ import { deleteToken, getToken, setToken } from "./runtime/profile/secrets.js";
28
28
  import { readProfiles, upsertProfile, writeProfiles, } from "./runtime/profile/store.js";
29
29
  export async function main(argv, options = {}) {
30
30
  const program = new Command();
31
+ const defaultHelp = new Help();
31
32
  // Get version - use embedded version if available, otherwise read from package.json
32
33
  const cliVersion = options.version ?? getPackageVersion();
33
34
  program
@@ -177,6 +178,10 @@ export async function main(argv, options = {}) {
177
178
  process.stdout.write(`- ${program.name()} ${op.resource} ${op.action}${args}\n`);
178
179
  }
179
180
  }
181
+ process.stdout.write("\nTip: explore required flags with --help at each level:\n" +
182
+ `- ${program.name()} --help\n` +
183
+ `- ${program.name()} <resource> --help\n` +
184
+ `- ${program.name()} <resource> <action> --help\n`);
180
185
  });
181
186
  addGeneratedCommands(program, {
182
187
  servers: ctx.servers,
@@ -189,5 +194,128 @@ export async function main(argv, options = {}) {
189
194
  auth: options.auth,
190
195
  },
191
196
  });
197
+ program.configureHelp({
198
+ formatHelp: (cmd, _helper) => {
199
+ // Only customize the top-level help. Subcommands should keep
200
+ // their own default or explicitly configured help.
201
+ if (cmd !== program)
202
+ return defaultHelp.formatHelp(cmd, defaultHelp);
203
+ const lines = [];
204
+ const name = program.name();
205
+ const embedded = Boolean(options.embeddedSpecText);
206
+ lines.push(`Usage: ${name} [options] [command]`);
207
+ lines.push("");
208
+ lines.push(program.description());
209
+ lines.push("");
210
+ // OpenAPI-derived commands first (resources)
211
+ if (ctx.commands.resources.length > 0) {
212
+ lines.push("OpenAPI Commands:");
213
+ const resources = [...ctx.commands.resources]
214
+ .map((r) => r.resource)
215
+ .sort((a, b) => a.localeCompare(b));
216
+ for (const r of resources) {
217
+ lines.push(` ${r}`);
218
+ }
219
+ lines.push("");
220
+ }
221
+ // Non-OpenAPI commands (built-ins)
222
+ lines.push("Global Commands:");
223
+ const globalCommands = ["login", "logout", "whoami", "__schema", "help"];
224
+ const maxCmdLen = Math.max(...globalCommands.map((c) => c.length));
225
+ for (const cmdName of globalCommands) {
226
+ const c = program.commands.find((c) => c.name() === cmdName);
227
+ if (!c)
228
+ continue;
229
+ const term = cmdName === "login"
230
+ ? "login [token]"
231
+ : cmdName === "help"
232
+ ? "help [command]"
233
+ : cmdName;
234
+ const desc = c.description();
235
+ const pad = " ".repeat(Math.max(1, maxCmdLen - cmdName.length + 2));
236
+ lines.push(` ${term}${pad}${desc}`);
237
+ }
238
+ lines.push("");
239
+ // Global options last
240
+ lines.push("Global Options:");
241
+ const optionRows = [];
242
+ for (const opt of program.options) {
243
+ // In compiled binaries the spec is embedded; --spec is meaningless.
244
+ if (embedded && opt.long === "--spec")
245
+ continue;
246
+ optionRows.push({ flags: opt.flags, desc: opt.description });
247
+ }
248
+ optionRows.push({
249
+ flags: "-h, --help",
250
+ desc: "display help for command",
251
+ });
252
+ const maxOptLen = Math.max(...optionRows.map((o) => o.flags.length));
253
+ for (const row of optionRows) {
254
+ const pad = " ".repeat(Math.max(1, maxOptLen - row.flags.length + 2));
255
+ lines.push(` ${row.flags}${pad}${row.desc}`);
256
+ }
257
+ lines.push("");
258
+ lines.push("Agent workflow:");
259
+ lines.push(` 1) ${name} __schema --json --min`);
260
+ lines.push(` 2) ${name} <resource> --help`);
261
+ lines.push(` 3) ${name} <resource> <action> --help`);
262
+ lines.push("");
263
+ return lines.join("\n");
264
+ },
265
+ });
266
+ if (argv.length <= 2) {
267
+ program.outputHelp();
268
+ return;
269
+ }
270
+ const args = argv.slice(2);
271
+ const flagWithValue = new Set([
272
+ "--spec",
273
+ "--server",
274
+ "--server-var",
275
+ "--auth",
276
+ "--bearer-token",
277
+ "--oauth-token",
278
+ "--username",
279
+ "--password",
280
+ "--api-key",
281
+ ]);
282
+ const boolFlags = new Set(["--json"]);
283
+ const passthroughFlags = new Set(["-h", "--help", "-v", "--version"]);
284
+ let hasSubcommand = false;
285
+ let onlyKnownGlobals = true;
286
+ for (let i = 0; i < args.length; i++) {
287
+ const a = args[i];
288
+ if (!a)
289
+ continue;
290
+ if (passthroughFlags.has(a))
291
+ break;
292
+ if (boolFlags.has(a))
293
+ continue;
294
+ if (flagWithValue.has(a)) {
295
+ i++;
296
+ continue;
297
+ }
298
+ if (a.startsWith("--") && a.includes("=")) {
299
+ const key = a.slice(0, a.indexOf("="));
300
+ if (!flagWithValue.has(key) &&
301
+ !boolFlags.has(key) &&
302
+ !passthroughFlags.has(key)) {
303
+ onlyKnownGlobals = false;
304
+ }
305
+ continue;
306
+ }
307
+ if (a.startsWith("--") || a.startsWith("-")) {
308
+ onlyKnownGlobals = false;
309
+ continue;
310
+ }
311
+ hasSubcommand = true;
312
+ break;
313
+ }
314
+ if (!hasSubcommand &&
315
+ onlyKnownGlobals &&
316
+ !hasAnyArg(argv, ["-h", "--help", "-v", "--version"])) {
317
+ program.outputHelp();
318
+ return;
319
+ }
192
320
  await program.parseAsync(argv);
193
321
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specli",
3
- "version": "0.0.30",
3
+ "version": "0.0.32",
4
4
  "description": "Run any OpenAPI spec as a CLI. Built for Agents.",
5
5
  "repository": {
6
6
  "type": "git",