image-skill 0.1.34 → 0.1.36

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/CHANGELOG.md CHANGED
@@ -4,6 +4,27 @@ This changelog tracks the public `image-skill` CLI package and public skill
4
4
  mirror. The npm package metadata remains the authority for tarball integrity and
5
5
  provenance; this file is the human- and agent-readable release map.
6
6
 
7
+ ## 0.1.36 - 2026-06-04
8
+
9
+ - Fix (guide): `create --guide --json` now marks templated follow-up commands
10
+ explicitly with `data.next_command_copy_runnable`,
11
+ `data.next_command_missing_inputs`, and
12
+ `data.next_command_effect.requires_placeholder_substitution`. Auth signup,
13
+ prompt recovery, payment handoff, and input-asset templates remain visible to
14
+ agents, but placeholder values such as `AGENT_OR_OPERATOR_INBOX`,
15
+ `AGENT_NAME`, `RUNTIME_NAME`, `QUOTE_ID`, and `PAYMENT_ATTEMPT_ID` are no
16
+ longer presented as if the command can be copied blindly.
17
+
18
+ ## 0.1.35 - 2026-06-04
19
+
20
+ - Fix (CLI aliases): natural modality-first commands now route into the
21
+ guide-first public runtime. `image-skill image create`,
22
+ `image-skill video create`, `image-skill audio create`,
23
+ `image-skill 3d create`, and `image-skill image edit` normalize to the
24
+ existing `create` / `edit` flows instead of failing with
25
+ `PUBLIC_CLI_COMMAND_NOT_AVAILABLE`. Video, audio, and 3D aliases add the
26
+ matching intent hint unless the agent already supplied `--intent`.
27
+
7
28
  ## 0.1.34 - 2026-06-04
8
29
 
9
30
  - Fix (guide): `create --guide --model openai.gpt-image-2-edit` now returns an
@@ -7,7 +7,7 @@ import { Readable } from "node:stream";
7
7
  import { pipeline } from "node:stream/promises";
8
8
  import os from "node:os";
9
9
 
10
- const VERSION = "0.1.34";
10
+ const VERSION = "0.1.36";
11
11
  const PACKAGE_NAME = "image-skill";
12
12
  const DEFAULT_API_BASE_URL = "https://api.image-skill.com";
13
13
  const DEFAULT_DOCS_BASE_URL = "https://image-skill.com";
@@ -37,6 +37,14 @@ const HOSTED_SIGNUP_TOKEN_RETURNED_WARNING =
37
37
  const PUBLIC_NPX_COMMAND_PREFIX =
38
38
  "npm_config_update_notifier=false npx -y image-skill@latest";
39
39
  const CREDIT_UNIT_USD = 0.01;
40
+ const MODALITY_COMMAND_ALIASES = new Map([
41
+ ["image", { command: "create", intent: null }],
42
+ ["video", { command: "create", intent: "video" }],
43
+ ["audio", { command: "create", intent: "audio" }],
44
+ ["3d", { command: "create", intent: "image-to-3d" }],
45
+ ["image-to-3d", { command: "create", intent: "image-to-3d" }],
46
+ ["three-d", { command: "create", intent: "image-to-3d" }],
47
+ ]);
40
48
  const PAYMENT_CREDENTIAL_FLAGS = new Set([
41
49
  "payment-token",
42
50
  "payment-secret",
@@ -57,8 +65,72 @@ const PAYMENT_CREDENTIAL_FLAGS = new Set([
57
65
  "provider-key",
58
66
  "provider-receipt",
59
67
  ]);
60
-
61
- const argv = process.argv.slice(2);
68
+ const GUIDE_NEXT_COMMAND_PLACEHOLDERS = [
69
+ {
70
+ placeholder: "AGENT_OR_OPERATOR_INBOX",
71
+ flag: "--agent-contact",
72
+ value_description:
73
+ "Email-shaped durable contact inbox for the restricted agent identity; use an agent-owned inbox when available, otherwise an operator, team, or sponsor inbox.",
74
+ effect_description: "email-shaped durable contact inbox",
75
+ example: "agent-inbox@example.com",
76
+ },
77
+ {
78
+ placeholder: "AGENT_NAME",
79
+ flag: "--agent-name",
80
+ value_description:
81
+ "Stable display name for this restricted agent identity.",
82
+ effect_description: "stable agent identity name",
83
+ example: "codex-image-worker",
84
+ },
85
+ {
86
+ placeholder: "RUNTIME_NAME",
87
+ flag: "--runtime",
88
+ value_description:
89
+ "Stable name for the agent runtime or substrate using Image Skill.",
90
+ effect_description: "agent/runtime substrate name",
91
+ example: "codex-cli",
92
+ },
93
+ {
94
+ placeholder: "PROMPT",
95
+ flag: "--prompt",
96
+ value_description: "The real creative prompt to plan or create.",
97
+ effect_description: "real creative prompt",
98
+ example: "a compact field camera on a stainless workbench",
99
+ },
100
+ {
101
+ placeholder: "KEY",
102
+ flag: "--idempotency-key",
103
+ value_description:
104
+ "Unique idempotency key for this payment or create attempt.",
105
+ effect_description: "unique idempotency key",
106
+ example: "agent-generated-idempotency-key",
107
+ },
108
+ {
109
+ placeholder: "QUOTE_ID",
110
+ flag: "--quote-id",
111
+ value_description: "Quote id returned by the preceding credits quote call.",
112
+ effect_description: "quote id from credits quote",
113
+ example: null,
114
+ },
115
+ {
116
+ placeholder: "PAYMENT_ATTEMPT_ID",
117
+ flag: "--payment-attempt-id",
118
+ value_description:
119
+ "Payment attempt id returned by the preceding credits buy call.",
120
+ effect_description: "payment attempt id from credits buy",
121
+ example: null,
122
+ },
123
+ {
124
+ placeholder: "image_...",
125
+ flag: "--input",
126
+ value_description:
127
+ "Image Skill input asset id, usually from upload, assets, jobs, or a previous create.",
128
+ effect_description: "Image Skill input asset id",
129
+ example: null,
130
+ },
131
+ ];
132
+
133
+ const argv = normalizePublicArgv(process.argv.slice(2));
62
134
  const result = await main(argv);
63
135
  process.stdout.write(`${JSON.stringify(result.envelope, null, 2)}\n`);
64
136
  process.exitCode = result.exitCode;
@@ -71,7 +143,7 @@ async function main(rawArgv) {
71
143
  }
72
144
 
73
145
  if (command === "help") {
74
- return publicCliHelp(helpTarget(rest));
146
+ return publicCliHelp(helpTarget(normalizePublicArgv(rest)));
75
147
  }
76
148
 
77
149
  if (hasHelpFlag(rest)) {
@@ -160,10 +232,37 @@ function hasHelpFlag(argv) {
160
232
  return argv.includes("--help") || argv.includes("-h");
161
233
  }
162
234
 
235
+ function normalizePublicArgv(argv) {
236
+ const [maybeModality, maybeSubcommand, ...rest] = argv;
237
+ if (maybeModality === undefined || maybeSubcommand === undefined) {
238
+ return argv;
239
+ }
240
+
241
+ const alias = MODALITY_COMMAND_ALIASES.get(maybeModality);
242
+ if (alias === undefined) {
243
+ return argv;
244
+ }
245
+
246
+ if (maybeSubcommand === "create") {
247
+ if (
248
+ alias.intent !== null &&
249
+ !rest.some((arg) => arg === "--intent" || arg.startsWith("--intent="))
250
+ ) {
251
+ return [alias.command, "--intent", alias.intent, ...rest];
252
+ }
253
+ return [alias.command, ...rest];
254
+ }
255
+
256
+ if (maybeModality === "image" && maybeSubcommand === "edit") {
257
+ return ["edit", ...rest];
258
+ }
259
+
260
+ return argv;
261
+ }
262
+
163
263
  function helpTarget(argv) {
164
- return argv.filter(
165
- (arg) => arg !== "--help" && arg !== "-h" && arg !== "--json",
166
- );
264
+ return parseArgs(argv.filter((arg) => arg !== "--help" && arg !== "-h"))
265
+ .positionals;
167
266
  }
168
267
 
169
268
  function helpKey(path) {
@@ -177,30 +276,36 @@ function helpKey(path) {
177
276
  function commandHelpByKey(key) {
178
277
  return {
179
278
  "": {
180
- command: "image-skill help",
279
+ command: "help",
181
280
  usage:
182
- "image-skill <doctor|trust|signup|auth|whoami|usage|quota|credits|models|capabilities|create|upload|edit|assets|jobs|activity|feedback> --json",
281
+ "image-skill <doctor|trust|signup|whoami|usage|quota|credits|capabilities|models|create|upload|edit|assets|jobs|activity|feedback> --json",
183
282
  docs_url: "https://image-skill.com/cli.md",
184
283
  commands: [
185
284
  "doctor",
186
285
  "trust",
187
286
  "signup --agent --agent-contact --agent-name NAME --runtime RUNTIME",
188
- "auth status",
189
- "auth save",
190
- "auth logout",
191
287
  "whoami",
192
288
  "usage quota",
289
+ "quota",
193
290
  "credits methods",
194
- "credits packs list",
195
291
  "credits quote",
292
+ "credits packs list",
196
293
  "credits buy",
197
294
  "credits status",
295
+ "capabilities",
296
+ "capabilities list",
297
+ "capabilities show",
298
+ "models",
198
299
  "models list",
199
300
  "models show",
200
301
  "create --guide",
201
- "capabilities list",
202
- "capabilities show",
302
+ "image create --guide",
303
+ "video create --guide",
304
+ "audio create --guide",
305
+ "3d create --guide",
306
+ "create --dry-run",
203
307
  "create",
308
+ "image edit",
204
309
  "upload",
205
310
  "edit",
206
311
  "assets show",
@@ -289,7 +394,7 @@ function commandHelpByKey(key) {
289
394
  },
290
395
  "credits methods": {
291
396
  command: "image-skill credits methods help",
292
- usage: "image-skill credits methods --json",
397
+ usage: "image-skill credits methods",
293
398
  docs_url: "https://image-skill.com/cli.md#image-skill-credits",
294
399
  },
295
400
  "credits packs": {
@@ -332,6 +437,16 @@ function commandHelpByKey(key) {
332
437
  usage:
333
438
  "image-skill models list --available --operation image.generate --json",
334
439
  docs_url: "https://image-skill.com/cli.md#image-skill-models",
440
+ optional_flags: [
441
+ "--available",
442
+ "--executable",
443
+ "--catalog-only",
444
+ "--operation",
445
+ "--modality",
446
+ "--provider",
447
+ "--summary",
448
+ "--details",
449
+ ],
335
450
  },
336
451
  "models show": {
337
452
  command: "image-skill models show help",
@@ -365,6 +480,9 @@ function commandHelpByKey(key) {
365
480
  "--model",
366
481
  "--aspect-ratio",
367
482
  "--output-count",
483
+ "--element-frontal",
484
+ "--element-reference",
485
+ "--reference-image",
368
486
  "--model-parameters-json",
369
487
  "--idempotency-key",
370
488
  ],
@@ -385,6 +503,8 @@ function commandHelpByKey(key) {
385
503
  "--model",
386
504
  "--mask",
387
505
  "--element-reference",
506
+ "--element-frontal",
507
+ "--reference-image",
388
508
  "--model-parameters-json",
389
509
  "--idempotency-key",
390
510
  ],
@@ -897,12 +1017,6 @@ async function credits(argv) {
897
1017
  (flag) =>
898
1018
  !["json", "api-base-url", "token", "token-stdin"].includes(flag),
899
1019
  );
900
- if (!flagBool(args, "json")) {
901
- return invalid(
902
- "image-skill credits methods",
903
- "credits methods requires --json",
904
- );
905
- }
906
1020
  if (args.positionals.length > 0 || unknownFlags.length > 0) {
907
1021
  return invalid(
908
1022
  "image-skill credits methods",
@@ -993,7 +1107,7 @@ async function credits(argv) {
993
1107
  if (paymentMethod === null) {
994
1108
  return invalid(
995
1109
  "image-skill credits quote",
996
- "credits quote requires --payment-method from credits methods --json; use stripe_x402.exact.usdc for an agent-settleable browserless rail or stripe_checkout for a human Checkout handoff",
1110
+ "credits quote requires --payment-method from credits methods; use stripe_x402.exact.usdc for an agent-settleable browserless rail or stripe_checkout for a human Checkout handoff",
997
1111
  );
998
1112
  }
999
1113
  if (!PUBLIC_QUOTE_PAYMENT_METHODS.includes(paymentMethod)) {
@@ -1134,13 +1248,13 @@ async function models(argv) {
1134
1248
  subcommand === "list" || subcommand === "show" ? rest : argv,
1135
1249
  );
1136
1250
  if (subcommand === "show") {
1137
- const modelId = args.positionals[0];
1138
- if (modelId === undefined) {
1251
+ if (args.positionals.length !== 1) {
1139
1252
  return invalid(
1140
1253
  "image-skill models show",
1141
- "models show requires MODEL_ID",
1254
+ "models show requires exactly one MODEL_ID",
1142
1255
  );
1143
1256
  }
1257
+ const modelId = args.positionals[0];
1144
1258
  return apiRequest({
1145
1259
  command: "image-skill models show",
1146
1260
  method: "GET",
@@ -1169,13 +1283,21 @@ async function models(argv) {
1169
1283
  apiBaseUrl: apiBase(args),
1170
1284
  path: query.path,
1171
1285
  });
1172
- return flagBool(args, "summary") ? withModelSummary(result) : result;
1286
+ return flagBool(args, "details") ? result : withModelSummary(result);
1173
1287
  }
1174
1288
 
1175
1289
  function modelListQuery(args) {
1176
1290
  const available = flagBool(args, "available");
1177
1291
  const executable = flagBool(args, "executable");
1178
1292
  const catalogOnly = flagBool(args, "catalog-only");
1293
+ const summary = flagBool(args, "summary");
1294
+ const details = flagBool(args, "details");
1295
+ if (summary && details) {
1296
+ return {
1297
+ ok: false,
1298
+ message: "models list --summary cannot be combined with --details",
1299
+ };
1300
+ }
1179
1301
  if (catalogOnly && (available || executable)) {
1180
1302
  return {
1181
1303
  ok: false,
@@ -1193,6 +1315,9 @@ function modelListQuery(args) {
1193
1315
  if (catalogOnly) {
1194
1316
  params.set("catalog_only", "true");
1195
1317
  }
1318
+ if (details) {
1319
+ params.set("details", "true");
1320
+ }
1196
1321
  addQueryValue(params, "operation", flagString(args, "operation"));
1197
1322
  addQueryValue(params, "modality", flagString(args, "modality"));
1198
1323
  addQueryValue(params, "provider", flagString(args, "provider"));
@@ -1208,6 +1333,9 @@ function withModelSummary(result) {
1208
1333
  if (!isRecord(data) || !Array.isArray(data.models)) {
1209
1334
  return result;
1210
1335
  }
1336
+ if (data.summary?.result_shape === "compact_model_summary") {
1337
+ return result;
1338
+ }
1211
1339
  return {
1212
1340
  ...result,
1213
1341
  envelope: {
@@ -1217,7 +1345,7 @@ function withModelSummary(result) {
1217
1345
  summary: {
1218
1346
  ...(isRecord(data.summary) ? data.summary : {}),
1219
1347
  result_shape: "compact_model_summary",
1220
- full_list_command: "image-skill models list --json",
1348
+ full_list_command: "image-skill models list --details --json",
1221
1349
  },
1222
1350
  models: data.models.map(modelSummaryRow),
1223
1351
  },
@@ -1228,11 +1356,13 @@ function withModelSummary(result) {
1228
1356
  function modelSummaryRow(model) {
1229
1357
  return {
1230
1358
  id: model.id,
1359
+ default: model.default === true,
1231
1360
  display_name: model.display_name,
1232
1361
  provider_id: model.provider_id,
1233
1362
  mode: model.mode,
1234
1363
  status: model.status,
1235
1364
  availability_reason: model.availability_reason ?? null,
1365
+ modality: model.modality ?? "image",
1236
1366
  supports: Array.isArray(model.supports) ? [...model.supports] : [],
1237
1367
  operations: Array.isArray(model.operations) ? [...model.operations] : [],
1238
1368
  task_tags: modelSummaryTaskTags(model),
@@ -1505,6 +1635,9 @@ async function createGuide(args) {
1505
1635
  commandPrefix: guideCommandPrefix,
1506
1636
  authConfigWritable: authConfigWrite?.ok ?? true,
1507
1637
  });
1638
+ const nextCommandMissingInputs =
1639
+ createGuideNextCommandMissingInputs(nextCommand);
1640
+ const nextCommandCopyRunnable = nextCommandMissingInputs.length === 0;
1508
1641
  const escapeHatches = createGuideEscapeHatches({
1509
1642
  prompt: trimmedPrompt,
1510
1643
  selected,
@@ -1521,6 +1654,8 @@ async function createGuide(args) {
1521
1654
  const nextCommandEffect = createGuideNextCommandEffect(stage, {
1522
1655
  estimatedCredits,
1523
1656
  estimatedDebitUsdPerImage,
1657
+ nextCommandCopyRunnable,
1658
+ nextCommandMissingInputs,
1524
1659
  });
1525
1660
  const noSpendNextCommand =
1526
1661
  stage === "ready_to_create" ? escapeHatches.dry_run : null;
@@ -1540,6 +1675,7 @@ async function createGuide(args) {
1540
1675
  const guideWarning = createGuideWarning(stage, {
1541
1676
  nextCommandEffect,
1542
1677
  paymentSummary,
1678
+ nextCommandCopyRunnable,
1543
1679
  });
1544
1680
  const selfFundNextCommand = stage === "quota_required" ? nextCommand : null;
1545
1681
  const selfFundNextCommandLabel = createGuideSelfFundNextCommandLabel(
@@ -1570,6 +1706,7 @@ async function createGuide(args) {
1570
1706
  authenticated,
1571
1707
  tokenSource: publicTokenSource,
1572
1708
  savedConfigPath: configPath(),
1709
+ nextCommandCopyRunnable,
1573
1710
  });
1574
1711
  const selfFundHandoff = createGuideSelfFundHandoff(stage, {
1575
1712
  paymentSummary,
@@ -1663,6 +1800,8 @@ async function createGuide(args) {
1663
1800
  guide_warning: guideWarning,
1664
1801
  auth_ready: authReady,
1665
1802
  next_command: nextCommand,
1803
+ next_command_copy_runnable: nextCommandCopyRunnable,
1804
+ next_command_missing_inputs: nextCommandMissingInputs,
1666
1805
  next_command_effect: nextCommandEffect,
1667
1806
  no_spend_next_command: noSpendNextCommand,
1668
1807
  no_spend_next_command_label: noSpendNextCommandLabel,
@@ -2262,7 +2401,9 @@ function createGuideAuthReady(stage, input) {
2262
2401
  warning: ready
2263
2402
  ? "Current hosted auth is ready; data.next_command can reuse this auth context without exposing a raw token."
2264
2403
  : stage === "auth_required"
2265
- ? "Auth is not ready yet; run data.next_command to create a restricted agent identity, then rerun the guide."
2404
+ ? input.nextCommandCopyRunnable
2405
+ ? "Auth is not ready yet; run data.next_command to create a restricted agent identity, then rerun the guide."
2406
+ : "Auth is not ready yet; fill data.next_command_missing_inputs before running the data.next_command signup template, then rerun the guide."
2266
2407
  : null,
2267
2408
  };
2268
2409
  }
@@ -2393,6 +2534,9 @@ function createGuideWalletSettlementHandoff({
2393
2534
  }
2394
2535
 
2395
2536
  function createGuideNextCommandEffect(stage, input) {
2537
+ const placeholders = createGuideEffectPlaceholders(
2538
+ input.nextCommandMissingInputs,
2539
+ );
2396
2540
  const base = {
2397
2541
  label: "read_only_or_no_media_setup",
2398
2542
  no_spend: true,
@@ -2404,6 +2548,9 @@ function createGuideNextCommandEffect(stage, input) {
2404
2548
  media_write: false,
2405
2549
  estimated_credits: null,
2406
2550
  estimated_debit_usd_per_image: null,
2551
+ copy_runnable: input.nextCommandCopyRunnable,
2552
+ requires_placeholder_substitution: placeholders.length > 0,
2553
+ placeholders,
2407
2554
  warning: null,
2408
2555
  };
2409
2556
  if (stage === "auth_required") {
@@ -2437,6 +2584,9 @@ function createGuideNextCommandEffect(stage, input) {
2437
2584
  media_write: true,
2438
2585
  estimated_credits: input.estimatedCredits,
2439
2586
  estimated_debit_usd_per_image: input.estimatedDebitUsdPerImage,
2587
+ copy_runnable: input.nextCommandCopyRunnable,
2588
+ requires_placeholder_substitution: placeholders.length > 0,
2589
+ placeholders,
2440
2590
  warning:
2441
2591
  "data.next_command creates hosted media and can debit credits. For no-spend verification, run data.recommended_no_spend_command (same value as data.no_spend_next_command) instead.",
2442
2592
  };
@@ -2532,8 +2682,9 @@ function createGuideWarning(stage, input) {
2532
2682
  ...base,
2533
2683
  next_command_safety: "rerun_guide_no_spend",
2534
2684
  recommended_command_field: "next_command",
2535
- warning:
2536
- "data.next_command reruns the free guide with a real prompt; it does not call a provider, open payment, debit credits, or create media.",
2685
+ warning: input.nextCommandCopyRunnable
2686
+ ? "data.next_command reruns the free guide with a real prompt; it does not call a provider, open payment, debit credits, or create media."
2687
+ : "data.next_command is a no-spend guide template; fill data.next_command_missing_inputs before running it. It does not call a provider, open payment, debit credits, or create media.",
2537
2688
  };
2538
2689
  }
2539
2690
  if (stage === "no_executable_model" || stage === "service_unreachable") {
@@ -2550,8 +2701,9 @@ function createGuideWarning(stage, input) {
2550
2701
  ...base,
2551
2702
  next_command_safety: "hosted_signup_no_spend_setup",
2552
2703
  recommended_command_field: "next_command",
2553
- warning:
2554
- "data.next_command is no-spend hosted signup/setup; it creates a restricted agent identity but does not call a provider, open payment, debit credits, or create media.",
2704
+ warning: input.nextCommandCopyRunnable
2705
+ ? "data.next_command is no-spend hosted signup/setup; it creates a restricted agent identity but does not call a provider, open payment, debit credits, or create media."
2706
+ : "data.next_command is a no-spend hosted signup/setup template; fill data.next_command_missing_inputs before running it. It creates a restricted agent identity but does not call a provider, open payment, debit credits, or create media.",
2555
2707
  };
2556
2708
  }
2557
2709
  if (stage === "quota_required") {
@@ -2565,12 +2717,17 @@ function createGuideWarning(stage, input) {
2565
2717
  spend_required: true,
2566
2718
  recommended_command_field: "escape_hatches",
2567
2719
  payment_top_up_path: paymentTopUpPath,
2568
- warning:
2569
- paymentTopUpPath === "browserless_agent_self_fund"
2720
+ warning: input.nextCommandCopyRunnable
2721
+ ? paymentTopUpPath === "browserless_agent_self_fund"
2570
2722
  ? "data.next_command starts the browserless live-money top-up path; stay within the delegated cap, or use data.escape_hatches.payment_methods for read-only payment inspection."
2571
2723
  : paymentTopUpPath === "human_payment_handoff"
2572
2724
  ? "data.next_command starts a live-money payment handoff that needs human or browser completion; stay within the delegated cap, or use data.escape_hatches.payment_methods for read-only inspection."
2573
- : "data.next_command starts payment or quota recovery; inspect data.checks.payments before attempting live money, or use data.escape_hatches.payment_methods for read-only inspection.",
2725
+ : "data.next_command starts payment or quota recovery; inspect data.checks.payments before attempting live money, or use data.escape_hatches.payment_methods for read-only inspection."
2726
+ : paymentTopUpPath === "browserless_agent_self_fund"
2727
+ ? "data.next_command is a browserless live-money top-up template; fill data.next_command_missing_inputs before running it, stay within the delegated cap, or use data.escape_hatches.payment_methods for read-only payment inspection."
2728
+ : paymentTopUpPath === "human_payment_handoff"
2729
+ ? "data.next_command is a live-money payment handoff template; fill data.next_command_missing_inputs before running it, stay within the delegated cap, or use data.escape_hatches.payment_methods for read-only inspection."
2730
+ : "data.next_command is a live-money payment template; fill data.next_command_missing_inputs before running it, stay within the delegated cap, or use data.escape_hatches.payment_methods for read-only inspection.",
2574
2731
  };
2575
2732
  }
2576
2733
  return {
@@ -2584,6 +2741,40 @@ function createGuideWarning(stage, input) {
2584
2741
  };
2585
2742
  }
2586
2743
 
2744
+ function createGuideNextCommandMissingInputs(command) {
2745
+ return GUIDE_NEXT_COMMAND_PLACEHOLDERS.filter((placeholder) =>
2746
+ commandContainsTemplateToken(command, placeholder.placeholder),
2747
+ ).map((placeholder) => ({
2748
+ flag: placeholder.flag,
2749
+ placeholder: placeholder.placeholder,
2750
+ value_description: placeholder.value_description,
2751
+ example: placeholder.example,
2752
+ }));
2753
+ }
2754
+
2755
+ function createGuideEffectPlaceholders(missingInputs) {
2756
+ return missingInputs.map((input) => {
2757
+ const placeholder = GUIDE_NEXT_COMMAND_PLACEHOLDERS.find(
2758
+ (candidate) => candidate.placeholder === input.placeholder,
2759
+ );
2760
+ return {
2761
+ token: input.placeholder,
2762
+ description: placeholder?.effect_description ?? input.value_description,
2763
+ required: true,
2764
+ };
2765
+ });
2766
+ }
2767
+
2768
+ function commandContainsTemplateToken(command, token) {
2769
+ return new RegExp(
2770
+ `(^|[^A-Za-z0-9_])${escapeRegExp(token)}(?=$|[^A-Za-z0-9_])`,
2771
+ ).test(command);
2772
+ }
2773
+
2774
+ function escapeRegExp(value) {
2775
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2776
+ }
2777
+
2587
2778
  function createGuideNextCommand(stage, input) {
2588
2779
  if (stage === "prompt_required") {
2589
2780
  return renderGuideCommand("PROMPT", input.apiBaseUrl, input.commandPrefix, {
package/cli.md CHANGED
@@ -69,6 +69,11 @@ copyable commands, proof URL placeholders, and redaction guarantees.
69
69
  Use `trust` when deciding whether Image Skill is current and honest enough to
70
70
  select. It is not a required setup step before the first image; the canonical
71
71
  fresh-agent creative entrypoint remains `image-skill create --guide`.
72
+ Agents may also use modality-first aliases when that is the natural wording:
73
+ `image-skill image create --guide`, `image-skill video create --guide`,
74
+ `image-skill audio create --guide`, and `image-skill 3d create --guide` all
75
+ route into the same `create --guide` flow, with video/audio/3D intent hints
76
+ added only when the agent did not already provide `--intent`.
72
77
 
73
78
  If package metadata, hosted docs, API health, or model availability cannot be
74
79
  verified, the command still returns a packet with explicit `unreachable`,
@@ -129,7 +134,8 @@ should omit it.
129
134
  Use the no-spend guide first. It is the only required first command for a fresh
130
135
  agent. It checks health, executable model availability, auth/quota when a token
131
136
  already exists, and payment rails, then returns one primary
132
- `data.next_command` plus machine-readable `data.next_command_effect`,
137
+ `data.next_command` plus machine-readable `data.next_command_copy_runnable`,
138
+ `data.next_command_missing_inputs`, `data.next_command_effect`,
133
139
  `data.guide_warning`, `data.auth_ready`, and `data.no_spend_evaluation`. Guide
134
140
  mode does not create a signup, provider job, dry-run job, payment object,
135
141
  credit debit, or asset.
@@ -138,22 +144,28 @@ credit debit, or asset.
138
144
  image-skill create --guide --prompt "a compact field camera on a stainless workbench"
139
145
  ```
140
146
 
141
- Read `data.stage` and `data.guide_warning`, run `data.next_command` when
142
- `data.guide_warning.next_command_safety` is safe for the current spend policy,
143
- and rerun the guide only after auth or payment state changes. Do not run
147
+ Read `data.stage` and `data.guide_warning`, run `data.next_command` only when
148
+ `data.next_command_copy_runnable` is `true` and
149
+ `data.guide_warning.next_command_safety` is safe for the current spend policy.
150
+ When `data.next_command_copy_runnable` is `false`, fill
151
+ `data.next_command_missing_inputs` first. Rerun the guide only after auth or
152
+ payment state changes. Do not run
144
153
  `doctor`, `models list`, `signup`, `whoami`, `usage quota`, `create --dry-run`,
145
154
  or payment commands as a setup checklist before the guide asks for them.
146
155
 
147
- - `prompt_required`: rerun `data.next_command` with the real prompt.
148
- - `auth_required`: run `data.next_command`, then rerun guide once. Hosted
149
- signup saves auth to config by default. If the runtime intentionally used
156
+ - `prompt_required`: fill `data.next_command_missing_inputs` with the real
157
+ prompt, then rerun `data.next_command`.
158
+ - `auth_required`: fill `data.next_command_missing_inputs` when present, run
159
+ `data.next_command`, then rerun guide once. Hosted signup saves auth to
160
+ config by default. If the runtime intentionally used
150
161
  `--no-save --show-token`, store the returned token and use
151
162
  `data.auth_handoff.rerun_guide.with_env` or
152
163
  `data.auth_handoff.rerun_guide.with_stdin`. In this stage,
153
164
  `data.auth_ready.ready` is `false`, and
154
165
  `data.guide_warning.next_command_safety` is
155
166
  `hosted_signup_no_spend_setup`.
156
- - `quota_required`: run `data.self_fund_next_command` to start the top-up.
167
+ - `quota_required`: fill `data.next_command_missing_inputs` when present, then
168
+ run `data.self_fund_next_command` to start the top-up.
157
169
  It aliases `data.next_command` and is the first payment command, usually an
158
170
  x402 or Stripe quote. If the guide authenticated from env or stdin, prefer
159
171
  `data.self_fund_handoff.auth.next_command.with_env` or
@@ -762,7 +774,7 @@ capability-preserving schema for one model.
762
774
  ```bash
763
775
  image-skill models --json
764
776
  image-skill models list --json
765
- image-skill models list --summary --json
777
+ image-skill models list --details --json
766
778
  image-skill models list --available --operation image.generate --json
767
779
  image-skill models list --available --operation image.edit --json
768
780
  image-skill models list --available --modality video --operation video.generate --json
@@ -793,20 +805,23 @@ inspect the recommended create surface without knowing a provider-specific
793
805
  model id. The list response also returns `summary` with total, returned,
794
806
  available, executable, catalog-only, provider split,
795
807
  `execution_availability`, first actionable model ids, recommended filter
796
- commands, and catalog-inclusion flags. Default list output excludes
797
- catalog-only rows so fresh agents see executable candidates first. Use
798
- `--summary` when you need a compact, sortable model menu: each row keeps the
799
- model id, flat `estimated_usd_per_image`, `credits_required`, lightweight
800
- `task_tags`, status, provider, max output count/resolution, storage, and
801
- `show_command`, while omitting full parameter schemas. Use `--available` for
802
- currently usable executable rows, `--modality image|video|audio|3d` for media
803
- type, `--operation image.generate`, `--operation image.edit`,
804
- `--operation video.generate`, `--operation audio.generate`, or
805
- `--operation 3d.generate` for the task, `--provider fal|xai|openai` to narrow by
806
- provider, and `--catalog-only` when you intentionally want source-backed rows
807
- that are inspectable but not runnable yet. Provider-level availability is not
808
- the same thing as model executability; for runnable choices require both
809
- `status:"available"` and
808
+ commands, and catalog-inclusion flags. Default list output is a compact,
809
+ sortable model menu and excludes catalog-only rows so fresh agents see
810
+ executable candidates first. Each row keeps the model id, flat
811
+ `estimated_usd_per_image`, `credits_required`, lightweight `task_tags`, status,
812
+ provider, max output count/resolution, storage, and `show_command`, while
813
+ omitting full parameter schemas. Use `models show MODEL_ID --json` for one
814
+ model's full capability schema, or `models list --details --json` only when you
815
+ intentionally need the full list with capability schemas for compatibility or
816
+ offline analysis. `--summary` is still accepted as a compatibility alias for the
817
+ default compact list. Use `--available` for currently usable executable rows,
818
+ `--modality image|video|audio|3d` for media type, `--operation
819
+ image.generate`, `--operation image.edit`, `--operation video.generate`,
820
+ `--operation audio.generate`, or `--operation 3d.generate` for the task,
821
+ `--provider fal|xai|openai` to narrow by provider, and `--catalog-only` when you
822
+ intentionally want source-backed rows that are inspectable but not runnable yet.
823
+ Provider-level availability is not the same thing as model executability; for
824
+ runnable choices require both `status:"available"` and
810
825
  `execution.model_execution_status:"executable"`. If a reachable provider has no
811
826
  runnable model for the requested operation, `summary.execution_availability`
812
827
  says so directly and includes the fastest `--available --operation ...`
@@ -894,13 +909,15 @@ image-skill create --guide --prompt "A compact field camera on a stainless workb
894
909
  ```
895
910
 
896
911
  `create --guide` returns `schema: image-skill.create-guide.v1`,
897
- `stage`, `next_command`, `guide_warning`, `auth_ready`, `no_spend_evaluation`,
898
- `recommended_no_spend_command`,
912
+ `stage`, `next_command`, `next_command_copy_runnable`,
913
+ `next_command_missing_inputs`, `guide_warning`, `auth_ready`,
914
+ `no_spend_evaluation`, `recommended_no_spend_command`,
899
915
  `self_fund_next_command`, `self_fund_handoff`, `escape_hatches`, selected
900
916
  executable model and cost, auth/quota/payment blockers, and mutation flags. All
901
917
  mutation flags must be false in guide mode: no provider call, hosted create,
902
918
  signup, payment object, credit debit, or media write.
903
- For next-command safety, read `guide_warning.next_command_safety` before
919
+ For next-command safety, read `next_command_copy_runnable`,
920
+ `next_command_missing_inputs`, and `guide_warning.next_command_safety` before
904
921
  acting: `hosted_signup_no_spend_setup` is no-spend auth setup,
905
922
  `live_money_payment_action` is top-up/payment work, and
906
923
  `live_media_create_credit_debit` is a live create that can call a provider,