image-skill 0.1.21 → 0.1.23

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,31 @@ 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.23 - 2026-06-02
8
+
9
+ - Fix (guide payments): `create --guide` now distinguishes browserless,
10
+ agent-payable, and human-handoff payment rails instead of collapsing the
11
+ payment summary into a single browser-required flag. When the hosted catalog
12
+ exposes `stripe_x402.exact.usdc` as available and browserless, the guide marks
13
+ it as the preferred method and puts the x402 quote/buy/status commands before
14
+ the Stripe Checkout fallback.
15
+ - Fix (quota recovery): when an authenticated agent has no remaining credits,
16
+ guide mode now points `data.next_command` at the preferred credit quote command
17
+ instead of the generic `credits methods` inspection command.
18
+
19
+ ## 0.1.22 - 2026-06-02
20
+
21
+ - Fix (guide): `create --guide` now reports `cost.estimated_usd_per_image` as
22
+ the actual Image Skill credit debit dollars, matching `estimated_credits`.
23
+ The guide still exposes the upstream provider estimate separately as
24
+ `estimated_provider_usd_per_image`, so agents no longer see a confusing
25
+ "17 credits but $0.10" first-run cost mismatch.
26
+ - Fix (payment discovery): `credits methods --json` and
27
+ `credits packs list --json` now tolerate `--token` / `--token-stdin`.
28
+ Fresh agents that safely carry their signup token through stdin can inspect
29
+ payment rails without hitting an unsupported-flag dead end; the token is
30
+ drained and not forwarded to the no-auth discovery endpoint.
31
+
7
32
  ## 0.1.21 - 2026-06-02
8
33
 
9
34
  - Release: ships the guide auth handoff already present on main to
@@ -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.21";
10
+ const VERSION = "0.1.23";
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";
@@ -32,6 +32,7 @@ const SIGNUP_SUGGESTED_COMMAND =
32
32
  const SIGNUP_CONTACT_GUIDANCE =
33
33
  "Preview signup currently requires an email-shaped durable contact inbox, not an individual human email. Use an agent-owned inbox when available; otherwise use an operator, team, or sponsor inbox that can receive future claim, billing, or abuse notices. Do not block waiting for a person, invent a person, or use a throwaway inbox. --human-email remains a compatibility alias.";
34
34
  const PUBLIC_NPX_COMMAND_PREFIX = "npx -y image-skill@latest";
35
+ const CREDIT_UNIT_USD = 0.01;
35
36
  const PAYMENT_CREDENTIAL_FLAGS = new Set([
36
37
  "payment-token",
37
38
  "payment-secret",
@@ -547,7 +548,8 @@ async function credits(argv) {
547
548
  if (subcommand === "methods") {
548
549
  const args = parseArgs(rest);
549
550
  const unknownFlags = [...args.flags.keys()].filter(
550
- (flag) => !["json", "api-base-url"].includes(flag),
551
+ (flag) =>
552
+ !["json", "api-base-url", "token", "token-stdin"].includes(flag),
551
553
  );
552
554
  if (!flagBool(args, "json")) {
553
555
  return invalid(
@@ -563,6 +565,13 @@ async function credits(argv) {
563
565
  : "credits methods does not accept positional arguments",
564
566
  );
565
567
  }
568
+ const tokenHandoff = await acceptNoAuthTokenHandoff(
569
+ args,
570
+ "image-skill credits methods",
571
+ );
572
+ if (tokenHandoff !== null) {
573
+ return tokenHandoff;
574
+ }
566
575
  return apiRequest({
567
576
  command: "image-skill credits methods",
568
577
  method: "GET",
@@ -579,6 +588,25 @@ async function credits(argv) {
579
588
  );
580
589
  }
581
590
  const args = parseArgs(packsRest);
591
+ const unknownFlags = [...args.flags.keys()].filter(
592
+ (flag) =>
593
+ !["json", "api-base-url", "token", "token-stdin"].includes(flag),
594
+ );
595
+ if (args.positionals.length > 0 || unknownFlags.length > 0) {
596
+ return invalid(
597
+ "image-skill credits packs list",
598
+ unknownFlags.length > 0
599
+ ? `unsupported flags for credits packs list: ${unknownFlags.map((flag) => `--${flag}`).join(", ")}`
600
+ : "credits packs list does not accept positional arguments",
601
+ );
602
+ }
603
+ const tokenHandoff = await acceptNoAuthTokenHandoff(
604
+ args,
605
+ "image-skill credits packs list",
606
+ );
607
+ if (tokenHandoff !== null) {
608
+ return tokenHandoff;
609
+ }
582
610
  return apiRequest({
583
611
  command: "image-skill credits packs list",
584
612
  method: "GET",
@@ -719,6 +747,33 @@ async function credits(argv) {
719
747
  );
720
748
  }
721
749
 
750
+ async function acceptNoAuthTokenHandoff(args, command) {
751
+ const tokenValues = args.flags.get("token");
752
+ if (tokenValues !== undefined && typeof tokenValues.at(-1) !== "string") {
753
+ return invalid(command, "token requires a value");
754
+ }
755
+ if (flagBool(args, "token-stdin") && tokenValues !== undefined) {
756
+ return invalid(command, "use either --token or --token-stdin, not both");
757
+ }
758
+ if (!flagBool(args, "token-stdin")) {
759
+ return null;
760
+ }
761
+ if (process.stdin.isTTY) {
762
+ return invalid(command, "--token-stdin requires a token piped on stdin");
763
+ }
764
+ const token = (await readStdin()).trim();
765
+ if (token.length === 0) {
766
+ return failure(
767
+ command,
768
+ 3,
769
+ "AUTH_REQUIRED",
770
+ "--token-stdin received empty stdin",
771
+ false,
772
+ );
773
+ }
774
+ return null;
775
+ }
776
+
722
777
  async function models(argv) {
723
778
  const [subcommand, ...rest] = argv;
724
779
  const args = parseArgs(
@@ -863,6 +918,10 @@ async function createGuide(args) {
863
918
  const requestedModelId = flagString(args, "model");
864
919
  const requestedProviderId = flagString(args, "provider");
865
920
  const requestedIntent = flagString(args, "intent") ?? "explore";
921
+ const maxEstimatedUsdPerImage = flagNumber(
922
+ args,
923
+ "max-estimated-usd-per-image",
924
+ );
866
925
  const health = await apiRequest({
867
926
  command: "image-skill create --guide",
868
927
  method: "GET",
@@ -888,16 +947,22 @@ async function createGuide(args) {
888
947
 
889
948
  const selected =
890
949
  models.envelope.ok && models.envelope.data?.models
891
- ? selectCreateGuideModel(models.envelope.data.models, requestedModelId)
950
+ ? selectCreateGuideModel(models.envelope.data.models, requestedModelId, {
951
+ maxEstimatedUsdPerImage,
952
+ })
892
953
  : null;
893
954
  const pricing = selected?.economics?.credit_pricing ?? null;
894
955
  const estimatedCredits = pricing?.credits_required ?? null;
895
- const estimatedUsdPerImage =
956
+ const estimatedProviderUsdPerImage =
896
957
  selected?.economics?.estimated_usd_per_image ??
897
- (pricing === null ? null : pricing.estimated_revenue_usd);
958
+ pricing?.estimated_provider_cost_usd ??
959
+ pricing?.fallback_provider_cost_usd ??
960
+ null;
961
+ const estimatedDebitUsdPerImage =
962
+ pricing?.estimated_revenue_usd ?? estimatedProviderUsdPerImage;
898
963
  const budgetGuard =
899
- flagNumber(args, "max-estimated-usd-per-image") ??
900
- estimatedUsdPerImage ??
964
+ maxEstimatedUsdPerImage ??
965
+ estimatedDebitUsdPerImage ??
901
966
  (estimatedCredits === null ? 0.07 : estimatedCredits / 100);
902
967
  const quota =
903
968
  token.token === null
@@ -1003,7 +1068,10 @@ async function createGuide(args) {
1003
1068
  },
1004
1069
  cost: {
1005
1070
  estimated_credits: estimatedCredits,
1006
- estimated_usd_per_image: estimatedUsdPerImage,
1071
+ estimated_usd_per_image: estimatedDebitUsdPerImage,
1072
+ estimated_debit_usd_per_image: estimatedDebitUsdPerImage,
1073
+ estimated_provider_usd_per_image: estimatedProviderUsdPerImage,
1074
+ credit_unit_usd: pricing?.credit_unit_usd ?? CREDIT_UNIT_USD,
1007
1075
  pricing_confidence: pricing?.pricing_confidence ?? null,
1008
1076
  },
1009
1077
  blocker,
@@ -1061,7 +1129,11 @@ async function createGuide(args) {
1061
1129
  });
1062
1130
  }
1063
1131
 
1064
- function selectCreateGuideModel(models, requestedModelId) {
1132
+ function selectCreateGuideModel(
1133
+ models,
1134
+ requestedModelId,
1135
+ { maxEstimatedUsdPerImage = null } = {},
1136
+ ) {
1065
1137
  const isExecutableCreate = (model) =>
1066
1138
  model?.status === "available" &&
1067
1139
  model?.execution?.model_execution_status === "executable" &&
@@ -1073,35 +1145,97 @@ function selectCreateGuideModel(models, requestedModelId) {
1073
1145
  ? requested
1074
1146
  : null;
1075
1147
  }
1076
- return models.find(isExecutableCreate) ?? null;
1148
+ const candidates = models.filter(isExecutableCreate);
1149
+ if (maxEstimatedUsdPerImage === null) {
1150
+ return candidates[0] ?? null;
1151
+ }
1152
+ const capped = candidates.filter((model) => {
1153
+ const estimatedUsd = guideBudgetUsdForModel(model);
1154
+ return estimatedUsd === null || estimatedUsd <= maxEstimatedUsdPerImage;
1155
+ });
1156
+ return (capped.length === 0 ? candidates : capped)[0] ?? null;
1157
+ }
1158
+
1159
+ function guideBudgetUsdForModel(model) {
1160
+ const pricing = model?.economics?.credit_pricing ?? null;
1161
+ return (
1162
+ pricing?.estimated_revenue_usd ??
1163
+ model?.economics?.estimated_usd_per_image ??
1164
+ pricing?.estimated_provider_cost_usd ??
1165
+ pricing?.fallback_provider_cost_usd ??
1166
+ null
1167
+ );
1077
1168
  }
1078
1169
 
1079
1170
  function createGuidePaymentSummary(data) {
1080
1171
  const methods = Array.isArray(data?.methods)
1081
1172
  ? data.methods.filter((method) => method.live_money)
1082
1173
  : [];
1174
+ const availableMethods = methods.filter((method) => method.available);
1175
+ const browserlessMethods = availableMethods.filter(
1176
+ (method) => method.requires_browser === false,
1177
+ );
1178
+ const agentPayableMethods = browserlessMethods.filter((method) =>
1179
+ (method.buyer_modes ?? []).some(
1180
+ (mode) => mode === "agent_only" || mode === "hybrid",
1181
+ ),
1182
+ );
1183
+ const humanHandoffMethods = availableMethods.filter(
1184
+ (method) =>
1185
+ method.requires_browser === true ||
1186
+ (method.buyer_modes ?? []).some((mode) => mode === "human_only"),
1187
+ );
1188
+ const preferredMethod =
1189
+ agentPayableMethods[0] ?? browserlessMethods[0] ?? availableMethods[0];
1083
1190
  return {
1084
1191
  checked: data !== null && typeof data === "object",
1085
- live_money_methods: methods
1086
- .filter((method) => method.available)
1087
- .map((method) => method.method_id),
1088
- requires_browser: methods.some((method) => method.requires_browser),
1192
+ live_money_methods: availableMethods.map((method) => method.method_id),
1193
+ requires_browser:
1194
+ availableMethods.length > 0 &&
1195
+ availableMethods.every((method) => method.requires_browser === true),
1196
+ browserless_methods: browserlessMethods.map((method) => method.method_id),
1197
+ agent_payable_methods: agentPayableMethods.map(
1198
+ (method) => method.method_id,
1199
+ ),
1200
+ human_handoff_methods: humanHandoffMethods.map(
1201
+ (method) => method.method_id,
1202
+ ),
1203
+ preferred_method: preferredMethod?.method_id ?? null,
1089
1204
  buyer_modes: [
1090
1205
  ...new Set(methods.flatMap((method) => method.buyer_modes ?? [])),
1091
1206
  ],
1092
- suggested_commands: [
1093
- "image-skill credits methods --json",
1094
- "image-skill credits packs list --json",
1095
- methods[0]?.recovery?.quote_command ??
1096
- "image-skill credits quote --pack starter-500 --payment-method stripe_checkout --idempotency-key KEY --json",
1097
- methods[0]?.recovery?.purchase_command ??
1098
- "image-skill credits buy --provider stripe --quote-id QUOTE_ID --idempotency-key KEY --json",
1099
- methods[0]?.recovery?.status_command ??
1100
- "image-skill credits status --payment-attempt-id PAYMENT_ATTEMPT_ID --json",
1101
- ],
1207
+ suggested_commands: createGuidePaymentCommands(
1208
+ preferredMethod,
1209
+ availableMethods.filter((method) => method !== preferredMethod),
1210
+ ),
1102
1211
  };
1103
1212
  }
1104
1213
 
1214
+ function createGuidePaymentCommands(preferredMethod, fallbackMethods) {
1215
+ const commands = [
1216
+ "image-skill credits methods --json",
1217
+ "image-skill credits packs list --json",
1218
+ preferredMethod?.recovery?.quote_command ??
1219
+ "image-skill credits quote --pack starter-500 --payment-method stripe_x402.exact.usdc --idempotency-key KEY --json",
1220
+ preferredMethod?.recovery?.purchase_command ??
1221
+ "image-skill credits buy --provider stripe_x402 --quote-id QUOTE_ID --idempotency-key KEY --json",
1222
+ preferredMethod?.recovery?.status_command ??
1223
+ "image-skill credits status --payment-attempt-id PAYMENT_ATTEMPT_ID --json",
1224
+ ];
1225
+ for (const method of fallbackMethods) {
1226
+ for (const command of [
1227
+ method.recovery?.quote_command,
1228
+ method.recovery?.purchase_command,
1229
+ method.recovery?.status_command,
1230
+ ]) {
1231
+ if (typeof command === "string" && !commands.includes(command)) {
1232
+ commands.push(command);
1233
+ }
1234
+ }
1235
+ }
1236
+ return commands;
1237
+ }
1238
+
1105
1239
  function createGuideStage(input) {
1106
1240
  if (input.prompt.length === 0) {
1107
1241
  return "prompt_required";
@@ -1238,7 +1372,9 @@ function createGuideNextCommand(stage, input) {
1238
1372
  if (stage === "quota_required") {
1239
1373
  return renderGuidePrefixedCommand(
1240
1374
  input.commandPrefix,
1241
- stripImageSkillCommandPrefix(input.paymentSummary.suggested_commands[0]),
1375
+ stripImageSkillCommandPrefix(
1376
+ firstPaymentActionCommand(input.paymentSummary.suggested_commands),
1377
+ ),
1242
1378
  );
1243
1379
  }
1244
1380
  return renderCreateCommand({
@@ -1271,6 +1407,16 @@ function renderTokenStdinCommand(command) {
1271
1407
  return `printf '%s\\n' "$IMAGE_SKILL_TOKEN" | ${command} --token-stdin`;
1272
1408
  }
1273
1409
 
1410
+ function firstPaymentActionCommand(commands) {
1411
+ return (
1412
+ commands.find((command) => /\bcredits\s+quote\b/.test(command)) ??
1413
+ commands.find((command) => /\bcredits\s+buy\b/.test(command)) ??
1414
+ commands.find((command) => /\bcredits\s+methods\b/.test(command)) ??
1415
+ commands[0] ??
1416
+ "image-skill credits methods --json"
1417
+ );
1418
+ }
1419
+
1274
1420
  function renderCreateCommand(input) {
1275
1421
  return [
1276
1422
  input.commandPrefix ?? "image-skill",
package/cli.md CHANGED
@@ -266,15 +266,28 @@ Minimum success data shape:
266
266
  "requires_browser": true,
267
267
  "default_pack_id": "starter-500",
268
268
  "purchase_endpoint": "/v1/credit-purchases/stripe-checkout-sessions"
269
+ },
270
+ {
271
+ "method_id": "stripe_x402.exact.usdc",
272
+ "status": "available",
273
+ "available": true,
274
+ "quoteable": true,
275
+ "purchasable": true,
276
+ "live_money": true,
277
+ "buyer_modes": ["agent_only", "hybrid"],
278
+ "requires_browser": false,
279
+ "default_pack_id": "starter-500",
280
+ "purchase_endpoint": "/v1/credit-purchases/stripe-x402-deposits"
269
281
  }
270
282
  ]
271
283
  }
272
284
  ```
273
285
 
274
- Public payment discovery is intentionally action-only. Rails that are merely
275
- planned, watch-only, fake, or private harness-only are not returned here. Use a
276
- method only when it is returned with `available:true`, `quoteable:true`, and
277
- `purchasable:true`.
286
+ Public payment discovery is intentionally action-first. Limited-rollout rails
287
+ may be returned with `available:false`, `quoteable:false`, `purchasable:false`,
288
+ and a non-null `unavailable_reason` so headless agents can understand the path
289
+ without trying it. Use a method only when it is returned with `available:true`,
290
+ `quoteable:true`, and `purchasable:true`.
278
291
 
279
292
  Hosted API equivalent:
280
293
 
@@ -284,10 +297,13 @@ curl -sS https://api.image-skill.com/v1/payment-methods
284
297
 
285
298
  ### `image-skill credits packs list`
286
299
 
287
- Lists the recommended Image Skill credit packs for Stripe Checkout. Packs are
288
- the default live-money buying UX because agents get obvious starter choices and
289
- Stripe Checkout avoids tiny card-fee traps. Exact custom quotes are still
290
- supported when an agent already knows the required credit budget.
300
+ Lists the recommended Image Skill credit packs. Packs are the default
301
+ live-money buying UX because agents get obvious starter choices and avoid tiny
302
+ fee traps. Use the payment method catalog to choose the rail: browserless
303
+ `stripe_x402.exact.usdc` when it is available for agent self-funding, or
304
+ `stripe_checkout` when a human sponsor needs a Checkout handoff. Exact custom
305
+ quotes are still supported when an agent already knows the required credit
306
+ budget.
291
307
 
292
308
  ```bash
293
309
  image-skill credits packs list --json
@@ -326,8 +342,10 @@ curl -sS https://api.image-skill.com/v1/credit-packs
326
342
 
327
343
  ### `image-skill credits quote`
328
344
 
329
- Requests a bounded credit quote from the hosted service. Public top-ups use
330
- Stripe Checkout with `--payment-method stripe_checkout`. A quote never grants
345
+ Requests a bounded credit quote from the hosted service. Public top-ups use the
346
+ payment method returned by `credits methods --json`: `stripe_x402.exact.usdc`
347
+ for browserless agent self-funding when it is available, or
348
+ `stripe_checkout` for the human Checkout fallback. A quote never grants
331
349
  credits.
332
350
  One Image Skill credit is a stable user-facing value unit worth `$0.01`.
333
351
  Creative operations can consume more than one credit based on the selected
@@ -363,6 +381,17 @@ image-skill credits quote \
363
381
  --json
364
382
  ```
365
383
 
384
+ For the browserless agent x402 rail, quote the exact method id returned by
385
+ `credits methods --json`:
386
+
387
+ ```bash
388
+ image-skill credits quote \
389
+ --pack starter-500 \
390
+ --payment-method stripe_x402.exact.usdc \
391
+ --idempotency-key agent-x402-quote-run-001 \
392
+ --json
393
+ ```
394
+
366
395
  For exact custom Stripe Checkout terms, request the provider and bounded credit
367
396
  amount explicitly:
368
397
 
@@ -392,22 +421,77 @@ Minimum success data:
392
421
  }
393
422
  ```
394
423
 
424
+ For x402 quotes, `accepted_payment_method` is
425
+ `"stripe_x402.exact.usdc"` and the response includes redacted
426
+ `quote.x402` metadata for the agent-payable deposit flow.
427
+
395
428
  Hosted API equivalent:
396
429
 
397
430
  ```bash
398
431
  curl -sS https://api.image-skill.com/v1/credit-quotes \
399
432
  -H "authorization: Bearer $IMAGE_SKILL_TOKEN" \
400
433
  -H "content-type: application/json" \
401
- -d '{"pack_id":"starter-500","payment_method":"stripe_checkout","idempotency_key":"stripe-pack-quote-run-001"}'
434
+ -d '{"pack_id":"starter-500","payment_method":"stripe_x402.exact.usdc","idempotency_key":"agent-x402-quote-run-001"}'
402
435
  ```
403
436
 
404
437
  ### `image-skill credits buy`
405
438
 
406
- Creates a payment action for a previously returned quote. Stripe Checkout is the
407
- first live-money provider. This creates a hosted Stripe Checkout Session and
408
- returns an `action_required` response with `checkout_handoff_url`; credits are
409
- granted only after verified Stripe webhook fulfillment succeeds. Session
410
- creation itself must not mutate credit balances.
439
+ Creates a payment action for a previously returned quote. Choose the provider
440
+ that matches the quote's `accepted_payment_method`.
441
+
442
+ For a `stripe_x402.exact.usdc` quote, `--provider stripe_x402` creates a
443
+ browserless agent-payable USDC deposit challenge. The response is live money
444
+ when `live_money:true`; credits are granted only after verified settlement and
445
+ webhook fulfillment succeeds. Deposit challenge creation itself must not mutate
446
+ credit balances. Stay within the delegated cap and never pass wallet private
447
+ keys, seed phrases, x402 payment headers, deposit client secrets, or provider
448
+ receipts to Image Skill.
449
+
450
+ ```bash
451
+ image-skill credits buy \
452
+ --provider stripe_x402 \
453
+ --quote-id quote_... \
454
+ --idempotency-key agent-x402-buy-run-001 \
455
+ --json
456
+ ```
457
+
458
+ Minimum x402 action-required data:
459
+
460
+ ```json
461
+ {
462
+ "state": "action_required",
463
+ "quote_id": "quote_...",
464
+ "payment_attempt_id": "payatt_...",
465
+ "provider": "stripe",
466
+ "accepted_payment_method": "stripe_x402.exact.usdc",
467
+ "credits": 500,
468
+ "amount_cents": 500,
469
+ "currency": "USD",
470
+ "live_money": true,
471
+ "stripe_x402": {
472
+ "method_id": "stripe_x402.exact.usdc",
473
+ "scheme": "exact",
474
+ "network": "base",
475
+ "token_currency": "usdc",
476
+ "deposit_address_present": true,
477
+ "redacted": {
478
+ "payment_intent_id": "[redacted-stripe-payment-intent]",
479
+ "deposit_address": "[redacted-stripe-crypto-deposit-address]",
480
+ "client_secret": "[redacted-stripe-client-secret]"
481
+ }
482
+ },
483
+ "next": {
484
+ "agent_action": "pay_stripe_crypto_deposit",
485
+ "suggested_commands": [
486
+ "image-skill credits status --payment-attempt-id payatt_... --json"
487
+ ]
488
+ }
489
+ }
490
+ ```
491
+
492
+ For a `stripe_checkout` quote, `--provider stripe` creates a hosted Stripe
493
+ Checkout Session and returns an `action_required` response with
494
+ `checkout_handoff_url`.
411
495
 
412
496
  Agents should present or open `checkout_handoff_url` for humans. It is a short
413
497
  Image Skill URL that redirects to Stripe Checkout and is safe to copy from
@@ -417,8 +501,7 @@ provide one. `checkout_url` is the raw Stripe compatibility fallback only; do
417
501
  not present it unless no handoff URL is available. Do not trim Stripe Checkout
418
502
  URLs: the long `#...` fragment is required by Stripe Checkout in the browser.
419
503
  Present any fallback Stripe URL in a fenced code block so terminal wrapping does
420
- not corrupt it.
421
- Stripe-hosted Checkout may also show a promotion-code field for
504
+ not corrupt it. Stripe-hosted Checkout may also show a promotion-code field for
422
505
  operator-provided codes; agents should let the human enter those codes on
423
506
  Stripe, never collect promo codes, card details, or wallet credentials in the
424
507
  Image Skill CLI.
@@ -467,11 +550,20 @@ curl -sS https://api.image-skill.com/v1/credit-purchases/stripe-checkout-session
467
550
  -d '{"quote_id":"quote_...","idempotency_key":"stripe-buy-run-001"}'
468
551
  ```
469
552
 
553
+ x402 hosted API equivalent:
554
+
555
+ ```bash
556
+ curl -sS https://api.image-skill.com/v1/credit-purchases/stripe-x402-deposits \
557
+ -H "authorization: Bearer $IMAGE_SKILL_TOKEN" \
558
+ -H "content-type: application/json" \
559
+ -d '{"quote_id":"quote_...","idempotency_key":"agent-x402-buy-run-001"}'
560
+ ```
561
+
470
562
  ### `image-skill credits status`
471
563
 
472
- Shows the durable state of a quote, Stripe Checkout attempt, Checkout Session,
473
- or receipt. Use this after `credits buy` so agents do not have to infer payment
474
- state from quota deltas or activity text.
564
+ Shows the durable state of a quote, x402 deposit attempt, Stripe Checkout
565
+ attempt, Checkout Session, or receipt. Use this after `credits buy` so agents
566
+ do not have to infer payment state from quota deltas or activity text.
475
567
 
476
568
  ```bash
477
569
  image-skill credits status \
@@ -525,10 +617,13 @@ curl -sS "https://api.image-skill.com/v1/credit-purchases/status?payment_attempt
525
617
  ```
526
618
 
527
619
  Do not pass card data, wallet secrets, provider receipts, Stripe secrets, MPP
528
- tokens, SPTs, live x402 payment headers, or any payment credential to credits
529
- commands. Stripe Checkout collects payment details only on Stripe-hosted pages.
530
- The public request fields are `credits`, `pack_id`, `payment_method`,
531
- `quote_id`, status reference IDs, and `idempotency_key`.
620
+ tokens, SPTs, live x402 payment headers, deposit client secrets, wallet
621
+ private keys, seed phrases, or any payment credential to credits commands.
622
+ Stripe Checkout collects payment details only on Stripe-hosted pages; x402
623
+ settlement is handled by the agent/wallet against the returned redacted deposit
624
+ challenge, not by pasting credentials into Image Skill. The public request
625
+ fields are `credits`, `pack_id`, `payment_method`, `quote_id`, status reference
626
+ IDs, and `idempotency_key`.
532
627
 
533
628
  ### `image-skill models`
534
629
 
@@ -660,6 +755,12 @@ image-skill create --guide --prompt "A compact field camera on a stainless workb
660
755
  auth/quota/payment blockers, and mutation flags. All mutation flags must be
661
756
  false in guide mode: no provider call, hosted create, signup, payment object,
662
757
  credit debit, or media write.
758
+ In guide cost output, `cost.estimated_usd_per_image` is the estimated Image
759
+ Skill debit in dollars for one output, matching
760
+ `cost.estimated_debit_usd_per_image` and
761
+ `cost.estimated_credits * cost.credit_unit_usd` when credit pricing is known.
762
+ `cost.estimated_provider_usd_per_image` is the upstream provider estimate for
763
+ transparency; do not use it as the amount the agent needs to fund.
663
764
 
664
765
  ```bash
665
766
  image-skill create \
@@ -679,10 +780,9 @@ intents, Image Skill may default an eligible quality-capability request to a
679
780
  higher output tier only when `--max-estimated-usd-per-image` is high enough for
680
781
  that tier; otherwise it stays on a lower-cost quality tier or chooses a cheaper
681
782
  capability within the budget and tells agents what happened in the selection
682
- receipt.
683
- Use `0.05` only when intentionally budget-capping to a lower-cost or
684
- lower-resolution path; the current no-model quality default needs `0.07` to
685
- permit the 2k plan.
783
+ receipt. Use the `--max-estimated-usd-per-image` value returned by
784
+ `create --guide`; it is sized to the Image Skill credit debit, not only the
785
+ upstream provider estimate.
686
786
 
687
787
  Preview-compatible richer shape:
688
788
 
@@ -704,7 +804,8 @@ top-level Image Skill create control; do not pass provider-native `n` through
704
804
  `model_parameters` unless the selected model schema explicitly advertises that
705
805
  field. Credit pricing and `cost.credit_pricing.credits_required` are total
706
806
  operation debits across all requested outputs. `--max-estimated-usd-per-image`
707
- and raw API `max_estimated_usd_per_image` remain per-image budget guards.
807
+ and raw API `max_estimated_usd_per_image` are per-image Image Skill debit
808
+ budget guards.
708
809
 
709
810
  Generate video through the same `create` command and durable-media loop. Because
710
811
  the no-model default selects an image model, request a video model by id; the