@agent-native/core 0.66.7 → 0.66.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.
@@ -19,13 +19,14 @@ const HELP = `npx @agent-native/core@latest skills
19
19
 
20
20
  Usage:
21
21
  npx @agent-native/core@latest skills list
22
- npx @agent-native/core@latest skills status [assets|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|pi|all] [--scope user|project] [--json]
23
- npx @agent-native/core@latest skills update [assets|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|pi|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|cowork|cursor|opencode|github-copilot|all] [--scope user|project] [--mode hosted|local-files|self-hosted] [--mcp-url <url>] [--no-connect] [--with-github-action] [--yes] [--dry-run] [--json]
22
+ npx @agent-native/core@latest skills status [assets|content|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|pi|all] [--scope user|project] [--json]
23
+ npx @agent-native/core@latest skills update [assets|content|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|pi|all] [--scope user|project] [--dry-run] [--json]
24
+ npx @agent-native/core@latest skills add assets|content|design-exploration|visual-plan|visual-recap|context-xray [--client codex|claude-code|cowork|cursor|opencode|github-copilot|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:
28
28
  npx @agent-native/core@latest skills add assets
29
+ npx @agent-native/core@latest skills add content --mode local-files
29
30
  npx @agent-native/core@latest skills add design-exploration
30
31
  npx @agent-native/core@latest skills add visual-plan
31
32
  npx @agent-native/core@latest skills add visual-recap
@@ -71,6 +72,12 @@ Pass --mode to choose directly. Local-files mode skips MCP registration and
71
72
  auth and installs instructions that default to a no-auth block catalog fetch,
72
73
  MDX folders, and the localhost bridge viewer.
73
74
 
75
+ When installing content with --mode local-files, the CLI installs Content
76
+ instructions and writes or updates agent-native.json with repo-backed Markdown /
77
+ MDX roots for docs, blog, content, and resources. Use a local Content app, Agent
78
+ Native Desktop, or another trusted local bridge for Content actions to read and
79
+ write those files.
80
+
74
81
  When installing visual-recap interactively, the CLI offers to add the optional PR
75
82
  Visual Recap GitHub Action. Pass --with-github-action to write it directly, then
76
83
  run "npx @agent-native/core@latest recap setup" / "npx @agent-native/core@latest recap doctor" to configure and
@@ -161,6 +168,115 @@ of using a generic image generator.
161
168
  - If you inspect local MCP config, redact \`Authorization\`, \`http_headers\`,
162
169
  and token values. Never paste bearer tokens into chat or logs.
163
170
  `;
171
+ const CONTENT_SKILL_MD = `---
172
+ name: content
173
+ description: >-
174
+ Use Content for repo-backed Markdown/MDX docs, blogs, resources, rich
175
+ document editing, local components, shareable copies, and Content local-file
176
+ workspaces. Prefer Content actions over raw filesystem writes when available.
177
+ metadata:
178
+ visibility: exported
179
+ ---
180
+
181
+ # Content
182
+
183
+ Use the Content app when a workflow is about authoring, editing, reviewing, or
184
+ publishing Markdown/MDX documents: docs sites, blogs, resource libraries,
185
+ marketing pages, internal notes, and local MDX components. Content gives the
186
+ agent a document tree, a rich editor, normal document actions, and optional
187
+ local-file source of truth.
188
+
189
+ ## Choose The Path
190
+
191
+ - Use Content actions when the Content MCP/action tools are available:
192
+ \`list-documents\`, \`search-documents\`, \`get-document\`,
193
+ \`pull-document\`, \`create-document\`, \`edit-document\`,
194
+ \`update-document\`, \`delete-document\`, \`share-local-file-document\`,
195
+ \`list-local-component-files\`, and \`write-local-component-file\`.
196
+ - Use \`pull-document\` or \`get-document\` before editing a page. Use
197
+ \`edit-document\` for precise find/replace changes and \`update-document\`
198
+ for full rewrites or new content.
199
+ - In Local File Mode, Content actions read and write the repo files declared in
200
+ \`agent-native.json\`; SQL remains cache/history/search glue, not the source of
201
+ truth for those pages.
202
+ - If Content tools are not visible and no local Content app or Desktop bridge is
203
+ running, treat this skill as repo-editing guidance. Edit configured
204
+ \`.md\`/\`.mdx\` files directly, preserve frontmatter and MDX imports, and tell
205
+ the user the Content action surface was not available.
206
+
207
+ ## Action Examples
208
+
209
+ Prefer JSON input for action calls:
210
+
211
+ \`\`\`bash
212
+ pnpm action list-documents
213
+ pnpm action get-document '{"id":"local-file:..."}'
214
+ pnpm action edit-document '{"id":"local-file:...","find":"old copy","replace":"new copy"}'
215
+ pnpm action update-document '{"id":"local-file:...","content":"# Updated\\n\\nBody"}'
216
+ pnpm action share-local-file-document '{"id":"local-file:..."}'
217
+ \`\`\`
218
+
219
+ Run \`refresh-list\` after create/update/delete operations when you need the
220
+ open Content UI sidebar to repaint immediately.
221
+
222
+ ## Local File Mode
223
+
224
+ Install into an existing repo with:
225
+
226
+ \`\`\`bash
227
+ npx @agent-native/core@latest skills add content --mode local-files --scope project
228
+ \`\`\`
229
+
230
+ The installer copies this skill and writes or updates \`agent-native.json\` with
231
+ Content roots for \`docs/\`, \`blog/\`, \`content/\`, and \`resources/\`, plus a
232
+ \`components/\` folder for local MDX components. A typical manifest looks like:
233
+
234
+ \`\`\`json
235
+ {
236
+ "version": 1,
237
+ "apps": {
238
+ "content": {
239
+ "mode": "local-files",
240
+ "roots": [
241
+ { "name": "Docs", "path": "docs", "kind": "docs", "extensions": [".md", ".mdx"] },
242
+ { "name": "Blog", "path": "blog", "kind": "blog", "extensions": [".md", ".mdx"] },
243
+ { "name": "Content", "path": "content", "kind": "content", "extensions": [".md", ".mdx"] },
244
+ { "name": "Resources", "path": "resources", "kind": "resources", "extensions": [".md", ".mdx"] }
245
+ ],
246
+ "components": "components",
247
+ "extensions": "extensions",
248
+ "hide": ["**/_*.md", "**/_*.mdx"]
249
+ }
250
+ }
251
+ }
252
+ \`\`\`
253
+
254
+ Local File Mode does not make the host language model local, and the hosted
255
+ Content app cannot read private repo files by itself. File access requires a
256
+ local Content app, Agent Native Desktop, or another trusted local bridge.
257
+
258
+ ## MDX And Components
259
+
260
+ - Preserve frontmatter keys you do not understand. Preserve MDX imports,
261
+ exports, JSX, and expression props unless the user explicitly asks to change
262
+ them.
263
+ - Use local components from the configured \`components\` folder. Components
264
+ should be PascalCase exports from \`.tsx\` files; simple editable input metadata
265
+ can live next to them as \`ComponentNameInputs\`.
266
+ - Use \`list-local-component-files\` and \`write-local-component-file\` for
267
+ component source changes when Content tools are available. Otherwise edit the
268
+ component files directly like normal repo source.
269
+
270
+ ## Boundaries
271
+
272
+ - Moving, renaming, and reordering local-file pages are not first-class Content
273
+ UI operations yet. Use normal file operations when the user asks for those,
274
+ then let Content rediscover the file tree.
275
+ - Do not push/pull Notion, Builder.io, or other provider-backed content unless
276
+ the user explicitly asks for provider sync.
277
+ - Do not paste secrets, private provider data, or credential-looking values into
278
+ docs, generated pages, frontmatter, examples, or local components.
279
+ `;
164
280
  const DESIGN_EXPLORATION_SKILL_MD = `---
165
281
  name: design-exploration
166
282
  description: >-
@@ -2164,6 +2280,53 @@ export const BUILT_IN_APP_SKILLS = {
2164
2280
  }),
2165
2281
  skillMarkdown: ASSETS_SKILL_MD,
2166
2282
  },
2283
+ content: {
2284
+ skillName: "content",
2285
+ manifest: normalizeAppSkillManifest({
2286
+ schemaVersion: 1,
2287
+ id: "content",
2288
+ displayName: "Content",
2289
+ description: "Edit docs, blogs, resources, and MDX content through the Content app, including repo-backed Local File Mode.",
2290
+ hosted: {
2291
+ url: "https://content.agent-native.com",
2292
+ mcpUrl: "https://content.agent-native.com/_agent-native/mcp",
2293
+ },
2294
+ mcp: { serverName: "agent-native-content" },
2295
+ auth: {
2296
+ mode: "oauth",
2297
+ setup: "Authenticate with the Content MCP connector in the host app. Local File Mode requires a local Content app, Agent Native Desktop, or trusted local bridge for filesystem access.",
2298
+ },
2299
+ surfaces: [
2300
+ {
2301
+ id: "content-documents",
2302
+ action: "list-documents",
2303
+ path: "/",
2304
+ },
2305
+ {
2306
+ id: "content-local-files",
2307
+ action: "share-local-file-document",
2308
+ path: "/local-files",
2309
+ },
2310
+ ],
2311
+ skills: [
2312
+ {
2313
+ path: "skills/content",
2314
+ visibility: "exported",
2315
+ exportAs: "content",
2316
+ },
2317
+ ],
2318
+ hostAdapters: [
2319
+ "codex-plugin",
2320
+ "claude-marketplace",
2321
+ "vercel-skills",
2322
+ "plain-skill",
2323
+ "claude-skill",
2324
+ "chatgpt-mcp",
2325
+ "generic-mcp",
2326
+ ],
2327
+ }),
2328
+ skillMarkdown: CONTENT_SKILL_MD,
2329
+ },
2167
2330
  design: {
2168
2331
  skillName: "design-exploration",
2169
2332
  manifest: normalizeAppSkillManifest({
@@ -2318,6 +2481,12 @@ const BUILT_IN_APP_SKILL_ALIASES = {
2318
2481
  "image-generation": "assets",
2319
2482
  "agent-native-assets": "assets",
2320
2483
  "agent-native-images": "assets",
2484
+ content: "content",
2485
+ docs: "content",
2486
+ documents: "content",
2487
+ "local-content": "content",
2488
+ "content-local-files": "content",
2489
+ "agent-native-content": "content",
2321
2490
  design: "design",
2322
2491
  "ui-design": "design",
2323
2492
  "ux-design": "design",
@@ -2345,6 +2514,13 @@ const BUILT_IN_APP_SKILL_ALIASES = {
2345
2514
  };
2346
2515
  const BUILT_IN_APP_SKILL_DISPLAY_ALIASES = {
2347
2516
  assets: ["images", "image-generation", "agent-native-images"],
2517
+ content: [
2518
+ "docs",
2519
+ "documents",
2520
+ "local-content",
2521
+ "content-local-files",
2522
+ "agent-native-content",
2523
+ ],
2348
2524
  design: [
2349
2525
  "design-exploration",
2350
2526
  "ux-exploration",
@@ -2431,6 +2607,12 @@ function isKnownSkill(value) {
2431
2607
  function isLocalOnlyBuiltInSkill(entry) {
2432
2608
  return Boolean(entry && "localOnly" in entry && entry.localOnly);
2433
2609
  }
2610
+ function targetSupportsInstallMode(targetId) {
2611
+ return targetId === "visual-plans" || targetId === "content";
2612
+ }
2613
+ function localFilesModeSkipsMcp(targetId, mode) {
2614
+ return mode === "local-files" && targetSupportsInstallMode(targetId);
2615
+ }
2434
2616
  function builtInExtraSkills(entry) {
2435
2617
  return "extraSkills" in entry && entry.extraSkills ? entry.extraSkills : {};
2436
2618
  }
@@ -2508,19 +2690,49 @@ for plans and recaps instead of assuming \`https://plan.agent-native.com\`.`;
2508
2690
  }
2509
2691
  return "";
2510
2692
  }
2511
- function applyPlanModeToSkillMarkdown(markdown, input) {
2512
- if (input.appSkillId !== "visual-plans")
2513
- return markdown;
2514
- const block = planModeInstructionBlock({
2515
- mode: input.mode,
2516
- mcpUrl: input.mcpUrl,
2517
- });
2693
+ function contentModeInstructionBlock(input) {
2694
+ if (input.mode === "local-files") {
2695
+ return `## Installed Mode
2696
+
2697
+ Default storage for this installation: Content Local File Mode. This repo should
2698
+ have an \`agent-native.json\` file with \`apps.content.mode: "local-files"\`;
2699
+ the installer writes one if missing and fills in default roots for \`docs/\`,
2700
+ \`blog/\`, \`content/\`, and \`resources/\`. Prefer Content document actions
2701
+ when a local Content app,
2702
+ Agent Native Desktop, or another trusted local bridge exposes them. If those
2703
+ tools are not currently available, edit the configured Markdown/MDX files and
2704
+ local components directly, preserving frontmatter, imports, JSX, and unknown MDX
2705
+ syntax. The hosted Content app cannot read private repo files by itself.`;
2706
+ }
2707
+ if (input.mode === "self-hosted") {
2708
+ return `## Installed Mode
2709
+
2710
+ Default storage for this installation: the configured self-hosted/custom Content
2711
+ app${input.mcpUrl ? ` at \`${input.mcpUrl}\`` : ""}. Use that Content MCP
2712
+ connector instead of assuming \`https://content.agent-native.com\`.`;
2713
+ }
2714
+ return "";
2715
+ }
2716
+ function applyInstallModeToSkillMarkdown(markdown, input) {
2717
+ let block = "";
2718
+ if (input.appSkillId === "visual-plans") {
2719
+ block = planModeInstructionBlock({
2720
+ mode: input.mode,
2721
+ mcpUrl: input.mcpUrl,
2722
+ });
2723
+ }
2724
+ else if (input.appSkillId === "content") {
2725
+ block = contentModeInstructionBlock({
2726
+ mode: input.mode,
2727
+ mcpUrl: input.mcpUrl,
2728
+ });
2729
+ }
2518
2730
  return insertAfterFrontmatter(markdown, block);
2519
2731
  }
2520
2732
  function skillFilesForBuiltIn(appSkillId, options = {}) {
2521
2733
  const entry = BUILT_IN_APP_SKILLS[appSkillId];
2522
2734
  const skills = {
2523
- [entry.skillName]: applyPlanModeToSkillMarkdown(entry.skillMarkdown, {
2735
+ [entry.skillName]: applyInstallModeToSkillMarkdown(entry.skillMarkdown, {
2524
2736
  appSkillId,
2525
2737
  mode: options.planMode,
2526
2738
  mcpUrl: options.mcpUrl,
@@ -2528,7 +2740,7 @@ function skillFilesForBuiltIn(appSkillId, options = {}) {
2528
2740
  ...builtInExtraSkills(entry),
2529
2741
  };
2530
2742
  for (const [skillName, skillMarkdown] of Object.entries(builtInExtraSkills(entry))) {
2531
- skills[skillName] = applyPlanModeToSkillMarkdown(skillMarkdown, {
2743
+ skills[skillName] = applyInstallModeToSkillMarkdown(skillMarkdown, {
2532
2744
  appSkillId,
2533
2745
  mode: options.planMode,
2534
2746
  mcpUrl: options.mcpUrl,
@@ -2545,7 +2757,8 @@ function skillFilesForBuiltIn(appSkillId, options = {}) {
2545
2757
  appSkillId,
2546
2758
  displayName: entry.manifest.displayName,
2547
2759
  skillName,
2548
- mcpUrl: isLocalOnlyBuiltInSkill(entry) || options.planMode === "local-files"
2760
+ mcpUrl: isLocalOnlyBuiltInSkill(entry) ||
2761
+ localFilesModeSkipsMcp(appSkillId, options.planMode)
2549
2762
  ? ""
2550
2763
  : (options.mcpUrl ?? entry.manifest.hosted.mcpUrl),
2551
2764
  files,
@@ -2584,6 +2797,90 @@ function writeSkillFolder(dir, bundle, installedAt = new Date().toISOString()) {
2584
2797
  };
2585
2798
  fs.writeFileSync(path.join(dir, AGENT_NATIVE_SKILL_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}\n`, "utf-8");
2586
2799
  }
2800
+ function isJsonRecord(value) {
2801
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
2802
+ }
2803
+ function defaultContentLocalFilesAppConfig() {
2804
+ return {
2805
+ mode: "local-files",
2806
+ roots: [
2807
+ {
2808
+ name: "Docs",
2809
+ path: "docs",
2810
+ kind: "docs",
2811
+ extensions: [".md", ".mdx"],
2812
+ },
2813
+ {
2814
+ name: "Blog",
2815
+ path: "blog",
2816
+ kind: "blog",
2817
+ extensions: [".md", ".mdx"],
2818
+ },
2819
+ {
2820
+ name: "Content",
2821
+ path: "content",
2822
+ kind: "content",
2823
+ extensions: [".md", ".mdx"],
2824
+ },
2825
+ {
2826
+ name: "Resources",
2827
+ path: "resources",
2828
+ kind: "resources",
2829
+ extensions: [".md", ".mdx"],
2830
+ },
2831
+ ],
2832
+ components: "components",
2833
+ extensions: "extensions",
2834
+ hide: ["**/_*.md", "**/_*.mdx"],
2835
+ };
2836
+ }
2837
+ function contentLocalFilesManifestPath(baseDir) {
2838
+ return path.join(baseDir, "agent-native.json");
2839
+ }
2840
+ function shouldWriteContentLocalFilesManifest(targetId, mode) {
2841
+ return targetId === "content" && mode === "local-files";
2842
+ }
2843
+ function mergeContentLocalFilesManifest(existing) {
2844
+ const manifest = isJsonRecord(existing) ? { ...existing } : {};
2845
+ if (manifest.version === undefined)
2846
+ manifest.version = 1;
2847
+ const apps = isJsonRecord(manifest.apps) ? { ...manifest.apps } : {};
2848
+ const contentApp = isJsonRecord(apps.content) ? { ...apps.content } : {};
2849
+ const defaults = defaultContentLocalFilesAppConfig();
2850
+ contentApp.mode = "local-files";
2851
+ if (!Array.isArray(contentApp.roots) || contentApp.roots.length === 0) {
2852
+ contentApp.roots = defaults.roots;
2853
+ }
2854
+ if (contentApp.components === undefined) {
2855
+ contentApp.components = defaults.components;
2856
+ }
2857
+ if (contentApp.extensions === undefined) {
2858
+ contentApp.extensions = defaults.extensions;
2859
+ }
2860
+ if (!Array.isArray(contentApp.hide) || contentApp.hide.length === 0) {
2861
+ contentApp.hide = defaults.hide;
2862
+ }
2863
+ apps.content = contentApp;
2864
+ manifest.apps = apps;
2865
+ return manifest;
2866
+ }
2867
+ function writeContentLocalFilesManifest(baseDir, options = {}) {
2868
+ const manifestPath = contentLocalFilesManifestPath(baseDir);
2869
+ let existing = {};
2870
+ if (fs.existsSync(manifestPath)) {
2871
+ try {
2872
+ existing = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
2873
+ }
2874
+ catch (error) {
2875
+ throw new Error(`Could not parse ${manifestPath}: ${error?.message ?? error}`);
2876
+ }
2877
+ }
2878
+ const manifest = mergeContentLocalFilesManifest(existing);
2879
+ if (!options.dryRun) {
2880
+ fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf-8");
2881
+ }
2882
+ return manifestPath;
2883
+ }
2587
2884
  /**
2588
2885
  * The skills directory a built-in skill's instructions are copied into for a
2589
2886
  * given agent + scope. Mirrors the layout the skills installer uses so
@@ -2979,6 +3276,11 @@ const BUILT_IN_SKILL_PROMPT_OPTIONS = [
2979
3276
  label: "assets",
2980
3277
  hint: BUILT_IN_APP_SKILLS.assets.manifest.description,
2981
3278
  },
3279
+ {
3280
+ value: "content",
3281
+ label: "content",
3282
+ hint: BUILT_IN_APP_SKILLS.content.manifest.description,
3283
+ },
2982
3284
  {
2983
3285
  value: "design-exploration",
2984
3286
  label: "design-exploration",
@@ -3262,11 +3564,21 @@ function targetIncludesPlans(target) {
3262
3564
  function targetsIncludePlans(targets) {
3263
3565
  return targets.some(targetIncludesPlans);
3264
3566
  }
3567
+ function targetIncludesInstallModeSkill(target) {
3568
+ return targetSupportsInstallMode(normalizeKnownSkillTarget(target));
3569
+ }
3570
+ function targetsIncludeInstallModeSkills(targets) {
3571
+ return targets.some(targetIncludesInstallModeSkill);
3572
+ }
3265
3573
  function planSkillNamesSelected(skillNames) {
3266
3574
  return Boolean(skillNames?.some((name) => normalizeKnownSkillTarget(name) === "visual-plans"));
3267
3575
  }
3576
+ function installModeSkillNamesSelected(skillNames) {
3577
+ return Boolean(skillNames?.some((name) => targetSupportsInstallMode(normalizeKnownSkillTarget(name))));
3578
+ }
3268
3579
  function shouldForwardPlanModeFlag(target, skillNames) {
3269
- return targetIncludesPlans(target) || planSkillNamesSelected(skillNames);
3580
+ return (targetIncludesInstallModeSkill(target) ||
3581
+ installModeSkillNamesSelected(skillNames));
3270
3582
  }
3271
3583
  function recapSkillNamesSelected(skillNames) {
3272
3584
  return Boolean(skillNames?.some((name) => {
@@ -3484,6 +3796,9 @@ function loadSkillTarget(target, onlySkillNames) {
3484
3796
  dir: process.cwd(),
3485
3797
  },
3486
3798
  skillNames,
3799
+ modeAwareId: targetSupportsInstallMode(knownTarget)
3800
+ ? knownTarget
3801
+ : undefined,
3487
3802
  materializeInstructions(outDir) {
3488
3803
  const bundles = skillFilesForBuiltIn(knownTarget);
3489
3804
  for (const bundle of Object.values(bundles)) {
@@ -3508,6 +3823,9 @@ function loadSkillTarget(target, onlySkillNames) {
3508
3823
  skillNames: loaded.manifest.skills
3509
3824
  .filter((skill) => skill.visibility === "exported" || skill.visibility === "both")
3510
3825
  .map((skill) => skill.exportAs ?? path.basename(skill.path)),
3826
+ modeAwareId: targetSupportsInstallMode(loaded.manifest.id)
3827
+ ? loaded.manifest.id
3828
+ : undefined,
3511
3829
  materializeInstructions(outDir) {
3512
3830
  const packed = buildAppSkillPack(loaded, outDir);
3513
3831
  const vercelAdapter = path.join(packed.outDir, "adapters", "vercel-skills");
@@ -3571,7 +3889,7 @@ function preserveMcpUrlAppPathOverride(target, input) {
3571
3889
  },
3572
3890
  };
3573
3891
  }
3574
- function dryRunInstallCommand(parsed, target) {
3892
+ function dryRunInstallCommand(parsed, target, options = {}) {
3575
3893
  const clients = parsed.clients ??
3576
3894
  resolveSkillsClientArg(parsed.client, targetInstallsMcp(target, parsed));
3577
3895
  const args = [
@@ -3585,7 +3903,8 @@ function dryRunInstallCommand(parsed, target) {
3585
3903
  parsed.scope,
3586
3904
  ];
3587
3905
  const forwardsPlanFlags = shouldForwardPlanModeFlag(target, parsed.plainSkillNames);
3588
- if (forwardsPlanFlags && parsed.planMode)
3906
+ const forwardsInstallMode = forwardsPlanFlags || targetSupportsInstallMode(options.modeAwareTargetId);
3907
+ if (forwardsInstallMode && parsed.planMode)
3589
3908
  args.push("--mode", parsed.planMode);
3590
3909
  if (parsed.mcpUrl)
3591
3910
  args.push("--mcp-url", parsed.mcpUrl);
@@ -3752,7 +4071,7 @@ async function addPlainSkillRepo(parsed, options) {
3752
4071
  if (!parsed.instructions && parsed.mcp) {
3753
4072
  throw new Error("Plain skill repositories only install skill instructions. Run without --mcp-only.");
3754
4073
  }
3755
- if (parsed.mcpUrl && !planSkillNamesSelected(parsed.plainSkillNames)) {
4074
+ if (parsed.mcpUrl && !installModeSkillNamesSelected(parsed.plainSkillNames)) {
3756
4075
  throw new Error("--mcp-url only applies to app-backed Agent Native skills.");
3757
4076
  }
3758
4077
  const clients = parsed.clients ?? resolveSkillsClientArg(parsed.client);
@@ -3942,20 +4261,6 @@ export async function addAgentNativeSkill(parsed, options = {}) {
3942
4261
  }, options);
3943
4262
  }
3944
4263
  const knownTarget = normalizeKnownSkillTarget(target);
3945
- const planMode = knownTarget === "visual-plans"
3946
- ? (parsed.planMode ?? (parsed.mcpUrl ? "self-hosted" : "hosted"))
3947
- : undefined;
3948
- if (parsed.planMode && knownTarget !== "visual-plans") {
3949
- throw new Error("--mode only applies to visual-plan / visual-recap.");
3950
- }
3951
- if (planMode === "local-files" && parsed.mcpUrl) {
3952
- throw new Error("--mode local-files cannot be combined with --mcp-url.");
3953
- }
3954
- if (planMode === "self-hosted" && !parsed.mcpUrl) {
3955
- throw new Error("--mode self-hosted requires --mcp-url <url>.");
3956
- }
3957
- const shouldRegisterMcp = parsed.mcp &&
3958
- !(knownTarget === "visual-plans" && planMode === "local-files");
3959
4264
  // For multi-skill bundles (the plan bundle), a single-skill target installs
3960
4265
  // only that skill. `installsRecap` controls the PR Visual Recap github-action
3961
4266
  // offer, which is only relevant when the recap skill is part of the install.
@@ -3971,7 +4276,11 @@ export async function addAgentNativeSkill(parsed, options = {}) {
3971
4276
  throw new Error(`Unknown skill or manifest path: ${target}. Run "npx @agent-native/core@latest skills list".`);
3972
4277
  }
3973
4278
  const knownBuiltIn = knownTarget ? BUILT_IN_APP_SKILLS[knownTarget] : null;
4279
+ const baseDir = options.baseDir ?? process.cwd();
3974
4280
  if (isLocalOnlyBuiltInSkill(knownBuiltIn)) {
4281
+ if (parsed.planMode) {
4282
+ throw new Error("--mode only applies to visual-plan / visual-recap / content.");
4283
+ }
3975
4284
  if (parsed.mcpUrl) {
3976
4285
  throw new Error("Context X-Ray is installed locally and does not use --mcp-url yet.");
3977
4286
  }
@@ -4004,7 +4313,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
4004
4313
  };
4005
4314
  }
4006
4315
  const localInstall = installLocalContextXray({
4007
- baseDir: options.baseDir ?? process.cwd(),
4316
+ baseDir,
4008
4317
  clients,
4009
4318
  scope: parsed.scope,
4010
4319
  });
@@ -4030,6 +4339,25 @@ export async function addAgentNativeSkill(parsed, options = {}) {
4030
4339
  };
4031
4340
  }
4032
4341
  let installTarget = loadSkillTarget(target, onlySkillNames);
4342
+ const modeAwareTargetId = installTarget.modeAwareId;
4343
+ const planMode = modeAwareTargetId
4344
+ ? (parsed.planMode ??
4345
+ (parsed.mcpUrl
4346
+ ? "self-hosted"
4347
+ : modeAwareTargetId === "visual-plans"
4348
+ ? "hosted"
4349
+ : undefined))
4350
+ : undefined;
4351
+ if (parsed.planMode && !modeAwareTargetId) {
4352
+ throw new Error("--mode only applies to visual-plan / visual-recap / content.");
4353
+ }
4354
+ if (planMode === "local-files" && parsed.mcpUrl) {
4355
+ throw new Error("--mode local-files cannot be combined with --mcp-url.");
4356
+ }
4357
+ if (planMode === "self-hosted" && !parsed.mcpUrl) {
4358
+ throw new Error("--mode self-hosted requires --mcp-url <url>.");
4359
+ }
4360
+ const shouldRegisterMcp = parsed.mcp && !localFilesModeSkipsMcp(modeAwareTargetId, planMode);
4033
4361
  if (parsed.mcpUrl) {
4034
4362
  installTarget = withMcpUrlOverride(installTarget, parsed.mcpUrl);
4035
4363
  }
@@ -4042,6 +4370,9 @@ export async function addAgentNativeSkill(parsed, options = {}) {
4042
4370
  const skillsAgents = skillsAgentsForClients(clients);
4043
4371
  if (parsed.dryRun) {
4044
4372
  try {
4373
+ const localManifestPath = shouldWriteContentLocalFilesManifest(modeAwareTargetId, planMode)
4374
+ ? contentLocalFilesManifestPath(baseDir)
4375
+ : undefined;
4045
4376
  const githubActionPath = parsed.withGithubAction && installsRecap
4046
4377
  ? prVisualRecapWorkflowDisplayPath()
4047
4378
  : undefined;
@@ -4059,15 +4390,19 @@ export async function addAgentNativeSkill(parsed, options = {}) {
4059
4390
  displayName: installTarget.displayName,
4060
4391
  skillNames: installTarget.skillNames,
4061
4392
  skillsAgents,
4062
- mcpUrl: knownTarget === "visual-plans" && planMode === "local-files"
4393
+ mcpUrl: localFilesModeSkipsMcp(modeAwareTargetId, planMode)
4063
4394
  ? ""
4064
4395
  : installTarget.loaded.manifest.hosted.mcpUrl,
4065
4396
  mcpClients: shouldRegisterMcp ? mcpClients : [],
4066
4397
  dryRun: true,
4067
- commands: [dryRunInstallCommand(parsed, target)],
4398
+ commands: [
4399
+ dryRunInstallCommand(parsed, target, { modeAwareTargetId }),
4400
+ ...(localManifestPath ? [`write ${localManifestPath}`] : []),
4401
+ ],
4068
4402
  githubActionPath,
4069
4403
  githubActionSuggestedCommand,
4070
4404
  planMode,
4405
+ localManifestPath,
4071
4406
  };
4072
4407
  }
4073
4408
  finally {
@@ -4081,6 +4416,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
4081
4416
  let connected = false;
4082
4417
  let connectCommand;
4083
4418
  let registeredMcpClients = shouldRegisterMcp ? mcpClients : [];
4419
+ let localManifestPath;
4084
4420
  try {
4085
4421
  if (parsed.instructions) {
4086
4422
  if (skillsAgents.length === 0) {
@@ -4098,7 +4434,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
4098
4434
  onlySkillNames,
4099
4435
  skillsAgents,
4100
4436
  scope: parsed.scope,
4101
- baseDir: options.baseDir ?? process.cwd(),
4437
+ baseDir,
4102
4438
  dryRun: parsed.dryRun,
4103
4439
  planMode,
4104
4440
  mcpUrl: installTarget.loaded.manifest.hosted.mcpUrl,
@@ -4121,6 +4457,12 @@ export async function addAgentNativeSkill(parsed, options = {}) {
4121
4457
  ...installTarget.skillNames.flatMap((skill) => ["--skill", skill]),
4122
4458
  ...skillsAgents.flatMap((agent) => ["-a", agent]),
4123
4459
  ...(parsed.scope === "user" ? ["-g"] : []),
4460
+ ...(modeAwareTargetId && parsed.planMode
4461
+ ? ["--mode", parsed.planMode]
4462
+ : []),
4463
+ ...(modeAwareTargetId && parsed.mcpUrl
4464
+ ? ["--mcp-url", parsed.mcpUrl]
4465
+ : []),
4124
4466
  ...(parsed.yes || knownTarget ? ["-y"] : []),
4125
4467
  ];
4126
4468
  commands.push(commandString("npx", args));
@@ -4133,6 +4475,10 @@ export async function addAgentNativeSkill(parsed, options = {}) {
4133
4475
  }
4134
4476
  }
4135
4477
  }
4478
+ if (shouldWriteContentLocalFilesManifest(modeAwareTargetId, planMode)) {
4479
+ localManifestPath = writeContentLocalFilesManifest(baseDir);
4480
+ commands.push(`write ${localManifestPath}`);
4481
+ }
4136
4482
  // Skill instructions are now on disk (built-in folders copied or external
4137
4483
  // pack materialized) — record the install before MCP registration/connect.
4138
4484
  options.telemetry?.track("skills_cli install completed", {
@@ -4180,7 +4526,6 @@ export async function addAgentNativeSkill(parsed, options = {}) {
4180
4526
  }
4181
4527
  // `--with-github-action`: also drop the PR Visual Recap workflow into the
4182
4528
  // repo so PRs get automatic recaps. Only meaningful for the plan family.
4183
- const baseDir = options.baseDir ?? process.cwd();
4184
4529
  let withGithubAction = Boolean(parsed.withGithubAction);
4185
4530
  let githubActionPath;
4186
4531
  let githubActionExisted;
@@ -4233,7 +4578,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
4233
4578
  instructionSource,
4234
4579
  skillNames: installTarget.skillNames,
4235
4580
  skillsAgents,
4236
- mcpUrl: knownTarget === "visual-plans" && planMode === "local-files"
4581
+ mcpUrl: localFilesModeSkipsMcp(modeAwareTargetId, planMode)
4237
4582
  ? ""
4238
4583
  : installTarget.loaded.manifest.hosted.mcpUrl,
4239
4584
  mcpClients: registeredMcpClients,
@@ -4243,6 +4588,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
4243
4588
  connected,
4244
4589
  connectCommand,
4245
4590
  planMode,
4591
+ localManifestPath,
4246
4592
  githubActionPath,
4247
4593
  githubActionExisted,
4248
4594
  githubActionSuggestedCommand,
@@ -4306,10 +4652,10 @@ function formatSkillState(state) {
4306
4652
  }
4307
4653
  function planModeSummary(mode) {
4308
4654
  if (mode === "local-files")
4309
- return "Local files - No sharing, all local.";
4655
+ return "Local files - no hosted writes by default";
4310
4656
  if (mode === "self-hosted")
4311
- return "Self-hosted/custom Plan app";
4312
- return "Hosted Plans - shareable links and comments";
4657
+ return "Self-hosted/custom app";
4658
+ return "Hosted app";
4313
4659
  }
4314
4660
  function skillInstructionAgentLabel(agent) {
4315
4661
  if (agent === "codex")
@@ -4326,8 +4672,8 @@ function targetInstallsMcp(target, parsed) {
4326
4672
  if (publicSkillSelectionNames(target))
4327
4673
  return false;
4328
4674
  const knownTarget = normalizeKnownSkillTarget(target);
4329
- if (knownTarget === "visual-plans")
4330
- return parsed.planMode !== "local-files";
4675
+ if (localFilesModeSkipsMcp(knownTarget, parsed.planMode))
4676
+ return false;
4331
4677
  if (knownTarget) {
4332
4678
  return !isLocalOnlyBuiltInSkill(BUILT_IN_APP_SKILLS[knownTarget]);
4333
4679
  }
@@ -4515,8 +4861,10 @@ export async function runSkills(argv, options = {}) {
4515
4861
  });
4516
4862
  const includesPlans = targetsIncludePlans(targets) ||
4517
4863
  planSkillNamesSelected(parsed.plainSkillNames);
4518
- if (parsed.planMode && !includesPlans) {
4519
- throw new Error("--mode only applies to visual-plan / visual-recap.");
4864
+ const includesInstallModeSkills = targetsIncludeInstallModeSkills(targets) ||
4865
+ installModeSkillNamesSelected(parsed.plainSkillNames);
4866
+ if (parsed.planMode && !includesInstallModeSkills) {
4867
+ throw new Error("--mode only applies to visual-plan / visual-recap / content.");
4520
4868
  }
4521
4869
  if (includesPlans) {
4522
4870
  if (!parsed.planMode && parsed.mcpUrl) {
@@ -4709,7 +5057,7 @@ export async function runSkills(argv, options = {}) {
4709
5057
  : "MCP config not required",
4710
5058
  mcpUrls.length ? `MCP URL ${mcpUrls.join(", ")}` : "",
4711
5059
  planModes.length
4712
- ? `Plan mode ${planModes.map(planModeSummary).join(", ")}`
5060
+ ? `Install mode ${planModes.map(planModeSummary).join(", ")}`
4713
5061
  : "",
4714
5062
  authConnected
4715
5063
  ? "Authentication completed"