specli 0.0.31 → 0.0.33

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
@@ -45,7 +46,6 @@ export async function main(argv, options = {}) {
45
46
  .option("--api-key <key>", "API key value")
46
47
  .option("--json", "Machine-readable output")
47
48
  .showHelpAfterError();
48
- program.addHelpText("after", `\nAgent workflow:\n 1) ${options.cliName ?? "specli"} __schema --json --min\n 2) ${options.cliName ?? "specli"} <resource> --help\n 3) ${options.cliName ?? "specli"} <resource> <action> --help\n`);
49
49
  // If user asks for help and we have no embedded spec and no --spec, show minimal help.
50
50
  const spec = getArgValue(argv, "--spec");
51
51
  const wantsHelp = hasAnyArg(argv, ["-h", "--help"]);
@@ -152,6 +152,7 @@ export async function main(argv, options = {}) {
152
152
  .description("Print indexed operations (machine-readable when --json)")
153
153
  .option("--pretty", "Pretty-print JSON when used with --json")
154
154
  .option("--min", "Minimal JSON output (commands + metadata only)")
155
+ .option("--commands", "List all <resource> <action> commands (can be large)")
155
156
  .action(async (_opts, command) => {
156
157
  const flags = command.optsWithGlobals();
157
158
  if (flags.json) {
@@ -165,11 +166,17 @@ export async function main(argv, options = {}) {
165
166
  }
166
167
  process.stdout.write(`${ctx.schema.openapi.title ?? "(untitled)"}\n`);
167
168
  process.stdout.write(`OpenAPI: ${ctx.schema.openapi.version}\n`);
168
- process.stdout.write(`Spec: ${ctx.schema.spec.id} (${ctx.schema.spec.source})\n`);
169
- process.stdout.write(`Fingerprint: ${ctx.schema.spec.fingerprint}\n`);
170
169
  process.stdout.write(`Servers: ${ctx.schema.servers.length}\n`);
171
170
  process.stdout.write(`Auth Schemes: ${ctx.schema.authSchemes.length}\n`);
172
- if (ctx.schema.planned?.length) {
171
+ process.stdout.write(`Spec: ${ctx.schema.spec.id} (${ctx.schema.spec.source})\n`);
172
+ // Token-efficient default output: list resources (top-level commands)
173
+ // and push the user/agent toward --help for details.
174
+ process.stdout.write(`\nResources: ${ctx.commands.resources.length}\n\n`);
175
+ const resources = [...ctx.commands.resources].sort((a, b) => a.resource.localeCompare(b.resource));
176
+ for (const r of resources) {
177
+ process.stdout.write(`- ${r.resource} (${r.actions.length} actions)\n`);
178
+ }
179
+ if (flags.commands && ctx.schema.planned?.length) {
173
180
  process.stdout.write(`\nCommands: ${ctx.schema.planned.length}\n\n`);
174
181
  for (const op of ctx.schema.planned) {
175
182
  const args = op.pathArgs.length
@@ -178,10 +185,10 @@ export async function main(argv, options = {}) {
178
185
  process.stdout.write(`- ${program.name()} ${op.resource} ${op.action}${args}\n`);
179
186
  }
180
187
  }
181
- process.stdout.write("\nTip: explore required flags with --help at each level:\n" +
182
- `- ${program.name()} --help\n` +
188
+ process.stdout.write("\nNext:\n" +
183
189
  `- ${program.name()} <resource> --help\n` +
184
- `- ${program.name()} <resource> <action> --help\n`);
190
+ `- ${program.name()} <resource> <action> --help\n` +
191
+ "\nNote: Use --help to discover required flags; avoid __schema --json for agent use (too verbose).\n");
185
192
  });
186
193
  addGeneratedCommands(program, {
187
194
  servers: ctx.servers,
@@ -194,6 +201,76 @@ export async function main(argv, options = {}) {
194
201
  auth: options.auth,
195
202
  },
196
203
  });
204
+ program.configureHelp({
205
+ formatHelp: (cmd, _helper) => {
206
+ // Only customize the top-level help. Subcommands should keep
207
+ // their own default or explicitly configured help.
208
+ if (cmd !== program)
209
+ return defaultHelp.formatHelp(cmd, defaultHelp);
210
+ const lines = [];
211
+ const name = program.name();
212
+ const embedded = Boolean(options.embeddedSpecText);
213
+ lines.push(`Usage: ${name} [options] [command]`);
214
+ lines.push("");
215
+ lines.push(program.description());
216
+ lines.push("");
217
+ // OpenAPI-derived commands first (resources)
218
+ if (ctx.commands.resources.length > 0) {
219
+ lines.push("OpenAPI Commands:");
220
+ const resources = [...ctx.commands.resources]
221
+ .map((r) => r.resource)
222
+ .sort((a, b) => a.localeCompare(b));
223
+ for (const r of resources) {
224
+ lines.push(` ${r}`);
225
+ }
226
+ lines.push("");
227
+ }
228
+ // Non-OpenAPI commands (built-ins)
229
+ lines.push("Global Commands:");
230
+ const globalCommands = ["login", "logout", "whoami", "__schema", "help"];
231
+ const maxCmdLen = Math.max(...globalCommands.map((c) => c.length));
232
+ for (const cmdName of globalCommands) {
233
+ const c = program.commands.find((c) => c.name() === cmdName);
234
+ if (!c)
235
+ continue;
236
+ const term = cmdName === "login"
237
+ ? "login [token]"
238
+ : cmdName === "help"
239
+ ? "help [command]"
240
+ : cmdName;
241
+ const desc = c.description();
242
+ const pad = " ".repeat(Math.max(1, maxCmdLen - cmdName.length + 2));
243
+ lines.push(` ${term}${pad}${desc}`);
244
+ }
245
+ lines.push("");
246
+ // Global options last
247
+ lines.push("Global Options:");
248
+ const optionRows = [];
249
+ for (const opt of program.options) {
250
+ // In compiled binaries the spec is embedded; --spec is meaningless.
251
+ if (embedded && opt.long === "--spec")
252
+ continue;
253
+ optionRows.push({ flags: opt.flags, desc: opt.description });
254
+ }
255
+ optionRows.push({
256
+ flags: "-h, --help",
257
+ desc: "display help for command",
258
+ });
259
+ const maxOptLen = Math.max(...optionRows.map((o) => o.flags.length));
260
+ for (const row of optionRows) {
261
+ const pad = " ".repeat(Math.max(1, maxOptLen - row.flags.length + 2));
262
+ lines.push(` ${row.flags}${pad}${row.desc}`);
263
+ }
264
+ lines.push("");
265
+ lines.push("Agent workflow:");
266
+ lines.push(` 1) ${name} __schema`);
267
+ lines.push(` 2) ${name} <resource> --help`);
268
+ lines.push(` 3) ${name} <resource> <action> --help`);
269
+ lines.push(` 4) ${name} <resource> <action> --curl`);
270
+ lines.push("");
271
+ return lines.join("\n");
272
+ },
273
+ });
197
274
  if (argv.length <= 2) {
198
275
  program.outputHelp();
199
276
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "specli",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
4
4
  "description": "Run any OpenAPI spec as a CLI. Built for Agents.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -31,7 +31,7 @@
31
31
  ],
32
32
  "scripts": {
33
33
  "build": "tsc",
34
- "prepublishOnly": "tsc",
34
+ "prepublishOnly": "rm -rf dist && tsc",
35
35
  "lint": "biome ci",
36
36
  "lint:check": "biome check --write --unsafe",
37
37
  "lint:format": "biome format --write",
@@ -54,7 +54,7 @@
54
54
  "@tsconfig/node22": "^22.0.5",
55
55
  "@types/bun": "^1.3.6",
56
56
  "@types/node": "^22.19.7",
57
- "@typescript/native-preview": "^7.0.0-dev.20260122.3",
57
+ "@typescript/native-preview": "^7.0.0-dev.20260122.4",
58
58
  "typescript": "^5.9.3"
59
59
  }
60
60
  }