@whop/cli 0.12.0 → 0.13.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/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  external_exports
6
6
  } from "./chunk-KFCNNWPI.js";
7
7
 
8
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Cli.js
8
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Cli.js
9
9
  var Cli_exports = {};
10
10
  __export(Cli_exports, {
11
11
  collectSkillCommands: () => collectSkillCommands,
@@ -106,7 +106,7 @@ function extractSegmentPart(segment, segmentTokenStart, segmentTokenCount, targe
106
106
  return segment.slice(charStart, charEnd);
107
107
  }
108
108
 
109
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/internal/helpers.js
109
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/internal/helpers.js
110
110
  function isRecord(value) {
111
111
  return typeof value === "object" && value !== null && !Array.isArray(value);
112
112
  }
@@ -154,7 +154,7 @@ function suggest(input, candidates) {
154
154
  return best;
155
155
  }
156
156
 
157
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Completions.js
157
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Completions.js
158
158
  function register(shell, name) {
159
159
  switch (shell) {
160
160
  case "bash":
@@ -417,7 +417,7 @@ let _incur_complete_${id} = {|spans|
417
417
  }`;
418
418
  }
419
419
 
420
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Errors.js
420
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Errors.js
421
421
  var BaseError = class extends Error {
422
422
  name = "Incur.BaseError";
423
423
  /** The short, human-readable error message (without details). */
@@ -491,7 +491,7 @@ function walk(error, fn) {
491
491
  return current;
492
492
  }
493
493
 
494
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Fetch.js
494
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Fetch.js
495
495
  var reservedFlags = /* @__PURE__ */ new Set(["method", "body", "data", "header"]);
496
496
  var reservedShort = { X: "method", d: "data", H: "header" };
497
497
  function parseArgv(argv2) {
@@ -627,7 +627,7 @@ async function parseResponse(response) {
627
627
  };
628
628
  }
629
629
 
630
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Filter.js
630
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Filter.js
631
631
  function parse(expression) {
632
632
  const paths = [];
633
633
  const tokens = [];
@@ -1127,7 +1127,7 @@ function resolveOptions(options) {
1127
1127
  };
1128
1128
  }
1129
1129
 
1130
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/internal/json.js
1130
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/internal/json.js
1131
1131
  function stringify(value, space) {
1132
1132
  return JSON.stringify(value, (_key, value2) => {
1133
1133
  if (typeof value2 === "bigint")
@@ -1139,7 +1139,7 @@ function normalize(value) {
1139
1139
  return JSON.parse(stringify(value));
1140
1140
  }
1141
1141
 
1142
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/internal/yaml.js
1142
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/internal/yaml.js
1143
1143
  import { createRequire } from "module";
1144
1144
  var cached;
1145
1145
  async function load() {
@@ -1151,7 +1151,7 @@ function loadSync() {
1151
1151
  return cached;
1152
1152
  }
1153
1153
 
1154
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Formatter.js
1154
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Formatter.js
1155
1155
  function format2(value, fmt = "toon") {
1156
1156
  if (value == null)
1157
1157
  return "";
@@ -1259,7 +1259,7 @@ ${String(val)}`;
1259
1259
  return kvTable(obj);
1260
1260
  }
1261
1261
 
1262
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Parser.js
1262
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Parser.js
1263
1263
  function parse2(argv2, options = {}) {
1264
1264
  const { args: argsSchema, options: optionsSchema, alias, defaults } = options;
1265
1265
  const optionNames = createOptionNames(optionsSchema, alias);
@@ -1676,7 +1676,7 @@ function defaultEnvSource() {
1676
1676
  return {};
1677
1677
  }
1678
1678
 
1679
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/internal/command.js
1679
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/internal/command.js
1680
1680
  var sentinel = Symbol.for("incur.sentinel");
1681
1681
  async function execute(command, options) {
1682
1682
  const { argv: argv2, inputOptions: inputOptions2, agent, format: format3, formatExplicit, name, path: path9, version, envSource = process.env, env: envSchema, globals = {}, vars: varsSchema, middlewares = [], request: request2 } = options;
@@ -1925,7 +1925,7 @@ function findBuiltinSubcommand(builtin, token) {
1925
1925
  return builtin.subcommands?.find((sub) => sub.name === token || sub.aliases?.includes(token));
1926
1926
  }
1927
1927
 
1928
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Help.js
1928
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Help.js
1929
1929
  function formatRoot(name, options = {}) {
1930
1930
  const { aliases, configFlag, description, globals, version, commands = [], root = false } = options;
1931
1931
  const lines = [];
@@ -2211,7 +2211,7 @@ function redact(value) {
2211
2211
  return `****${value.slice(-4)}`;
2212
2212
  }
2213
2213
 
2214
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/internal/cta.js
2214
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/internal/cta.js
2215
2215
  function formatCtaBlock(name, block) {
2216
2216
  if (!block || block.commands.length === 0)
2217
2217
  return void 0;
@@ -2234,7 +2234,7 @@ function formatCta(name, cta) {
2234
2234
  return { command: cmd, ...cta.description ? { description: cta.description } : void 0 };
2235
2235
  }
2236
2236
 
2237
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/internal/pm.js
2237
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/internal/pm.js
2238
2238
  function detectRunner() {
2239
2239
  const userAgent = process.env.npm_config_user_agent ?? "";
2240
2240
  const execPath = process.env.npm_execpath ?? "";
@@ -2245,7 +2245,7 @@ function detectRunner() {
2245
2245
  return "npx";
2246
2246
  }
2247
2247
 
2248
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Schema.js
2248
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Schema.js
2249
2249
  function toJsonSchema(schema) {
2250
2250
  const result = external_exports.toJSONSchema(schema, {
2251
2251
  unrepresentable: "any",
@@ -2259,7 +2259,7 @@ function toJsonSchema(schema) {
2259
2259
  return result;
2260
2260
  }
2261
2261
 
2262
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Mcp.js
2262
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Mcp.js
2263
2263
  async function serve(name, version, commands, options = {}) {
2264
2264
  const stdio = importStdioModule();
2265
2265
  const mcp = await import("./dist-2MZJLO2W.js");
@@ -2594,7 +2594,7 @@ function buildToolSchema(args, options) {
2594
2594
  return { type: "object", properties };
2595
2595
  }
2596
2596
 
2597
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Openapi.js
2597
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Openapi.js
2598
2598
  var Openapi_exports = {};
2599
2599
  __export(Openapi_exports, {
2600
2600
  coerceIfNeeded: () => coerceIfNeeded,
@@ -2604,7 +2604,7 @@ __export(Openapi_exports, {
2604
2604
  toZod: () => toZod
2605
2605
  });
2606
2606
 
2607
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/internal/dereference.js
2607
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/internal/dereference.js
2608
2608
  function dereference(root) {
2609
2609
  const cache = /* @__PURE__ */ new Map();
2610
2610
  return walk2(root, root, cache);
@@ -2656,7 +2656,7 @@ function resolvePointer(root, pointer) {
2656
2656
  return current;
2657
2657
  }
2658
2658
 
2659
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Openapi.js
2659
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Openapi.js
2660
2660
  function fromCli(cli2, options = {}) {
2661
2661
  const commands = toCommands.get(cli2);
2662
2662
  if (!commands)
@@ -3251,7 +3251,7 @@ function coerceIfNeeded(schema) {
3251
3251
  return desc ? coerced.describe(desc) : coerced;
3252
3252
  }
3253
3253
 
3254
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/McpSource.js
3254
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/McpSource.js
3255
3255
  var protocolVersion = "2025-06-18";
3256
3256
  async function resolve2(source, options = {}) {
3257
3257
  const session = sourceSession(source);
@@ -3418,7 +3418,7 @@ function resultValue(result) {
3418
3418
  return textItems;
3419
3419
  }
3420
3420
 
3421
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Skill.js
3421
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Skill.js
3422
3422
  import { createHash } from "crypto";
3423
3423
  function index(name, commands, description) {
3424
3424
  const lines = [`# ${name}`];
@@ -3662,7 +3662,7 @@ function resolveTypeName2(prop) {
3662
3662
  return "unknown";
3663
3663
  }
3664
3664
 
3665
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/SyncMcp.js
3665
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/SyncMcp.js
3666
3666
  import { execFile } from "child_process";
3667
3667
  import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync } from "fs";
3668
3668
  import { homedir } from "os";
@@ -3847,13 +3847,13 @@ function exec(cmd, args) {
3847
3847
  });
3848
3848
  }
3849
3849
 
3850
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/SyncSkills.js
3850
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/SyncSkills.js
3851
3851
  import fsSync from "fs";
3852
3852
  import fs2 from "fs/promises";
3853
3853
  import os2 from "os";
3854
3854
  import path2 from "path";
3855
3855
 
3856
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/internal/agents.js
3856
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/internal/agents.js
3857
3857
  import * as fs from "fs";
3858
3858
  import * as os from "os";
3859
3859
  import * as path from "path";
@@ -4133,7 +4133,7 @@ function resolveParent(dir) {
4133
4133
  }
4134
4134
  }
4135
4135
 
4136
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/SyncSkills.js
4136
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/SyncSkills.js
4137
4137
  async function sync(name, commands, options = {}) {
4138
4138
  const { depth = 1, description, global = true } = options;
4139
4139
  const cwd = options.cwd ?? (global ? resolvePackageRoot() : process.cwd());
@@ -4146,13 +4146,17 @@ async function sync(name, commands, options = {}) {
4146
4146
  const tmpDir = await fs2.mkdtemp(path2.join(os2.tmpdir(), `incur-skills-${name}-`));
4147
4147
  try {
4148
4148
  const skills = [];
4149
+ const generatedDirs = /* @__PURE__ */ new Map();
4149
4150
  for (const file of files) {
4150
4151
  const filePath = file.dir ? path2.join(tmpDir, file.dir, "SKILL.md") : path2.join(tmpDir, "SKILL.md");
4151
4152
  await fs2.mkdir(path2.dirname(filePath), { recursive: true });
4152
4153
  await fs2.writeFile(filePath, `${file.content}
4153
4154
  `);
4154
4155
  const meta = parseSkillFrontmatter(file.content);
4155
- skills.push({ name: meta.name ?? (file.dir || name), description: meta.description });
4156
+ const skillName = meta.name ?? (file.dir || name);
4157
+ skills.push({ name: skillName, description: meta.description });
4158
+ if (file.dir)
4159
+ generatedDirs.set(skillName, file.dir);
4156
4160
  }
4157
4161
  if (options.include) {
4158
4162
  for (const pattern of options.include) {
@@ -4165,7 +4169,14 @@ async function sync(name, commands, options = {}) {
4165
4169
  const dest = path2.join(tmpDir, skillName, "SKILL.md");
4166
4170
  await fs2.mkdir(path2.dirname(dest), { recursive: true });
4167
4171
  await fs2.writeFile(dest, content);
4168
- if (!skills.some((s) => s.name === skillName))
4172
+ const generatedDir = generatedDirs.get(meta.name ?? skillName);
4173
+ if (generatedDir && generatedDir !== skillName)
4174
+ await fs2.rm(path2.join(tmpDir, generatedDir), { recursive: true, force: true });
4175
+ const existing = skills.find((s) => s.name === skillName);
4176
+ if (existing) {
4177
+ existing.description = meta.description;
4178
+ existing.external = true;
4179
+ } else
4169
4180
  skills.push({ name: skillName, description: meta.description, external: true });
4170
4181
  } catch {
4171
4182
  }
@@ -4294,7 +4305,7 @@ function readHash(name) {
4294
4305
  return readMeta(name)?.hash;
4295
4306
  }
4296
4307
 
4297
- // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+27b7d58e6db9d4a56de5138e2835a3a9c8eb8859/node_modules/incur/dist/Cli.js
4308
+ // ../../node_modules/.pnpm/incur@https+++codeload.github.com+whopio+incur+tar.gz+585b28b5317c8b5aeb58acb034bea04ed4adc067/node_modules/incur/dist/Cli.js
4298
4309
  var destructiveCommandHint = "Confirm with the user before executing this destructive command.";
4299
4310
  function create(nameOrDefinition, definition) {
4300
4311
  const name = typeof nameOrDefinition === "string" ? nameOrDefinition : nameOrDefinition.name;
@@ -16421,13 +16432,13 @@ var native_spec_default = {
16421
16432
  },
16422
16433
  "/events": {
16423
16434
  get: {
16424
- description: "Lists pixel events, most recent first. Pass person_id for one person's journey, or omit it to list identity-linked events for an account within an explicit time range. Events are shaped like the POST /events intake: attribution in context, identity in user.",
16435
+ description: "Lists identity-linked events, most recent first. Pass identifier for one person's journey, or omit it to list events for an account within an explicit time range. Events are shaped like the POST /events intake: attribution in context, identity in user.",
16425
16436
  operationId: "list",
16426
16437
  parameters: [
16427
16438
  {
16428
- description: "The ID of the person. Omit to list recent identity-linked events for the account.",
16439
+ description: "Any hard identifier of the person: a person ID (prsn_*), user ID, email, phone number, or a tracking cookie value (wuid, anonymous ID, fbp/fbc/ttp/ga). Omit to list recent events for the account.",
16429
16440
  in: "query",
16430
- name: "person_id",
16441
+ name: "identifier",
16431
16442
  required: false,
16432
16443
  schema: {
16433
16444
  type: "string"
@@ -16443,7 +16454,7 @@ var native_spec_default = {
16443
16454
  }
16444
16455
  },
16445
16456
  {
16446
- description: "Start of the time range as an ISO 8601 timestamp. Required when person_id is omitted.",
16457
+ description: "Start of the time range as an ISO 8601 timestamp. Required when identifier is omitted.",
16447
16458
  in: "query",
16448
16459
  name: "from",
16449
16460
  required: false,
@@ -16453,7 +16464,7 @@ var native_spec_default = {
16453
16464
  }
16454
16465
  },
16455
16466
  {
16456
- description: "End of the time range as an ISO 8601 timestamp. Required when person_id is omitted; otherwise defaults to now.",
16467
+ description: "End of the time range as an ISO 8601 timestamp. Required when identifier is omitted; otherwise defaults to now.",
16457
16468
  in: "query",
16458
16469
  name: "to",
16459
16470
  required: false,
@@ -16645,6 +16656,195 @@ var native_spec_default = {
16645
16656
  "null"
16646
16657
  ]
16647
16658
  },
16659
+ related: {
16660
+ description: "Hydrated details for the records this event references. Only present keys resolved.",
16661
+ properties: {
16662
+ account: {
16663
+ properties: {
16664
+ id: {
16665
+ type: "string"
16666
+ },
16667
+ logo_url: {
16668
+ type: [
16669
+ "string",
16670
+ "null"
16671
+ ]
16672
+ },
16673
+ route: {
16674
+ type: [
16675
+ "string",
16676
+ "null"
16677
+ ]
16678
+ },
16679
+ title: {
16680
+ type: [
16681
+ "string",
16682
+ "null"
16683
+ ]
16684
+ }
16685
+ },
16686
+ type: [
16687
+ "object",
16688
+ "null"
16689
+ ]
16690
+ },
16691
+ app: {
16692
+ properties: {
16693
+ domain_id: {
16694
+ type: [
16695
+ "string",
16696
+ "null"
16697
+ ]
16698
+ },
16699
+ icon_url: {
16700
+ type: [
16701
+ "string",
16702
+ "null"
16703
+ ]
16704
+ },
16705
+ id: {
16706
+ type: "string"
16707
+ },
16708
+ title: {
16709
+ type: [
16710
+ "string",
16711
+ "null"
16712
+ ]
16713
+ }
16714
+ },
16715
+ type: [
16716
+ "object",
16717
+ "null"
16718
+ ]
16719
+ },
16720
+ payment: {
16721
+ properties: {
16722
+ card_brand: {
16723
+ type: [
16724
+ "string",
16725
+ "null"
16726
+ ]
16727
+ },
16728
+ card_last4: {
16729
+ type: [
16730
+ "string",
16731
+ "null"
16732
+ ]
16733
+ },
16734
+ id: {
16735
+ type: "string"
16736
+ },
16737
+ provider: {
16738
+ type: [
16739
+ "string",
16740
+ "null"
16741
+ ]
16742
+ }
16743
+ },
16744
+ type: [
16745
+ "object",
16746
+ "null"
16747
+ ]
16748
+ },
16749
+ plan: {
16750
+ properties: {
16751
+ billing_period: {
16752
+ type: [
16753
+ "integer",
16754
+ "null"
16755
+ ]
16756
+ },
16757
+ currency: {
16758
+ type: [
16759
+ "string",
16760
+ "null"
16761
+ ]
16762
+ },
16763
+ id: {
16764
+ type: "string"
16765
+ },
16766
+ initial_price: {
16767
+ type: [
16768
+ "number",
16769
+ "null"
16770
+ ]
16771
+ },
16772
+ renewal_price: {
16773
+ type: [
16774
+ "number",
16775
+ "null"
16776
+ ]
16777
+ },
16778
+ title: {
16779
+ type: [
16780
+ "string",
16781
+ "null"
16782
+ ]
16783
+ }
16784
+ },
16785
+ type: [
16786
+ "object",
16787
+ "null"
16788
+ ]
16789
+ },
16790
+ product: {
16791
+ properties: {
16792
+ id: {
16793
+ type: "string"
16794
+ },
16795
+ route: {
16796
+ type: [
16797
+ "string",
16798
+ "null"
16799
+ ]
16800
+ },
16801
+ title: {
16802
+ type: [
16803
+ "string",
16804
+ "null"
16805
+ ]
16806
+ }
16807
+ },
16808
+ type: [
16809
+ "object",
16810
+ "null"
16811
+ ]
16812
+ },
16813
+ user: {
16814
+ properties: {
16815
+ avatar_url: {
16816
+ type: [
16817
+ "string",
16818
+ "null"
16819
+ ]
16820
+ },
16821
+ id: {
16822
+ type: "string"
16823
+ },
16824
+ name: {
16825
+ type: [
16826
+ "string",
16827
+ "null"
16828
+ ]
16829
+ },
16830
+ username: {
16831
+ type: [
16832
+ "string",
16833
+ "null"
16834
+ ]
16835
+ }
16836
+ },
16837
+ type: [
16838
+ "object",
16839
+ "null"
16840
+ ]
16841
+ }
16842
+ },
16843
+ type: [
16844
+ "object",
16845
+ "null"
16846
+ ]
16847
+ },
16648
16848
  total_usd_amount: {
16649
16849
  type: [
16650
16850
  "number",
@@ -16700,12 +16900,6 @@ var native_spec_default = {
16700
16900
  "string",
16701
16901
  "null"
16702
16902
  ]
16703
- },
16704
- state: {
16705
- type: [
16706
- "string",
16707
- "null"
16708
- ]
16709
16903
  }
16710
16904
  },
16711
16905
  type: [
@@ -20493,10 +20687,6 @@ var native_spec_default = {
20493
20687
  description: "The payout currency. Defaults to usd.",
20494
20688
  type: "string"
20495
20689
  },
20496
- idempotency_key: {
20497
- description: "A client-generated key that makes retries safe. Retrying with the same key returns the original payout instead of creating a second one.",
20498
- type: "string"
20499
- },
20500
20690
  payout_method_id: {
20501
20691
  description: "The saved payout method to deliver to (a potk_ identifier).",
20502
20692
  type: "string"
@@ -30526,6 +30716,13 @@ var native_spec_default = {
30526
30716
  "null"
30527
30717
  ]
30528
30718
  },
30719
+ cost_per_unique_click: {
30720
+ description: "Spend divided by unique clicks; null when there are no unique clicks.",
30721
+ type: [
30722
+ "number",
30723
+ "null"
30724
+ ]
30725
+ },
30529
30726
  cost_per_viewed_content: {
30530
30727
  description: "Spend divided by attributed view-content events; null when they are not the goal and none are attributed.",
30531
30728
  type: [
@@ -30795,7 +30992,7 @@ var native_spec_default = {
30795
30992
  ]
30796
30993
  },
30797
30994
  unique_clicks: {
30798
- description: "The number of unique clicks.",
30995
+ description: "People who clicked, reported by the Whop pixel, counted once per person.",
30799
30996
  type: "number"
30800
30997
  },
30801
30998
  updated_at: {
@@ -30826,6 +31023,7 @@ var native_spec_default = {
30826
31023
  "click_through_rate",
30827
31024
  "clicks",
30828
31025
  "cost_per_click",
31026
+ "cost_per_unique_click",
30829
31027
  "cost_per_lead",
30830
31028
  "cost_per_mille",
30831
31029
  "cost_per_purchase",
@@ -31038,6 +31236,13 @@ var native_spec_default = {
31038
31236
  "null"
31039
31237
  ]
31040
31238
  },
31239
+ cost_per_unique_click: {
31240
+ description: "Spend divided by unique clicks; null when there are no unique clicks.",
31241
+ type: [
31242
+ "number",
31243
+ "null"
31244
+ ]
31245
+ },
31041
31246
  cost_per_viewed_content: {
31042
31247
  description: "Spend divided by attributed view-content events; null when they are not the goal and none are attributed.",
31043
31248
  type: [
@@ -31262,7 +31467,7 @@ var native_spec_default = {
31262
31467
  ]
31263
31468
  },
31264
31469
  unique_clicks: {
31265
- description: "The number of unique clicks.",
31470
+ description: "People who clicked, reported by the Whop pixel, counted once per person.",
31266
31471
  type: "number"
31267
31472
  },
31268
31473
  updated_at: {
@@ -31282,6 +31487,7 @@ var native_spec_default = {
31282
31487
  "click_through_rate",
31283
31488
  "clicks",
31284
31489
  "cost_per_click",
31490
+ "cost_per_unique_click",
31285
31491
  "cost_per_lead",
31286
31492
  "cost_per_mille",
31287
31493
  "cost_per_purchase",
@@ -31595,6 +31801,13 @@ var native_spec_default = {
31595
31801
  "null"
31596
31802
  ]
31597
31803
  },
31804
+ cost_per_unique_click: {
31805
+ description: "Spend divided by unique clicks; null when there are no unique clicks.",
31806
+ type: [
31807
+ "number",
31808
+ "null"
31809
+ ]
31810
+ },
31598
31811
  cost_per_viewed_content: {
31599
31812
  description: "Spend divided by attributed view-content events; null when they are not the goal and none are attributed.",
31600
31813
  type: [
@@ -31886,7 +32099,7 @@ var native_spec_default = {
31886
32099
  ]
31887
32100
  },
31888
32101
  unique_clicks: {
31889
- description: "The number of unique clicks.",
32102
+ description: "People who clicked, reported by the Whop pixel, counted once per person.",
31890
32103
  type: "number"
31891
32104
  },
31892
32105
  updated_at: {
@@ -31906,6 +32119,7 @@ var native_spec_default = {
31906
32119
  "click_through_rate",
31907
32120
  "clicks",
31908
32121
  "cost_per_click",
32122
+ "cost_per_unique_click",
31909
32123
  "cost_per_lead",
31910
32124
  "cost_per_mille",
31911
32125
  "cost_per_purchase",
@@ -42155,7 +42369,13 @@ function openBrowser(url) {
42155
42369
  if (process.platform === "darwin") {
42156
42370
  execFile2("open", [url], ignore);
42157
42371
  } else if (process.platform === "win32") {
42158
- execFile2("cmd.exe", ["/c", "start", "", url], ignore);
42372
+ const escaped = url.replace(/[&|<>^]/g, "^$&");
42373
+ execFile2(
42374
+ "cmd.exe",
42375
+ ["/d", "/s", "/c", "start", '""', escaped],
42376
+ { windowsVerbatimArguments: true },
42377
+ ignore
42378
+ );
42159
42379
  } else {
42160
42380
  execFile2("xdg-open", [url], ignore);
42161
42381
  }
@@ -42223,7 +42443,7 @@ import { Whop } from "@whop/sdk";
42223
42443
  // package.json
42224
42444
  var package_default = {
42225
42445
  name: "@whop/cli",
42226
- version: "0.12.0",
42446
+ version: "0.13.0",
42227
42447
  description: "The Whop CLI \u2014 build and manage Whop apps from your terminal. Human and agent friendly.",
42228
42448
  keywords: [
42229
42449
  "agent",
@@ -42282,7 +42502,7 @@ var package_default = {
42282
42502
  devDependencies: {
42283
42503
  "@types/node": "25.3.5",
42284
42504
  fflate: "0.8.2",
42285
- incur: "github:whopio/incur#27b7d58e6db9d4a56de5138e2835a3a9c8eb8859",
42505
+ incur: "github:whopio/incur#585b28b5317c8b5aeb58acb034bea04ed4adc067",
42286
42506
  tsup: "8.5.0",
42287
42507
  tsx: "4.19.4",
42288
42508
  typescript: "5.9.3",
@@ -42426,11 +42646,23 @@ function writeConfig(config, env = process.env) {
42426
42646
  import fs5 from "fs";
42427
42647
  import path5 from "path";
42428
42648
  import { createRequire as createRequire2 } from "module";
42649
+ import { execFileSync } from "child_process";
42650
+ import {
42651
+ createCipheriv,
42652
+ createDecipheriv,
42653
+ hkdfSync,
42654
+ randomBytes
42655
+ } from "crypto";
42656
+
42657
+ // src/lib/npx.ts
42658
+ function isNpx(selfUrl = import.meta.url) {
42659
+ return selfUrl.includes("/_npx/");
42660
+ }
42429
42661
 
42430
42662
  // src/lib/build-info.ts
42431
42663
  var buildChannel = true ? "npm" : "dev";
42432
42664
  var buildTarget = typeof WHOP_CLI_TARGET === "string" ? WHOP_CLI_TARGET : null;
42433
- var buildVersion = true ? "0.12.0" : null;
42665
+ var buildVersion = true ? "0.13.0" : null;
42434
42666
  function isHomebrewPath(execPath, env = process.env) {
42435
42667
  if (/[/\\](Cellar|homebrew|linuxbrew)[/\\]/.test(execPath)) return true;
42436
42668
  const prefix = env.HOMEBREW_PREFIX?.trim();
@@ -42446,6 +42678,7 @@ function detectChannel(env = process.env, execPath = process.execPath) {
42446
42678
 
42447
42679
  // src/auth/secret-store.ts
42448
42680
  var SERVICE = "whop-cli";
42681
+ var KEY_PEPPER = "whop-cli/secret-store/v3";
42449
42682
  var keyringModule;
42450
42683
  function loadKeyring() {
42451
42684
  if (keyringModule === void 0) {
@@ -42487,37 +42720,135 @@ var keyringStore = {
42487
42720
  }
42488
42721
  }
42489
42722
  };
42723
+ var cachedMachineId;
42724
+ function machineId(env) {
42725
+ const override = env.WHOP_CLI_MACHINE_ID?.trim();
42726
+ if (override) return override;
42727
+ if (cachedMachineId !== void 0) return cachedMachineId;
42728
+ cachedMachineId = detectMachineId();
42729
+ return cachedMachineId;
42730
+ }
42731
+ function detectMachineId() {
42732
+ try {
42733
+ if (process.platform === "darwin") {
42734
+ const out = execFileSync(
42735
+ "ioreg",
42736
+ ["-rd1", "-c", "IOPlatformExpertDevice"],
42737
+ { encoding: "utf8" }
42738
+ );
42739
+ return /"IOPlatformUUID"\s*=\s*"([^"]+)"/.exec(out)?.[1] ?? "";
42740
+ }
42741
+ if (process.platform === "linux") {
42742
+ for (const file of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
42743
+ try {
42744
+ const id = fs5.readFileSync(file, "utf8").trim();
42745
+ if (id) return id;
42746
+ } catch {
42747
+ }
42748
+ }
42749
+ return "";
42750
+ }
42751
+ if (process.platform === "win32") {
42752
+ const out = execFileSync(
42753
+ "reg",
42754
+ [
42755
+ "query",
42756
+ "HKLM\\SOFTWARE\\Microsoft\\Cryptography",
42757
+ "/v",
42758
+ "MachineGuid"
42759
+ ],
42760
+ { encoding: "utf8" }
42761
+ );
42762
+ return /MachineGuid\s+REG_SZ\s+([\w-]+)/.exec(out)?.[1] ?? "";
42763
+ }
42764
+ } catch {
42765
+ }
42766
+ return "";
42767
+ }
42768
+ function deriveKey(machine, salt) {
42769
+ const ikm = machine || "whop-cli/no-machine-id";
42770
+ return Buffer.from(hkdfSync("sha256", ikm, salt, KEY_PEPPER, 32));
42771
+ }
42772
+ function encryptValue(plaintext, machine) {
42773
+ const salt = randomBytes(16);
42774
+ const iv = randomBytes(12);
42775
+ const cipher = createCipheriv("aes-256-gcm", deriveKey(machine, salt), iv);
42776
+ const ciphertext = Buffer.concat([
42777
+ cipher.update(Buffer.from(plaintext, "utf8")),
42778
+ cipher.final()
42779
+ ]);
42780
+ const payload = Buffer.concat([iv, ciphertext, cipher.getAuthTag()]);
42781
+ return `${salt.toString("base64")}-${payload.toString("base64")}`;
42782
+ }
42783
+ function decryptValue(stored, machine) {
42784
+ const dash = stored.indexOf("-");
42785
+ if (dash < 0) return null;
42786
+ const salt = Buffer.from(stored.slice(0, dash), "base64");
42787
+ const payload = Buffer.from(stored.slice(dash + 1), "base64");
42788
+ if (payload.length < 12 + 16) return null;
42789
+ const iv = payload.subarray(0, 12);
42790
+ const tag = payload.subarray(payload.length - 16);
42791
+ const ciphertext = payload.subarray(12, payload.length - 16);
42792
+ try {
42793
+ const decipher = createDecipheriv("aes-256-gcm", deriveKey(machine, salt), iv);
42794
+ decipher.setAuthTag(tag);
42795
+ return Buffer.concat([
42796
+ decipher.update(ciphertext),
42797
+ decipher.final()
42798
+ ]).toString("utf8");
42799
+ } catch {
42800
+ return null;
42801
+ }
42802
+ }
42490
42803
  function credentialsPath(env) {
42491
42804
  return path5.join(configDir(env), "credentials.json");
42492
42805
  }
42493
- function readCredentials(env) {
42806
+ function sanitizeStringMap(value) {
42807
+ if (value == null || typeof value !== "object" || Array.isArray(value)) {
42808
+ return {};
42809
+ }
42810
+ const out = {};
42811
+ for (const [key, val] of Object.entries(value)) {
42812
+ if (typeof val === "string") out[key] = val;
42813
+ }
42814
+ return out;
42815
+ }
42816
+ function readStoredFile(env) {
42494
42817
  let raw;
42495
42818
  try {
42496
42819
  raw = fs5.readFileSync(credentialsPath(env), "utf8");
42497
42820
  } catch {
42498
- return {};
42821
+ return { legacy: false, secrets: {} };
42499
42822
  }
42823
+ let parsed;
42500
42824
  try {
42501
- const parsed = JSON.parse(raw);
42502
- if (parsed != null && typeof parsed === "object" && parsed.secrets != null && typeof parsed.secrets === "object" && !Array.isArray(parsed.secrets)) {
42503
- const secrets = {};
42504
- for (const [key, value] of Object.entries(parsed.secrets)) {
42505
- if (typeof value === "string") secrets[key] = value;
42506
- }
42507
- return secrets;
42508
- }
42825
+ parsed = JSON.parse(raw);
42509
42826
  } catch {
42827
+ return { legacy: false, secrets: {} };
42510
42828
  }
42511
- return {};
42829
+ if (parsed == null || typeof parsed !== "object") {
42830
+ return { legacy: false, secrets: {} };
42831
+ }
42832
+ const obj = parsed;
42833
+ return { legacy: obj.version !== 3, secrets: sanitizeStringMap(obj.secrets) };
42834
+ }
42835
+ function toCiphertextMap(stored, env) {
42836
+ if (!stored.legacy) return { ...stored.secrets };
42837
+ const machine = machineId(env);
42838
+ const encrypted = {};
42839
+ for (const [name, value] of Object.entries(stored.secrets)) {
42840
+ encrypted[name] = encryptValue(value, machine);
42841
+ }
42842
+ return encrypted;
42512
42843
  }
42513
- function writeCredentials(secrets, env) {
42844
+ function writeStoredFile(secrets, env) {
42514
42845
  const dir = configDir(env);
42515
42846
  fs5.mkdirSync(dir, { recursive: true, mode: 448 });
42516
42847
  const file = credentialsPath(env);
42517
42848
  const tmp = `${file}.${process.pid}.tmp`;
42518
42849
  fs5.writeFileSync(
42519
42850
  tmp,
42520
- `${JSON.stringify({ version: 1, secrets }, null, 2)}
42851
+ `${JSON.stringify({ version: 3, secrets }, null, 2)}
42521
42852
  `,
42522
42853
  { mode: 384 }
42523
42854
  );
@@ -42530,56 +42861,91 @@ function writeCredentials(secrets, env) {
42530
42861
  function fileStore(env) {
42531
42862
  return {
42532
42863
  set(name, secret) {
42533
- const secrets = readCredentials(env);
42534
- secrets[name] = secret;
42535
- writeCredentials(secrets, env);
42864
+ const secrets = toCiphertextMap(readStoredFile(env), env);
42865
+ secrets[name] = encryptValue(secret, machineId(env));
42866
+ writeStoredFile(secrets, env);
42536
42867
  return true;
42537
42868
  },
42538
42869
  get(name) {
42539
- return readCredentials(env)[name] ?? null;
42870
+ const stored = readStoredFile(env);
42871
+ const value = stored.secrets[name];
42872
+ if (value == null) return null;
42873
+ return stored.legacy ? value : decryptValue(value, machineId(env));
42540
42874
  },
42541
42875
  delete(name) {
42542
42876
  if (!fs5.existsSync(credentialsPath(env))) return;
42543
- const secrets = readCredentials(env);
42877
+ const secrets = toCiphertextMap(readStoredFile(env), env);
42544
42878
  delete secrets[name];
42545
- writeCredentials(secrets, env);
42879
+ writeStoredFile(secrets, env);
42546
42880
  }
42547
42881
  };
42548
42882
  }
42549
- function storesFor(env) {
42883
+ function resolveStoreKinds(policy) {
42884
+ if (policy.forced === "keyring") return ["keyring"];
42885
+ if (policy.forced === "file") return ["file"];
42886
+ if (policy.isStandaloneBinary) return ["file"];
42887
+ if (policy.platform === "darwin" && policy.isNpx) return ["file"];
42888
+ return ["keyring", "file"];
42889
+ }
42890
+ function storeFor(kind, env) {
42891
+ return kind === "keyring" ? keyringStore : fileStore(env);
42892
+ }
42893
+ function storeKindsFor(env) {
42894
+ return resolveStoreKinds({
42895
+ platform: process.platform,
42896
+ isStandaloneBinary: buildTarget != null,
42897
+ isNpx: isNpx(),
42898
+ forced: env.WHOP_CLI_SECRET_STORE?.trim()
42899
+ });
42900
+ }
42901
+ function cleanupKindsFor(env) {
42550
42902
  const forced = env.WHOP_CLI_SECRET_STORE?.trim();
42551
- if (forced === "file") return [fileStore(env)];
42552
- if (forced === "keyring") return [keyringStore];
42553
- if (buildTarget) return [fileStore(env)];
42554
- return [keyringStore, fileStore(env)];
42903
+ if (forced === "file") return ["file"];
42904
+ if (forced === "keyring") return ["keyring"];
42905
+ return ["keyring", "file"];
42906
+ }
42907
+ var secretCache = /* @__PURE__ */ new Map();
42908
+ function cacheKey(name, env) {
42909
+ return `${storeKindsFor(env)[0]} ${configDir(env)} ${name}`;
42555
42910
  }
42556
42911
  function setSecret(name, secret, env = process.env) {
42557
- const stores = storesFor(env);
42558
- const winner = stores.find((store) => store.set(name, secret));
42912
+ const winner = storeKindsFor(env).find(
42913
+ (kind) => storeFor(kind, env).set(name, secret)
42914
+ );
42559
42915
  if (!winner) {
42560
42916
  throw new Error(
42561
- "WHOP_CLI_SECRET_STORE=keyring but the OS keychain is unavailable"
42917
+ "WHOP_CLI_SECRET_STORE=keyring but the OS keystore is unavailable"
42562
42918
  );
42563
42919
  }
42564
- for (const store of stores) {
42565
- if (store !== winner) store.delete(name);
42920
+ for (const kind of cleanupKindsFor(env)) {
42921
+ if (kind !== winner) storeFor(kind, env).delete(name);
42566
42922
  }
42923
+ secretCache.set(cacheKey(name, env), secret);
42567
42924
  }
42568
42925
  function getSecret(name, env = process.env) {
42569
- for (const store of storesFor(env)) {
42570
- const secret = store.get(name);
42571
- if (secret != null) return secret;
42926
+ const key = cacheKey(name, env);
42927
+ const cached2 = secretCache.get(key);
42928
+ if (cached2 !== void 0) return cached2;
42929
+ let result = null;
42930
+ for (const kind of storeKindsFor(env)) {
42931
+ const secret = storeFor(kind, env).get(name);
42932
+ if (secret != null) {
42933
+ result = secret;
42934
+ break;
42935
+ }
42572
42936
  }
42573
- return null;
42937
+ secretCache.set(key, result);
42938
+ return result;
42574
42939
  }
42575
42940
  function deleteSecret(name, env = process.env) {
42576
- for (const store of storesFor(env)) {
42577
- store.delete(name);
42941
+ for (const kind of cleanupKindsFor(env)) {
42942
+ storeFor(kind, env).delete(name);
42578
42943
  }
42944
+ secretCache.set(cacheKey(name, env), null);
42579
42945
  }
42580
42946
 
42581
42947
  // src/auth/oauth.ts
42582
- import { createHash as createHash2, randomBytes } from "crypto";
42948
+ import { createHash as createHash2, randomBytes as randomBytes2 } from "crypto";
42583
42949
 
42584
42950
  // src/auth/callback-server.ts
42585
42951
  import { createServer } from "http";
@@ -43011,15 +43377,15 @@ var CLI_CLIENT_ID = "app_IoPWUwtO8c2gGA";
43011
43377
  var CLI_REDIRECT_URI = "http://localhost:13337/callback";
43012
43378
  var CLI_SCOPES = [...WHOP_SCOPES];
43013
43379
  function generatePKCE() {
43014
- const verifier = randomBytes(32).toString("base64url");
43380
+ const verifier = randomBytes2(32).toString("base64url");
43015
43381
  const challenge = createHash2("sha256").update(verifier).digest("base64url");
43016
43382
  return { verifier, challenge };
43017
43383
  }
43018
43384
  function generateState() {
43019
- return randomBytes(16).toString("base64url");
43385
+ return randomBytes2(16).toString("base64url");
43020
43386
  }
43021
43387
  function generateNonce() {
43022
- return randomBytes(16).toString("base64url");
43388
+ return randomBytes2(16).toString("base64url");
43023
43389
  }
43024
43390
  async function requestToken(params) {
43025
43391
  const res = await whopFetch(`${oauthBaseUrl()}/oauth/token`, {
@@ -48283,6 +48649,52 @@ function render(data) {
48283
48649
  return null;
48284
48650
  }
48285
48651
 
48652
+ // src/lib/shipped-skills.ts
48653
+ import { mkdirSync as mkdirSync5, mkdtempSync as mkdtempSync4, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "fs";
48654
+ import { tmpdir as tmpdir4 } from "os";
48655
+ import { join as join11 } from "path";
48656
+
48657
+ // src/api/shipped-skills.json
48658
+ var shipped_skills_default = {
48659
+ "whop-accounts": '---\nname: whop-accounts\ndescription: "A business on Whop: profile, wallet, capabilities, settings. Run `whop accounts --help` for usage details."\nrequires_bin: whop\ncommand: whop accounts\n---\n\nAn Account represents a person or business on Whop that can have its own profile, wallet, and account-scoped settings. Use accounts for customers, creators, merchants, sellers, or connected businesses your integration supports.\n\nUse the Accounts API to create accounts, list accounts visible to your credentials, retrieve or update an account, and retrieve the account associated with the current API key.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop accounts list` | List Accounts |\n| `whop accounts create` | Create Account |\n| `whop accounts me` | Retrieve Requesting Account |\n| `whop accounts get` | Retrieve Account |\n| `whop accounts update` | Update Account |\n| `whop accounts llc` | Register LLC |\n| `whop accounts preferences` | Retrieve Account Preferences |\n| `whop accounts update-preferences` | Update Account Preferences |\n| `whop accounts recommend_actions` | List Recommended Actions |\n\nRun `whop accounts <command> --help` for options, or `whop accounts <command> --schema` for full argument details.\n',
48660
+ "whop-users": '---\nname: whop-users\ndescription: "A person on Whop: profile and connected identities. Run `whop users --help` for usage details."\nrequires_bin: whop\ncommand: whop users\n---\n\nA User represents a person on Whop. Users have a public profile and can buy products, join accounts, and access experiences.\n\nUse the Users API to search for users, retrieve or update profiles, and check whether a user has access to an account, product, or experience.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop users list` | List Users |\n| `whop users me` | Update Current User |\n| `whop users get` | Retrieve User |\n| `whop users update` | Update User |\n| `whop users access` | Check User Access |\n| `whop users recommend_actions` | List Recommended Actions |\n\nRun `whop users <command> --help` for options, or `whop users <command> --schema` for full argument details.\n',
48661
+ "whop-stats": "---\nname: whop-stats\ndescription: Aggregated financial, audience, and traffic reporting. Run `whop stats --help` for usage details.\nrequires_bin: whop\ncommand: whop stats\n---\n\nStats represent aggregated activity for an account over time. They help you understand revenue, transactions, disputes, members, referrals, and advertising performance across reporting periods like days, weeks, or months.\n\nUse the Stats API to list available metrics and their filterable properties, then retrieve time-series values for a date range.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop stats list` | List Metrics |\n| `whop stats get` | Retrieve Metric |\n\nRun `whop stats <command> --help` for options, or `whop stats <command> --schema` for full argument details.\n",
48662
+ "whop-ledgers": "---\nname: whop-ledgers\ndescription: The activity feed behind an account or user's balance. Run `whop ledgers --help` for usage details.\nrequires_bin: whop\ncommand: whop ledgers\n---\n\nA Ledger Activity row is a single financial event on an account's ledger \u2014 a payment, withdrawal, refund, transfer, on-chain deposit, swap, or card transaction. Each row is derived from the underlying ledger lines and carries a typed `resource` and `source` so you can present and link the event without extra lookups.\n\nUse Ledger Activity to build a statement or transaction feed for an account or user. Reconcile against your own records with `amount` (signed, in the currency's smallest precision units) and `posted_at`, and use `available_at` to know when inflows became withdrawable.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop ledgers list` | List Financial Activity |\n| `whop ledgers report` | Get Financial Report |\n\nRun `whop ledgers <command> --help` for options, or `whop ledgers <command> --schema` for full argument details.\n",
48663
+ "whop-payouts": "---\nname: whop-payouts\ndescription: Send money from a balance to a bank or wallet. Run `whop payouts --help` for usage details.\nrequires_bin: whop\ncommand: whop payouts\n---\n\nPayouts represent money sent from an account or user balance to an external destination, such as a bank account, wallet, or other saved payout method.\n\nUse the Payouts API to create payouts from stablecoin accounts, list payout history for accounts or users, monitor payout statuses, and show expected arrival details for funds leaving Whop.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop payouts list` | List Payouts |\n| `whop payouts create` | Create Payout |\n| `whop payouts methods` | List Payout Methods |\n| `whop payouts create-method` | Create Payout Method |\n\nRun `whop payouts <command> --help` for options, or `whop payouts <command> --schema` for full argument details.\n",
48664
+ "whop-cards": "---\nname: whop-cards\ndescription: Issue cards that spend from a balance. Run `whop cards --help` for usage details.\nrequires_bin: whop\ncommand: whop cards\n---\n\nCards represent Whop-issued virtual payment cards that spend from an account or user balance. Cards can be assigned to cardholders and configured with spending limits for controlled spending.\n\nUse the Cards API to issue cards, list cards for an account or user, and retrieve active card details such as the card number and CVC.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop cards list` | List Cards |\n| `whop cards create` | Create Card |\n| `whop cards get` | Retrieve Card |\n| `whop cards update` | Update Card |\n\nRun `whop cards <command> --help` for options, or `whop cards <command> --schema` for full argument details.\n",
48665
+ "whop-transfers": "---\nname: whop-transfers\ndescription: Move funds between Whop accounts and users. Run `whop transfers --help` for usage details.\nrequires_bin: whop\ncommand: whop transfers\n---\n\nTransfers move value between identities on Whop. They are used for account-to-account money movement, user payouts inside Whop, crypto transfers, and claim links depending on the destination type.\n\nUse the Transfers API to create a transfer, list previous transfers, and retrieve a transfer by ID when reconciling money movement between accounts or users.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop transfers list` | List Transfers |\n| `whop transfers create` | Create Transfer |\n| `whop transfers get` | Retrieve Transfer |\n\nRun `whop transfers <command> --help` for options, or `whop transfers <command> --schema` for full argument details.\n",
48666
+ "whop-deposits": "---\nname: whop-deposits\ndescription: Add funds to a balance. Run `whop deposits --help` for usage details.\nrequires_bin: whop\ncommand: whop deposits\n---\n\nDeposits describe ways to add funds to an account balance, including hosted deposit pages, bank deposit instructions, and supported crypto wallet addresses.\n\nUse the Deposits API to create deposit instructions for an account.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop deposits create` | Create Deposit |\n\nRun `whop deposits <command> --help` for options, or `whop deposits <command> --schema` for full argument details.\n",
48667
+ "whop-swaps": "---\nname: whop-swaps\ndescription: Convert a balance between currencies. Run `whop swaps --help` for usage details.\nrequires_bin: whop\ncommand: whop swaps\n---\n\nSwaps convert value between supported tokens, chains, or wallet destinations for an account. A swap quote describes the expected output, fees, and approval requirements before you create the swap.\n\nUse the Swaps API to quote a conversion, create the swap, list recent swaps, and retrieve status until the transaction completes.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop swaps status` | List Swaps |\n| `whop swaps create` | Create Swap |\n| `whop swaps quote` | Create Swap Quote |\n| `whop swaps get` | Retrieve Swap |\n\nRun `whop swaps <command> --help` for options, or `whop swaps <command> --schema` for full argument details.\n",
48668
+ "whop-verifications": "---\nname: whop-verifications\ndescription: Legal identity required before payouts and card issuing. Run `whop verifications --help` for usage details.\nrequires_bin: whop\ncommand: whop verifications\n---\n\nA Verification represents a legal identity for a person or business. Accounts and users complete verification when Whop needs to confirm who they are before enabling payouts or compliance-sensitive workflows.\n\nUse the Verifications API to start or resume a hosted verification session, check review status, and submit requested details or documents. If `requested_information` contains items, submit answers with [Update Verification](https://docs.whop.com/api-reference/beta/verifications/update-verification).\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop verifications list` | List Verifications |\n| `whop verifications create` | Create Verification |\n| `whop verifications get` | Retrieve Verification |\n| `whop verifications update` | Update Verification |\n\nRun `whop verifications <command> --help` for options, or `whop verifications <command> --schema` for full argument details.\n\n## Steps that finish in the browser\n\nSome commands respond with a URL the user must open in a browser to finish the flow (`authorize_url`, `session_url`, `deposit_url`) \u2014 the CLI cannot complete that step itself. When a response contains one of these fields, or the CLI prints \"Action required: open this link in the user's browser\", open that link in the user's browser for them, tell them what to complete there, then re-run the matching `get`/`list` command to confirm the step finished.\n",
48669
+ "whop-products": "---\nname: whop-products\ndescription: The things you sell. Each owns plans and a store page. Run `whop products --help` for usage details.\nrequires_bin: whop\ncommand: whop products\n---\n\nA Product is a digital good or service sold on Whop. Products may contain plans for pricing and/or experiences for content delivery.\n\nUse the Products API to create products, list products visible to your credentials, retrieve product details, update product metadata or merchandising fields, and delete products that should no longer be sold.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop products list` | List Products |\n| `whop products create` | Create Product |\n| `whop products delete` | Delete Product |\n| `whop products get` | Retrieve Product |\n| `whop products update` | Update Product |\n\nRun `whop products <command> --help` for options, or `whop products <command> --schema` for full argument details.\n",
48670
+ "whop-plans": '---\nname: whop-plans\ndescription: "Pricing for a product: one-time, recurring, trials, stock. Run `whop plans --help` for usage details."\nrequires_bin: whop\ncommand: whop plans\n---\n\nA Plan defines how customers buy a product. It controls pricing, billing cadence, availability, tax behavior, checkout fields, and purchase visibility.\n\nUse the Plans API to create plans for products, list existing plans, retrieve or update plan configuration, calculate tax for checkout, and delete plans that should no longer be offered.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop plans list` | List Plans |\n| `whop plans create` | Create Plan |\n| `whop plans delete` | Delete Plan |\n| `whop plans get` | Retrieve Plan |\n| `whop plans update` | Update Plan |\n| `whop plans calculate_tax` | Calculate Tax |\n\nRun `whop plans <command> --help` for options, or `whop plans <command> --schema` for full argument details.\n',
48671
+ "whop-checkout-configurations": "---\nname: whop-checkout-configurations\ndescription: Turn a plan into a shareable, prefilled checkout link. Run `whop checkout-configurations --help` for usage details.\nrequires_bin: whop\ncommand: whop checkout-configurations\n---\n\nA Checkout Configuration is a reusable checkout link owned by an account. In `payment` mode it sells a specific plan; in `setup` mode it collects and saves payment details without charging. Each configuration can also override which payment methods are accepted and how 3D Secure is enforced for that checkout.\n\nUse the Checkout Configurations API to create checkout links for an existing or inline plan, list configurations for an account, retrieve the configuration behind a checkout URL, and delete links that should no longer be used.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop checkout-configurations list` | List checkout configurations |\n| `whop checkout-configurations create` | Create a checkout configuration |\n| `whop checkout-configurations delete` | Delete a checkout configuration |\n| `whop checkout-configurations get` | Retrieve a checkout configuration |\n\nRun `whop checkout-configurations <command> --help` for options, or `whop checkout-configurations <command> --schema` for full argument details.\n",
48672
+ "whop-partners": "---\nname: whop-partners\ndescription: The users and businesses you referred to Whop, and what you earn from them. Run `whop partners --help` for usage details.\nrequires_bin: whop\ncommand: whop partners\n---\n\nThe Partners API covers your Whop partner activity: the users you referred onto Whop, the businesses you referred and the earnings generated from their processing volume, and the partner leaderboard.\n\nUse it to enroll as a Whop partner, list the users you referred, list your referred businesses and review their earnings, and see the partner leaderboard.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop partners create` | Enroll as a Whop partner |\n| `whop partners list` | List referred businesses |\n| `whop partners get` | Retrieve a referred business |\n| `whop partners earnings` | List referred business earnings |\n| `whop partners leaderboard` | Retrieve the leaderboard |\n| `whop partners referred_users` | List the users the caller referred |\n\nRun `whop partners <command> --help` for options, or `whop partners <command> --schema` for full argument details.\n",
48673
+ "whop-bounties": "---\nname: whop-bounties\ndescription: Paid tasks with reviewed submissions and escrowed rewards. Run `whop bounties --help` for usage details.\nrequires_bin: whop\ncommand: whop bounties\n---\n\nA Bounty is a paid task posted by an account or user. The reward is held in escrow when the bounty publishes, workers submit proof of completed work, and each accepted submission is paid out until every winner slot fills.\n\nUse the Bounties API to create and publish a bounty, list an account's bounties for reporting or dashboards, list the bounties a user can work or has participated in, and retrieve a single bounty by ID.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop bounties list` | List Bounties |\n| `whop bounties create` | Create Bounty |\n| `whop bounties get` | Retrieve Bounty |\n| `whop bounties update` | Update Bounty |\n\nRun `whop bounties <command> --help` for options, or `whop bounties <command> --schema` for full argument details.\n",
48674
+ "whop-bounty-submissions": "---\nname: whop-bounty-submissions\ndescription: Work submitted to a bounty, from attempt to payout. Run `whop bounty-submissions --help` for usage details.\nrequires_bin: whop\ncommand: whop bounty-submissions\n---\n\nA Bounty Submission is one worker's attempt on a bounty. It starts as an in-progress attempt, enters the review queue when proof is submitted, and ends approved (paid from the bounty's escrowed pool) or denied.\n\nUse the Bounty Submissions API to submit proof of completed work to a bounty, list the submissions you authored, and review the submissions on your bounties \u2014 across every bounty or narrowed to one.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop bounty-submissions list` | List Bounty Submissions |\n| `whop bounty-submissions create` | Create Bounty Submission |\n\nRun `whop bounty-submissions <command> --help` for options, or `whop bounty-submissions <command> --schema` for full argument details.\n",
48675
+ "whop-people": "---\nname: whop-people\ndescription: Visitors and customers of an account, aggregated from pixel events. Run `whop people --help` for usage details.\nrequires_bin: whop\ncommand: whop people\n---\n\nA Person represents a visitor or customer of an account, assembled from [pixel events](https://docs.whop.com/api-reference/beta/events/event) and purchase activity \u2014 ad clicks, storefront visits, and checkouts.\n\nUse the People API to list the people of an account and retrieve a single person.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop people list` | List People |\n| `whop people get` | Retrieve Person |\n\nRun `whop people <command> --help` for options, or `whop people <command> --schema` for full argument details.\n",
48676
+ "whop-events": "---\nname: whop-events\ndescription: Conversion and engagement events tracked for attribution. Run `whop events --help` for usage details.\nrequires_bin: whop\ncommand: whop events\n---\n\nAn Event records conversion or engagement activity for an account, such as page views, purchases, or leads. Each event ties the action to the [person](https://docs.whop.com/api-reference/beta/people/person) who took it, so activity can be attributed to the ads and links that drove it.\n\nUse the Events API to send new tracking events, list recent identity-linked events for an account, and inspect the events recorded for a person.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop events list` | List Events |\n| `whop events create` | Create Event |\n\nRun `whop events <command> --help` for options, or `whop events <command> --schema` for full argument details.\n",
48677
+ "whop-ads": '---\nname: whop-ads\ndescription: "The creative: copy, assets, and destination URL. Run `whop ads --help` for usage details."\nrequires_bin: whop\ncommand: whop ads\n---\n\nAn Ad is the individual creative unit delivered by an [ad group](https://docs.whop.com/api-reference/beta/ad-groups/ad-group). It holds the copy, creative assets, and destination URL for one ad.\n\nUse the Ads API to list ads for an account, create ads inside ad groups, retrieve or update creative details, delete ads that should stop running, and pause or resume delivery.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop ads list` | List Ads |\n| `whop ads create` | Create an Ad |\n| `whop ads delete` | Delete an Ad |\n| `whop ads get` | Retrieve an Ad |\n| `whop ads update` | Update an Ad |\n| `whop ads pause` | Pause an Ad |\n| `whop ads unpause` | Unpause an Ad |\n\nRun `whop ads <command> --help` for options, or `whop ads <command> --schema` for full argument details.\n\n## Launch playbook \u2014 from nothing to a live ad\n\nThree commands take you from nothing to a launchable ad: generate a creative, create the campaign + ad group + ad in one request, then flip the campaign to active. Structured flags (`--ad_group`, `--creatives`, `--ads_payment_methods`) take JSON strings.\n\n### One-time setup\n\n1. **Auth** \u2014 `whop login` (OAuth). First-time billing setup requires a user login; an API key can only reorder already-configured payment methods. If a command fails with a scope error saying your login predates the scope, run `whop login` again.\n2. **Facebook page** \u2014 `whop social-accounts list` must show a `"platform": "facebook"` entry. Three ways to get one:\n - **Already connected** \u2014 use its `sacc_` id as-is.\n - **Link a Meta Business account** \u2014 `whop social-accounts connect --platform meta_business --scopes \'["advertise"]\' --redirect_url <url>`, then send the user to the returned `authorize_url`.\n - **No page at all** \u2014 have Whop create one for the account: `whop social-accounts create --platform facebook`.\n3. **Ads payment method** \u2014 check with `whop accounts preferences <account_id>` (your `biz_` ID, from `whop accounts me`). If `ads_payment_methods` is null, configure balance billing:\n\n ```sh\n whop accounts update-preferences <account_id> --ads_payment_methods \'{"primary": {"type": "platform_balance"}}\'\n ```\n\n Only launching needs this \u2014 drafts work without. Fund the balance with `whop deposits create --amount 50` (returns a hosted deposit page URL).\n\n### 1. Generate a creative\n\n```sh\nwhop media generate --type image --prompt "A running club jogging across a bridge at sunrise, warm light" --wait\n```\n\n`--wait` blocks until the asset is terminal and returns `file.id` \u2014 use that as the creative. Billed from the balance (`amount_charged`); a failed generation auto-refunds, so adjust the prompt and retry. Video: `--type video` plus optional `--duration_seconds` (5/10/15), `--resolution` (480p\u20134k), and up to 4 `--reference_media` file IDs (first one seeds the opening frame).\n\n### 2. Create the whole tree as a draft \u2014 one request\n\n```sh\nwhop ads create \\\n --title "Run club launch ad" \\\n --primary_texts "Join 10,000 runners chasing their next PR together." \\\n --headlines "Find your stride" \\\n --call_to_action sign_up \\\n --url "https://whop.com/your-store-page" \\\n --creatives \'[{"id": "file_XXXXXXXX"}]\' \\\n --social_accounts \'[{"id": "sacc_XXXXXXXX"}]\' \\\n --ad_group \'{\n "title": "US broad",\n "conversion_location": "website",\n "regions": {"include": {"countries": ["US"]}},\n "ad_campaign": {"title": "Run club growth", "platform": "meta", "objective": "sales", "status": "draft", "budget_amount": 25, "budget_optimization": "ad_campaign"}\n }\'\n```\n\nField rules:\n\n| Field | Rule |\n|-------|------|\n| `creatives` | One entry with no `format` is required (the base asset). `square`/`vertical`/`horizontal` are optional crops on top. |\n| `url` | Required for website ads. A whop.com store page works as-is; an external page needs the Whop pixel installed. |\n| Budget | Default to CBO: `budget_amount` on the campaign with `budget_optimization: "ad_campaign"` (the network shifts spend to the best ad group). Per-ad-group `budget_amount` (ABO) is the manual alternative. One level owns it \u2014 never both. |\n| Targeting | Omit `demographics`/`placements`/`devices` for automatic optimization. `regions` uses ISO 3166 (`"US"`, `"US-CA"`). |\n| `lead_form` | Only with an instant-form `conversion_location`. |\n\nReuse existing containers by passing `--ad_group_id adgrp_x` instead of `--ad_group`, or `"ad_campaign_id": "adcamp_x"` inside `--ad_group` instead of the inline `ad_campaign`.\n\n### 3. Launch\n\n`"status": "draft"` above kept money out of it. Review, then launch \u2014 this is when spend starts and the payment method is enforced:\n\n```sh\nwhop ad-campaigns update adcamp_XXXXXXXX --status active\n```\n\n(Ready to spend immediately? Omit `"status": "draft"` and the one-shot create launches directly.)\n\n### 4. Monitor\n\n```sh\nwhop ads get ad_XXXXXXXX\n```\n\n`delivery_status` is the live state (a brief `in_review` for moderation is normal); `issues[]` carries a human-readable `message` for anything the network rejected asynchronously. Control delivery with `pause`/`unpause` on ads, ad groups, or campaigns. Edit copy or creatives with `whop ads update` \u2014 sending `creatives` replaces the whole set, so include the base entry.\n',
48678
+ "whop-ad-campaigns": "---\nname: whop-ad-campaigns\ndescription: Platform, objective, and budget for a set of ads. Run `whop ad-campaigns --help` for usage details.\nrequires_bin: whop\ncommand: whop ad-campaigns\n---\n\nAn Ad Campaign is the top-level container for paid ads on an ad network. It sets the platform, objective, and budget strategy shared by its [ad groups](https://docs.whop.com/api-reference/beta/ad-groups/ad-group) and ads.\n\nUse the Ad Campaigns API to create campaigns, list campaigns for an account, retrieve or update campaign settings, and pause or resume campaign delivery.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop ad-campaigns list` | List Ad Campaigns |\n| `whop ad-campaigns create` | Create an Ad Campaign |\n| `whop ad-campaigns delete` | Delete an Ad Campaign |\n| `whop ad-campaigns get` | Retrieve an Ad Campaign |\n| `whop ad-campaigns update` | Update an Ad Campaign |\n| `whop ad-campaigns pause` | Pause an Ad Campaign |\n| `whop ad-campaigns retry_payment` | Retry a Failed Ad Campaign Payment |\n| `whop ad-campaigns unpause` | Unpause an Ad Campaign |\n\nRun `whop ad-campaigns <command> --help` for options, or `whop ad-campaigns <command> --schema` for full argument details.\n",
48679
+ "whop-ad-groups": "---\nname: whop-ad-groups\ndescription: Audience, placements, and schedule within a campaign. Run `whop ad-groups --help` for usage details.\nrequires_bin: whop\ncommand: whop ad-groups\n---\n\nAn Ad Group sits inside an [ad campaign](https://docs.whop.com/api-reference/beta/ad-campaigns/ad-campaign) and controls delivery for [ads](https://docs.whop.com/api-reference/beta/ads/ad). It sets the audience, placements, schedule, budget, and optimization goal for its ads.\n\nUse the Ad Groups API to create ad groups in campaigns, list or retrieve targeting and delivery settings, update budgets or targeting, delete groups that should stop running, and pause or resume delivery. It can also search the ad platform's targeting taxonomy for options to target and estimate how many people a draft targeting spec can reach.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop ad-groups list` | List Ad Groups |\n| `whop ad-groups create` | Create an Ad Group |\n| `whop ad-groups estimate_reach` | Estimate Ad Group Reach |\n| `whop ad-groups targeting_options` | Search Targeting Options |\n| `whop ad-groups delete` | Delete an Ad Group |\n| `whop ad-groups get` | Retrieve an Ad Group |\n| `whop ad-groups update` | Update an Ad Group |\n| `whop ad-groups pause` | Pause an Ad Group |\n| `whop ad-groups unpause` | Unpause an Ad Group |\n\nRun `whop ad-groups <command> --help` for options, or `whop ad-groups <command> --schema` for full argument details.\n",
48680
+ "whop-audiences": "---\nname: whop-audiences\ndescription: Reusable targeting lists for ad groups. Run `whop audiences --help` for usage details.\nrequires_bin: whop\ncommand: whop audiences\n---\n\nAn Audience represents a customer list uploaded to Whop for ad targeting. Audiences belong to an account and sync to supported ad platforms as custom audiences.\n\nUse the Audiences API to create audiences from CSV uploads, monitor processing status, and list or delete audiences for an account. Created audiences are usable for targeting after processing reaches `ready` or `partial`.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop audiences list` | List Audiences |\n| `whop audiences create` | Create Audience |\n| `whop audiences delete` | Delete Audience |\n\nRun `whop audiences <command> --help` for options, or `whop audiences <command> --schema` for full argument details.\n",
48681
+ "whop-media": "---\nname: whop-media\ndescription: AI-generated assets, billed from a balance, attachable wherever files are accepted. Run `whop media --help` for usage details.\nrequires_bin: whop\ncommand: whop media\n---\n\nA Media Asset is an AI-generated image or video created from a prompt and billed from an account balance. When generation finishes, the asset includes a file that can be attached anywhere Whop accepts files.\n\nUse the Media API to start a generation job and retrieve the asset while it processes or after it is ready.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop media generate` | Generate Media Asset |\n| `whop media get` | Retrieve Media Asset |\n\nRun `whop media <command> --help` for options, or `whop media <command> --schema` for full argument details.\n\n## Steps that finish in the browser\n\nSome commands respond with a URL the user must open in a browser to finish the flow (`authorize_url`, `session_url`, `deposit_url`) \u2014 the CLI cannot complete that step itself. When a response contains one of these fields, or the CLI prints \"Action required: open this link in the user's browser\", open that link in the user's browser for them, tell them what to complete there, then re-run the matching `get`/`list` command to confirm the step finished.\n",
48682
+ "whop-social-accounts": "---\nname: whop-social-accounts\ndescription: Connected Facebook and Instagram accounts that run ads. Run `whop social-accounts --help` for usage details.\nrequires_bin: whop\ncommand: whop social-accounts\n---\n\nA Social Account represents an external profile connected to a Whop account or user, such as a Facebook page or Instagram account. Connecting a social account lets Whop run [ads](https://docs.whop.com/api-reference/beta/ads/ad) under that profile's identity and promote its existing posts.\n\nUse the Social Accounts API to list connected accounts, create a Whop-managed Facebook page, start an OAuth connection, disconnect a social account, and list a connected profile's posts or a Facebook page's lead forms.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop social-accounts list` | List Social Accounts |\n| `whop social-accounts create` | Create a Social Account |\n| `whop social-accounts connect` | Connect a Social Account |\n| `whop social-accounts delete` | Delete a Social Account |\n| `whop social-accounts lead_forms` | List Social Account Lead Forms |\n| `whop social-accounts posts` | List Social Account Posts |\n\nRun `whop social-accounts <command> --help` for options, or `whop social-accounts <command> --schema` for full argument details.\n\n## Steps that finish in the browser\n\nSome commands respond with a URL the user must open in a browser to finish the flow (`authorize_url`, `session_url`, `deposit_url`) \u2014 the CLI cannot complete that step itself. When a response contains one of these fields, or the CLI prints \"Action required: open this link in the user's browser\", open that link in the user's browser for them, tell them what to complete there, then re-run the matching `get`/`list` command to confirm the step finished.\n",
48683
+ "whop-apps": '---\nname: whop-apps\ndescription: "Apps you build on Whop: metadata, hosted builds, runtime logs. Run `whop apps --help` for usage details."\nrequires_bin: whop\ncommand: whop apps\n---\n\nAn App is software you build on Whop. It can be a hosted web app served at `<route>.whop.app` or an API integration installed as an experience, and it belongs to the account that owns its credentials, settings, builds, and runtime logs.\n\nUse the Apps API to manage app configuration and, for hosted apps, read server runtime logs for console output, uncaught exceptions, and failed requests. Logs are retained for 7 days and can be filtered by build, level, time window, and message text.\n\n## Commands\n\n| Command | Description |\n|---------|-------------|\n| `whop apps logs` | List App Logs |\n\nRun `whop apps <command> --help` for options, or `whop apps <command> --schema` for full argument details.\n'
48684
+ };
48685
+
48686
+ // src/lib/shipped-skills.ts
48687
+ function materializeShippedSkills() {
48688
+ const root = mkdtempSync4(join11(tmpdir4(), "whop-cli-skills-"));
48689
+ for (const [name, content] of Object.entries(shipped_skills_default)) {
48690
+ const dir = join11(root, name);
48691
+ mkdirSync5(dir);
48692
+ writeFileSync5(join11(dir, "SKILL.md"), content);
48693
+ }
48694
+ process.on("exit", () => rmSync5(root, { recursive: true, force: true }));
48695
+ return root;
48696
+ }
48697
+
48286
48698
  // src/lib/update/check.ts
48287
48699
  import fs6 from "fs";
48288
48700
  import path6 from "path";
@@ -48755,6 +49167,7 @@ async function runUpgrade(c2, env = process.env) {
48755
49167
  }
48756
49168
 
48757
49169
  // src/cli.ts
49170
+ var shippedSkillsDir = process.argv.includes("skills") && !process.argv.includes("--no-global") ? materializeShippedSkills() : void 0;
48758
49171
  var cli = Cli_exports.create("whop", {
48759
49172
  version: package_default.version,
48760
49173
  description: "Build and manage Whop apps from your terminal.",
@@ -48762,9 +49175,12 @@ var cli = Cli_exports.create("whop", {
48762
49175
  sync: {
48763
49176
  // Shipped skill files generated by scripts/sync-spec.ts from the
48764
49177
  // spec's own tag copy (x-whop-summary + description, authored in
48765
- // backend/openapi/v1/tags.yml). A matching directory name overrides
48766
- // the auto-generated skill for that command group.
48767
- include: ["skills/*"],
49178
+ // backend/openapi/v1/tags.yml), bundled into the build and written to
49179
+ // a temp dir at runtime so standalone binaries and npx runs get them
49180
+ // too. A matching directory name overrides the auto-generated skill
49181
+ // for that command group.
49182
+ cwd: shippedSkillsDir,
49183
+ include: shippedSkillsDir ? ["*"] : ["skills/*"],
48768
49184
  suggestions: [
48769
49185
  "choose or create my Whop business account",
48770
49186
  "show my Whop business accounts",