@agent-native/core 0.51.6 → 0.51.8

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.
Files changed (35) hide show
  1. package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
  2. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  3. package/dist/cli/pr-visual-recap-workflow.js +1 -1
  4. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  5. package/dist/cli/skills.d.ts +13 -0
  6. package/dist/cli/skills.d.ts.map +1 -1
  7. package/dist/cli/skills.js +255 -24
  8. package/dist/cli/skills.js.map +1 -1
  9. package/dist/client/assistant-ui-recovery.d.ts.map +1 -1
  10. package/dist/client/assistant-ui-recovery.js +15 -12
  11. package/dist/client/assistant-ui-recovery.js.map +1 -1
  12. package/dist/provider-api/corpus-jobs-store.d.ts +95 -0
  13. package/dist/provider-api/corpus-jobs-store.d.ts.map +1 -0
  14. package/dist/provider-api/corpus-jobs-store.js +394 -0
  15. package/dist/provider-api/corpus-jobs-store.js.map +1 -0
  16. package/dist/provider-api/corpus-jobs.d.ts +146 -0
  17. package/dist/provider-api/corpus-jobs.d.ts.map +1 -0
  18. package/dist/provider-api/corpus-jobs.js +1192 -0
  19. package/dist/provider-api/corpus-jobs.js.map +1 -0
  20. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  21. package/dist/server/agent-chat-plugin.js +9 -2
  22. package/dist/server/agent-chat-plugin.js.map +1 -1
  23. package/docs/content/template-analytics.md +0 -8
  24. package/docs/content/template-assets.md +0 -6
  25. package/docs/content/template-brain.md +0 -8
  26. package/docs/content/template-calendar.md +0 -8
  27. package/docs/content/template-clips.md +0 -8
  28. package/docs/content/template-content.md +0 -14
  29. package/docs/content/template-design.md +0 -6
  30. package/docs/content/template-forms.md +0 -10
  31. package/docs/content/template-mail.md +0 -8
  32. package/docs/content/template-plan.md +180 -0
  33. package/docs/content/template-slides.md +0 -8
  34. package/docs/content/template-videos.md +0 -8
  35. package/package.json +3 -1
@@ -21,7 +21,7 @@ Usage:
21
21
  npx @agent-native/core@latest skills list
22
22
  npx @agent-native/core@latest skills status [assets|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|all] [--scope user|project] [--json]
23
23
  npx @agent-native/core@latest skills update [assets|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|all] [--scope user|project] [--dry-run] [--json]
24
- npx @agent-native/core@latest skills add assets|design-exploration|visual-plan|visual-recap|context-xray [--client codex|claude-code|claude-code-cli|cowork|all] [--scope user|project] [--mcp-url <url>] [--no-connect] [--with-github-action] [--yes] [--dry-run] [--json]
24
+ npx @agent-native/core@latest skills add assets|design-exploration|visual-plan|visual-recap|context-xray [--client codex|claude-code|claude-code-cli|cowork|all] [--scope user|project] [--mode hosted|local-files|self-hosted] [--mcp-url <url>] [--no-connect] [--with-github-action] [--yes] [--dry-run] [--json]
25
25
  npx @agent-native/core@latest skills add <manifest-or-app-dir|skill-repo> [--skill <name>] [--client ...] [--yes]
26
26
 
27
27
  Examples:
@@ -30,6 +30,8 @@ Examples:
30
30
  npx @agent-native/core@latest skills add visual-plan
31
31
  npx @agent-native/core@latest skills add visual-recap
32
32
  npx @agent-native/core@latest skills add visual-recap --with-github-action
33
+ npx @agent-native/core@latest skills add visual-plan --mode local-files
34
+ npx @agent-native/core@latest skills add visual-plan --mode self-hosted --mcp-url https://my-plan-app.example.com
33
35
  npx @agent-native/core@latest skills status visual-plan
34
36
  npx @agent-native/core@latest skills update visual-plan
35
37
  npx @agent-native/core@latest skills add visual-plan --no-connect
@@ -59,6 +61,12 @@ deployment) instead of the built-in hosted default — a bare origin gets the
59
61
  standard /_agent-native/mcp path appended. Use app-skill pack for marketplace
60
62
  bundles and custom adapter output.
61
63
 
64
+ When installing visual-plan or visual-recap interactively, the CLI asks where
65
+ plans and recaps should live: hosted Plans for shareable links/comments, local
66
+ files for "No sharing, all local.", or a self-hosted/custom Plan app URL.
67
+ Pass --mode to choose directly. Local-files mode skips MCP registration and
68
+ auth and installs instructions that default to MDX folders plus local preview.
69
+
62
70
  When installing visual-recap interactively, the CLI offers to add the optional PR
63
71
  Visual Recap GitHub Action. Pass --with-github-action to write it directly, then
64
72
  run "npx @agent-native/core@latest recap setup" / "npx @agent-native/core@latest recap doctor" to configure and
@@ -2244,12 +2252,60 @@ function stableSkillHash(files) {
2244
2252
  }
2245
2253
  return hash.digest("hex").slice(0, 16);
2246
2254
  }
2247
- function skillFilesForBuiltIn(appSkillId) {
2255
+ function insertAfterFrontmatter(markdown, block) {
2256
+ if (!block.trim())
2257
+ return markdown;
2258
+ const match = markdown.match(/^---\n[\s\S]*?\n---\n/);
2259
+ if (!match)
2260
+ return `${block}\n\n${markdown}`;
2261
+ return `${match[0]}\n${block.trim()}\n\n${markdown.slice(match[0].length)}`;
2262
+ }
2263
+ function planModeInstructionBlock(input) {
2264
+ if (input.mode === "local-files") {
2265
+ return `## Installed Mode
2266
+
2267
+ Default storage for this installation: local files. Create and update plans and
2268
+ recaps as MDX folders under \`plans/<slug>/\`, run
2269
+ \`npx @agent-native/core@latest plan local preview --dir plans/<slug> --kind plan|recap\`,
2270
+ and report the local preview URL or path. No sharing, all local. Use a hosted
2271
+ or self-hosted Plan MCP connector only if the user explicitly asks to publish or
2272
+ share.`;
2273
+ }
2274
+ if (input.mode === "self-hosted") {
2275
+ return `## Installed Mode
2276
+
2277
+ Default storage for this installation: the configured self-hosted/custom Plan
2278
+ app${input.mcpUrl ? ` at \`${input.mcpUrl}\`` : ""}. Use that Plan MCP connector
2279
+ for plans and recaps instead of assuming \`https://plan.agent-native.com\`.`;
2280
+ }
2281
+ return "";
2282
+ }
2283
+ function applyPlanModeToSkillMarkdown(markdown, input) {
2284
+ if (input.appSkillId !== "visual-plans")
2285
+ return markdown;
2286
+ const block = planModeInstructionBlock({
2287
+ mode: input.mode,
2288
+ mcpUrl: input.mcpUrl,
2289
+ });
2290
+ return insertAfterFrontmatter(markdown, block);
2291
+ }
2292
+ function skillFilesForBuiltIn(appSkillId, options = {}) {
2248
2293
  const entry = BUILT_IN_APP_SKILLS[appSkillId];
2249
2294
  const skills = {
2250
- [entry.skillName]: entry.skillMarkdown,
2295
+ [entry.skillName]: applyPlanModeToSkillMarkdown(entry.skillMarkdown, {
2296
+ appSkillId,
2297
+ mode: options.planMode,
2298
+ mcpUrl: options.mcpUrl,
2299
+ }),
2251
2300
  ...builtInExtraSkills(entry),
2252
2301
  };
2302
+ for (const [skillName, skillMarkdown] of Object.entries(builtInExtraSkills(entry))) {
2303
+ skills[skillName] = applyPlanModeToSkillMarkdown(skillMarkdown, {
2304
+ appSkillId,
2305
+ mode: options.planMode,
2306
+ mcpUrl: options.mcpUrl,
2307
+ });
2308
+ }
2253
2309
  const extraFiles = builtInExtraFiles(entry);
2254
2310
  const out = {};
2255
2311
  for (const [skillName, skillMarkdown] of Object.entries(skills)) {
@@ -2261,11 +2317,12 @@ function skillFilesForBuiltIn(appSkillId) {
2261
2317
  appSkillId,
2262
2318
  displayName: entry.manifest.displayName,
2263
2319
  skillName,
2264
- mcpUrl: isLocalOnlyBuiltInSkill(entry)
2320
+ mcpUrl: isLocalOnlyBuiltInSkill(entry) || options.planMode === "local-files"
2265
2321
  ? ""
2266
- : entry.manifest.hosted.mcpUrl,
2322
+ : (options.mcpUrl ?? entry.manifest.hosted.mcpUrl),
2267
2323
  files,
2268
2324
  contentHash: stableSkillHash(files),
2325
+ planMode: options.planMode,
2269
2326
  };
2270
2327
  }
2271
2328
  return out;
@@ -2295,6 +2352,7 @@ function writeSkillFolder(dir, bundle, installedAt = new Date().toISOString()) {
2295
2352
  mcpUrl: bundle.mcpUrl,
2296
2353
  installedAt,
2297
2354
  updateCommand: `npx @agent-native/core@latest skills update ${bundle.skillName}`,
2355
+ ...(bundle.planMode ? { planMode: bundle.planMode } : {}),
2298
2356
  };
2299
2357
  fs.writeFileSync(path.join(dir, AGENT_NATIVE_SKILL_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}\n`, "utf-8");
2300
2358
  }
@@ -2324,7 +2382,10 @@ function builtInSkillsRootForAgent(agent, scope, baseDir) {
2324
2382
  * (which would have to be published to npm first). Returns the written folders.
2325
2383
  */
2326
2384
  function installBuiltInInstructions(input) {
2327
- const bundles = Object.values(skillFilesForBuiltIn(input.appSkillId)).filter((bundle) => !input.onlySkillNames || input.onlySkillNames.includes(bundle.skillName));
2385
+ const bundles = Object.values(skillFilesForBuiltIn(input.appSkillId, {
2386
+ planMode: input.planMode,
2387
+ mcpUrl: input.mcpUrl,
2388
+ })).filter((bundle) => !input.onlySkillNames || input.onlySkillNames.includes(bundle.skillName));
2328
2389
  const written = [];
2329
2390
  for (const agent of input.skillsAgents) {
2330
2391
  const root = builtInSkillsRootForAgent(agent, input.scope, input.baseDir);
@@ -2438,7 +2499,7 @@ function clientFilterForStatus(parsed) {
2438
2499
  }
2439
2500
  function collectSkillInstallStates(parsed, options) {
2440
2501
  const appSkillIds = targetIdsForStatus(parsed);
2441
- const latest = latestSkillBundlesForTargets(appSkillIds);
2502
+ const defaultLatest = latestSkillBundlesForTargets(appSkillIds);
2442
2503
  const roots = skillSearchRoots({
2443
2504
  baseDir: options.baseDir ?? process.cwd(),
2444
2505
  clients: clientFilterForStatus(parsed),
@@ -2447,7 +2508,7 @@ function collectSkillInstallStates(parsed, options) {
2447
2508
  const states = [];
2448
2509
  const seenDirs = new Set();
2449
2510
  for (const root of roots) {
2450
- for (const bundle of Object.values(latest)) {
2511
+ for (const bundle of Object.values(defaultLatest)) {
2451
2512
  const dir = path.join(root.root, bundle.skillName);
2452
2513
  const resolvedDir = path.resolve(dir);
2453
2514
  if (seenDirs.has(resolvedDir) || !fs.existsSync(dir))
@@ -2456,35 +2517,41 @@ function collectSkillInstallStates(parsed, options) {
2456
2517
  continue;
2457
2518
  seenDirs.add(resolvedDir);
2458
2519
  const files = listSkillFolderFiles(dir);
2459
- const installedHash = Object.keys(files).length > 0 ? stableSkillHash(files) : null;
2460
2520
  const metadata = readSkillInstallMetadata(dir);
2521
+ const stateBundle = skillFilesForBuiltIn(bundle.appSkillId, {
2522
+ planMode: metadata?.planMode,
2523
+ mcpUrl: metadata?.mcpUrl,
2524
+ })[bundle.skillName] ?? bundle;
2525
+ const installedHash = Object.keys(files).length > 0 ? stableSkillHash(files) : null;
2461
2526
  states.push({
2462
- appSkillId: bundle.appSkillId,
2463
- displayName: bundle.displayName,
2464
- skillName: bundle.skillName,
2527
+ appSkillId: stateBundle.appSkillId,
2528
+ displayName: stateBundle.displayName,
2529
+ skillName: stateBundle.skillName,
2465
2530
  path: dir,
2466
2531
  root: root.root,
2467
2532
  scope: root.scope,
2468
2533
  client: root.client,
2469
- latestHash: bundle.contentHash,
2534
+ latestHash: stateBundle.contentHash,
2470
2535
  installedHash,
2471
2536
  metadataHash: metadata?.contentHash,
2472
- current: installedHash === bundle.contentHash,
2537
+ current: installedHash === stateBundle.contentHash,
2473
2538
  managed: metadata?.source === "agent-native",
2539
+ planMode: metadata?.planMode,
2540
+ mcpUrl: metadata?.mcpUrl,
2474
2541
  });
2475
2542
  }
2476
2543
  }
2477
2544
  return states.sort((a, b) => `${a.skillName}:${a.path}`.localeCompare(`${b.skillName}:${b.path}`));
2478
2545
  }
2479
2546
  function updateSkillInstallStates(states, dryRun) {
2480
- const latest = latestSkillBundlesForTargets([
2481
- ...new Set(states.map((state) => state.appSkillId)),
2482
- ]);
2483
2547
  const updated = [];
2484
2548
  for (const state of states) {
2485
2549
  if (state.current && state.managed)
2486
2550
  continue;
2487
- const bundle = latest[state.skillName];
2551
+ const bundle = skillFilesForBuiltIn(state.appSkillId, {
2552
+ planMode: state.planMode,
2553
+ mcpUrl: state.mcpUrl,
2554
+ })[state.skillName];
2488
2555
  if (!bundle)
2489
2556
  continue;
2490
2557
  if (!dryRun)
@@ -2622,6 +2689,56 @@ async function promptForScope(context) {
2622
2689
  }
2623
2690
  return result === "project" ? "project" : "user";
2624
2691
  }
2692
+ async function promptForPlanMode(context) {
2693
+ const clack = await import("@clack/prompts");
2694
+ const result = await clack.select({
2695
+ message: "Where should visual plans and recaps live?",
2696
+ options: [
2697
+ {
2698
+ value: "hosted",
2699
+ label: "Hosted Plans, shareable links",
2700
+ hint: "Stores plans at plan.agent-native.com. Enables sharing, comments, browser editor. Requires one-time browser sign-in.",
2701
+ },
2702
+ {
2703
+ value: "local-files",
2704
+ label: "Local files only",
2705
+ hint: "Writes plans/<name>/plan.mdx in this repo and opens a local preview. No sharing, all local.",
2706
+ },
2707
+ {
2708
+ value: "self-hosted",
2709
+ label: "Self-hosted/custom URL",
2710
+ hint: "Connect to your own Plan app or local dev tunnel.",
2711
+ },
2712
+ ],
2713
+ initialValue: context.initialMode,
2714
+ });
2715
+ if (clack.isCancel(result)) {
2716
+ clack.cancel("Cancelled.");
2717
+ return null;
2718
+ }
2719
+ return normalizePlanInstallMode(String(result));
2720
+ }
2721
+ async function promptForPlanMcpUrl() {
2722
+ const clack = await import("@clack/prompts");
2723
+ const result = await clack.text({
2724
+ message: "Plan app URL or MCP URL",
2725
+ placeholder: "https://my-plan-app.example.com",
2726
+ validate(value) {
2727
+ try {
2728
+ resolveMcpUrlOverride(value);
2729
+ return undefined;
2730
+ }
2731
+ catch (err) {
2732
+ return err?.message ?? "Enter a valid http:// or https:// URL.";
2733
+ }
2734
+ },
2735
+ });
2736
+ if (clack.isCancel(result)) {
2737
+ clack.cancel("Cancelled.");
2738
+ return null;
2739
+ }
2740
+ return String(result).trim();
2741
+ }
2625
2742
  async function promptForSkills(context) {
2626
2743
  const clack = await import("@clack/prompts");
2627
2744
  const result = await clack.multiselect({
@@ -2659,6 +2776,30 @@ async function resolveSkillsClients(parsed, options) {
2659
2776
  }
2660
2777
  return selected;
2661
2778
  }
2779
+ function normalizePlanInstallMode(value) {
2780
+ const normalized = value?.trim().toLowerCase();
2781
+ if (!normalized || normalized === "hosted")
2782
+ return "hosted";
2783
+ if (normalized === "local" ||
2784
+ normalized === "local-file" ||
2785
+ normalized === "local-files" ||
2786
+ normalized === "files") {
2787
+ return "local-files";
2788
+ }
2789
+ if (normalized === "self-hosted" ||
2790
+ normalized === "selfhosted" ||
2791
+ normalized === "custom" ||
2792
+ normalized === "custom-url") {
2793
+ return "self-hosted";
2794
+ }
2795
+ throw new Error('--mode must be one of "hosted", "local-files", or "self-hosted".');
2796
+ }
2797
+ function targetIncludesPlans(target) {
2798
+ return normalizeKnownSkillTarget(target) === "visual-plans";
2799
+ }
2800
+ function targetsIncludePlans(targets) {
2801
+ return targets.some(targetIncludesPlans);
2802
+ }
2662
2803
  async function resolveSkillTargets(parsed, options) {
2663
2804
  if (parsed.target || !shouldPrompt(parsed, options)) {
2664
2805
  return [parsed.target ?? "assets"];
@@ -2755,6 +2896,14 @@ export function parseSkillsArgs(argv) {
2755
2896
  }
2756
2897
  else if ((value = eat("--mcp-url")) !== undefined)
2757
2898
  out.mcpUrl = value;
2899
+ else if ((value = eat("--mode")) !== undefined)
2900
+ out.planMode = normalizePlanInstallMode(value);
2901
+ else if (arg === "--hosted")
2902
+ out.planMode = "hosted";
2903
+ else if (arg === "--local" || arg === "--local-files")
2904
+ out.planMode = "local-files";
2905
+ else if (arg === "--self-hosted" || arg === "--custom-url")
2906
+ out.planMode = "self-hosted";
2758
2907
  else if (arg === "--yes" || arg === "-y")
2759
2908
  out.yes = true;
2760
2909
  else if (arg === "--dry-run")
@@ -2785,6 +2934,9 @@ export function parseSkillsArgs(argv) {
2785
2934
  if (out.scope !== "user" && out.scope !== "project") {
2786
2935
  throw new Error("--scope must be either user or project.");
2787
2936
  }
2937
+ if (out.planMode === "local-files" && out.mcpUrl) {
2938
+ throw new Error("--mode local-files cannot be combined with --mcp-url.");
2939
+ }
2788
2940
  return out;
2789
2941
  }
2790
2942
  function loadSkillTarget(target, onlySkillNames) {
@@ -2898,6 +3050,8 @@ function dryRunInstallCommand(parsed, target) {
2898
3050
  "--scope",
2899
3051
  parsed.scope,
2900
3052
  ];
3053
+ if (parsed.planMode)
3054
+ args.push("--mode", parsed.planMode);
2901
3055
  if (parsed.mcpUrl)
2902
3056
  args.push("--mcp-url", parsed.mcpUrl);
2903
3057
  if (parsed.instructions && !parsed.mcp)
@@ -3159,6 +3313,20 @@ async function connectAfterEnsure(installTarget, clients, parsed, options) {
3159
3313
  export async function addAgentNativeSkill(parsed, options = {}) {
3160
3314
  const target = parsed.target ?? "assets";
3161
3315
  const knownTarget = normalizeKnownSkillTarget(target);
3316
+ const planMode = knownTarget === "visual-plans"
3317
+ ? (parsed.planMode ?? (parsed.mcpUrl ? "self-hosted" : "hosted"))
3318
+ : undefined;
3319
+ if (parsed.planMode && knownTarget !== "visual-plans") {
3320
+ throw new Error("--mode only applies to visual-plan / visual-recap.");
3321
+ }
3322
+ if (planMode === "local-files" && parsed.mcpUrl) {
3323
+ throw new Error("--mode local-files cannot be combined with --mcp-url.");
3324
+ }
3325
+ if (planMode === "self-hosted" && !parsed.mcpUrl) {
3326
+ throw new Error("--mode self-hosted requires --mcp-url <url>.");
3327
+ }
3328
+ const shouldRegisterMcp = parsed.mcp &&
3329
+ !(knownTarget === "visual-plans" && planMode === "local-files");
3162
3330
  // For multi-skill bundles (the plan bundle), a single-skill target installs
3163
3331
  // only that skill. `installsRecap` controls the PR Visual Recap github-action
3164
3332
  // offer, which is only relevant when the recap skill is part of the install.
@@ -3258,12 +3426,15 @@ export async function addAgentNativeSkill(parsed, options = {}) {
3258
3426
  displayName: installTarget.displayName,
3259
3427
  skillNames: installTarget.skillNames,
3260
3428
  skillsAgents,
3261
- mcpUrl: installTarget.loaded.manifest.hosted.mcpUrl,
3262
- mcpClients: clients,
3429
+ mcpUrl: knownTarget === "visual-plans" && planMode === "local-files"
3430
+ ? ""
3431
+ : installTarget.loaded.manifest.hosted.mcpUrl,
3432
+ mcpClients: shouldRegisterMcp ? clients : [],
3263
3433
  dryRun: true,
3264
3434
  commands: [dryRunInstallCommand(parsed, target)],
3265
3435
  githubActionPath,
3266
3436
  githubActionSuggestedCommand,
3437
+ planMode,
3267
3438
  };
3268
3439
  }
3269
3440
  finally {
@@ -3279,7 +3450,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
3279
3450
  try {
3280
3451
  if (parsed.instructions) {
3281
3452
  if (skillsAgents.length === 0) {
3282
- if (!parsed.mcp) {
3453
+ if (!shouldRegisterMcp) {
3283
3454
  throw new Error("Skill instructions can only be installed for Codex or Claude Code clients. Use an MCP-capable client or omit --instructions-only.");
3284
3455
  }
3285
3456
  }
@@ -3295,6 +3466,8 @@ export async function addAgentNativeSkill(parsed, options = {}) {
3295
3466
  scope: parsed.scope,
3296
3467
  baseDir: options.baseDir ?? process.cwd(),
3297
3468
  dryRun: parsed.dryRun,
3469
+ planMode,
3470
+ mcpUrl: installTarget.loaded.manifest.hosted.mcpUrl,
3298
3471
  });
3299
3472
  instructionSource = instructionsWritten[0];
3300
3473
  commands.push(...instructionsWritten.map((dir) => `write ${dir}`));
@@ -3333,7 +3506,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
3333
3506
  scope: parsed.scope,
3334
3507
  dryRun: Boolean(parsed.dryRun),
3335
3508
  });
3336
- if (parsed.mcp) {
3509
+ if (shouldRegisterMcp) {
3337
3510
  commands.push(`npx @agent-native/core@latest app-skill ensure --manifest ${installTarget.loaded.file} --client ${parsed.client} --scope ${parsed.scope} --yes`);
3338
3511
  if (!parsed.dryRun) {
3339
3512
  await ensureAppSkill(installTarget.loaded, {
@@ -3414,13 +3587,16 @@ export async function addAgentNativeSkill(parsed, options = {}) {
3414
3587
  instructionSource,
3415
3588
  skillNames: installTarget.skillNames,
3416
3589
  skillsAgents,
3417
- mcpUrl: installTarget.loaded.manifest.hosted.mcpUrl,
3418
- mcpClients: clients,
3590
+ mcpUrl: knownTarget === "visual-plans" && planMode === "local-files"
3591
+ ? ""
3592
+ : installTarget.loaded.manifest.hosted.mcpUrl,
3593
+ mcpClients: shouldRegisterMcp ? clients : [],
3419
3594
  dryRun: parsed.dryRun,
3420
3595
  commands,
3421
3596
  written: instructionsWritten,
3422
3597
  connected,
3423
3598
  connectCommand,
3599
+ planMode,
3424
3600
  githubActionPath,
3425
3601
  githubActionExisted,
3426
3602
  githubActionSuggestedCommand,
@@ -3454,6 +3630,7 @@ function skillStateJson(state) {
3454
3630
  installedHash: state.installedHash,
3455
3631
  latestHash: state.latestHash,
3456
3632
  metadataHash: state.metadataHash,
3633
+ planMode: state.planMode,
3457
3634
  };
3458
3635
  }
3459
3636
  function formatSkillState(state) {
@@ -3464,6 +3641,13 @@ function formatSkillState(state) {
3464
3641
  : "";
3465
3642
  return `${state.skillName.padEnd(22)} ${status.padEnd(7)} ${state.scope}/${state.client} ${managed}${hashes}\n ${state.path}`;
3466
3643
  }
3644
+ function planModeSummary(mode) {
3645
+ if (mode === "local-files")
3646
+ return "Local files - No sharing, all local.";
3647
+ if (mode === "self-hosted")
3648
+ return "Self-hosted/custom Plan app";
3649
+ return "Hosted Plans - shareable links and comments";
3650
+ }
3467
3651
  function runSkillsStatusOrUpdate(parsed, options, update) {
3468
3652
  const before = collectSkillInstallStates(parsed, options);
3469
3653
  const changed = update ? updateSkillInstallStates(before, parsed.dryRun) : [];
@@ -3586,6 +3770,45 @@ export async function runSkills(argv, options = {}) {
3586
3770
  selectedAll: targets.length === skillPromptOptions().length,
3587
3771
  preselected,
3588
3772
  });
3773
+ const includesPlans = targetsIncludePlans(targets);
3774
+ if (parsed.planMode && !includesPlans) {
3775
+ throw new Error("--mode only applies to visual-plan / visual-recap.");
3776
+ }
3777
+ if (includesPlans) {
3778
+ if (!parsed.planMode && parsed.mcpUrl) {
3779
+ parsed.planMode = "self-hosted";
3780
+ }
3781
+ if (!parsed.planMode && shouldPrompt(parsed, options)) {
3782
+ const prompt = options.promptPlanMode ?? promptForPlanMode;
3783
+ const mode = await prompt({ initialMode: "hosted" });
3784
+ if (!mode) {
3785
+ telemetry.track("skills_cli cancelled", { step: "plan-mode" });
3786
+ return;
3787
+ }
3788
+ parsed.planMode = mode;
3789
+ }
3790
+ if (!parsed.planMode)
3791
+ parsed.planMode = "hosted";
3792
+ if (parsed.planMode === "self-hosted" && !parsed.mcpUrl) {
3793
+ if (shouldPrompt(parsed, options)) {
3794
+ const prompt = options.promptPlanMcpUrl ?? promptForPlanMcpUrl;
3795
+ const mcpUrl = await prompt();
3796
+ if (!mcpUrl) {
3797
+ telemetry.track("skills_cli cancelled", {
3798
+ step: "plan-mcp-url",
3799
+ });
3800
+ return;
3801
+ }
3802
+ parsed.mcpUrl = mcpUrl;
3803
+ }
3804
+ else {
3805
+ throw new Error("--mode self-hosted requires --mcp-url <url> in non-interactive mode.");
3806
+ }
3807
+ }
3808
+ telemetry.track("skills_cli plan mode selected", {
3809
+ mode: parsed.planMode,
3810
+ });
3811
+ }
3589
3812
  const clients = await resolveSkillsClients(parsed, optionsWithTelemetry);
3590
3813
  if (!clients) {
3591
3814
  telemetry.track("skills_cli cancelled", { step: "clients" });
@@ -3684,6 +3907,11 @@ export async function runSkills(argv, options = {}) {
3684
3907
  .filter((result) => result.local)
3685
3908
  .flatMap((result) => result.commands)),
3686
3909
  ];
3910
+ const planModes = [
3911
+ ...new Set(results
3912
+ .map((result) => result.planMode)
3913
+ .filter((mode) => Boolean(mode))),
3914
+ ];
3687
3915
  const authConnected = results.some((result) => result.connected);
3688
3916
  const pendingConnectCommands = [
3689
3917
  ...new Set(results
@@ -3720,6 +3948,9 @@ export async function runSkills(argv, options = {}) {
3720
3948
  ? `MCP config ${mcpClients.join(", ")}`
3721
3949
  : "MCP config not required",
3722
3950
  mcpUrls.length ? `MCP URL ${mcpUrls.join(", ")}` : "",
3951
+ planModes.length
3952
+ ? `Plan mode ${planModes.map(planModeSummary).join(", ")}`
3953
+ : "",
3723
3954
  authConnected
3724
3955
  ? "Authentication completed"
3725
3956
  : pendingConnectCommands.length