@agent-native/core 0.51.15 → 0.52.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.
Files changed (61) hide show
  1. package/README.md +3 -3
  2. package/dist/cli/connect.d.ts +4 -3
  3. package/dist/cli/connect.d.ts.map +1 -1
  4. package/dist/cli/connect.js +67 -26
  5. package/dist/cli/connect.js.map +1 -1
  6. package/dist/cli/mcp-config-writers.d.ts +20 -13
  7. package/dist/cli/mcp-config-writers.d.ts.map +1 -1
  8. package/dist/cli/mcp-config-writers.js +152 -13
  9. package/dist/cli/mcp-config-writers.js.map +1 -1
  10. package/dist/cli/mcp.d.ts +2 -2
  11. package/dist/cli/mcp.d.ts.map +1 -1
  12. package/dist/cli/mcp.js +41 -193
  13. package/dist/cli/mcp.js.map +1 -1
  14. package/dist/cli/plan-local.d.ts +3 -1
  15. package/dist/cli/plan-local.d.ts.map +1 -1
  16. package/dist/cli/plan-local.js +24 -6
  17. package/dist/cli/plan-local.js.map +1 -1
  18. package/dist/cli/recap.d.ts.map +1 -1
  19. package/dist/cli/recap.js +1 -1
  20. package/dist/cli/recap.js.map +1 -1
  21. package/dist/cli/skills.d.ts +11 -4
  22. package/dist/cli/skills.d.ts.map +1 -1
  23. package/dist/cli/skills.js +218 -53
  24. package/dist/cli/skills.js.map +1 -1
  25. package/dist/client/agent-engine-key.d.ts +6 -4
  26. package/dist/client/agent-engine-key.d.ts.map +1 -1
  27. package/dist/client/agent-engine-key.js +9 -6
  28. package/dist/client/agent-engine-key.js.map +1 -1
  29. package/dist/client/chat/run-recovery.js +1 -1
  30. package/dist/client/chat/run-recovery.js.map +1 -1
  31. package/dist/client/settings/SettingsPanel.d.ts.map +1 -1
  32. package/dist/client/settings/SettingsPanel.js +7 -14
  33. package/dist/client/settings/SettingsPanel.js.map +1 -1
  34. package/dist/coding-tools/run-code.d.ts +7 -0
  35. package/dist/coding-tools/run-code.d.ts.map +1 -1
  36. package/dist/coding-tools/run-code.js +21 -106
  37. package/dist/coding-tools/run-code.js.map +1 -1
  38. package/dist/coding-tools/sandbox/adapter.d.ts +79 -0
  39. package/dist/coding-tools/sandbox/adapter.d.ts.map +1 -0
  40. package/dist/coding-tools/sandbox/adapter.js +24 -0
  41. package/dist/coding-tools/sandbox/adapter.js.map +1 -0
  42. package/dist/coding-tools/sandbox/index.d.ts +51 -0
  43. package/dist/coding-tools/sandbox/index.d.ts.map +1 -0
  44. package/dist/coding-tools/sandbox/index.js +79 -0
  45. package/dist/coding-tools/sandbox/index.js.map +1 -0
  46. package/dist/coding-tools/sandbox/local-child-process-adapter.d.ts +24 -0
  47. package/dist/coding-tools/sandbox/local-child-process-adapter.d.ts.map +1 -0
  48. package/dist/coding-tools/sandbox/local-child-process-adapter.js +141 -0
  49. package/dist/coding-tools/sandbox/local-child-process-adapter.js.map +1 -0
  50. package/dist/server/agent-engine-api-key-route.d.ts +37 -0
  51. package/dist/server/agent-engine-api-key-route.d.ts.map +1 -0
  52. package/dist/server/agent-engine-api-key-route.js +105 -0
  53. package/dist/server/agent-engine-api-key-route.js.map +1 -0
  54. package/dist/server/core-routes-plugin.d.ts.map +1 -1
  55. package/dist/server/core-routes-plugin.js +10 -6
  56. package/dist/server/core-routes-plugin.js.map +1 -1
  57. package/dist/server/create-server.js +1 -1
  58. package/dist/server/create-server.js.map +1 -1
  59. package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +7 -4
  60. package/package.json +1 -1
  61. package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +7 -4
package/dist/cli/mcp.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * `agent-native mcp <subcommand>` — connect external coding agents (Claude
3
- * Code desktop & CLI, Claude Cowork, Codex) to this agent-native app/workspace
4
- * over MCP.
3
+ * Code desktop & CLI, Claude Cowork, Codex, Cursor, OpenCode, GitHub Copilot /
4
+ * VS Code) to this agent-native app/workspace over MCP.
5
5
  *
6
6
  * serve Run the MCP stdio transport (this is what client configs spawn).
7
7
  * install Provision a token + write the client's MCP config idempotently.
@@ -14,18 +14,11 @@
14
14
  */
15
15
  import crypto from "node:crypto";
16
16
  import fs from "node:fs";
17
- import os from "node:os";
18
17
  import path from "node:path";
19
18
  import { runMCPStdio } from "../mcp/stdio.js";
20
- import { writeFileAtomic } from "./mcp-config-writers.js";
19
+ import { CLIENTS, buildCodexHttpBlock, buildCodexLocalBlock, buildHttpMcpEntryForClient, buildLocalMcpEntryForClient, codexConfigPath, codexHasBlock, configPathFor as clientConfigPathFor, hasJsonMcpEntryForClient, writeCodexBlock, writeFileAtomic, writeJsonMcpEntryForClient, } from "./mcp-config-writers.js";
21
20
  import { findWorkspaceRoot, resolveLocalAppOrigin, resolveWorkspace, } from "../mcp/workspace-resolve.js";
22
21
  const SERVER_NAME_PREFIX = "agent-native";
23
- const CLIENTS = [
24
- "claude-code",
25
- "claude-code-cli",
26
- "codex",
27
- "cowork",
28
- ];
29
22
  function parseArgs(argv) {
30
23
  const out = { _: [], standalone: false, rotate: false };
31
24
  for (let i = 0; i < argv.length; i++) {
@@ -194,199 +187,55 @@ async function mintHostedJwt(cwd) {
194
187
  return undefined;
195
188
  }
196
189
  }
197
- // ---------------------------------------------------------------------------
198
- // Client config file locations + writers
199
- // ---------------------------------------------------------------------------
200
- /**
201
- * Cowork consumes MCP exactly like Claude Code (same JSON server-entry
202
- * shape). The exact on-disk config path for Cowork may differ across builds —
203
- * this is the best-known location. **Confirm before relying on it in
204
- * production.** It is validated against the Claude Code JSON format below.
205
- *
206
- * Resolved lazily (not as a module-level constant) so `os.homedir()` reflects
207
- * the current `$HOME` rather than the value at module-load time.
208
- */
209
- function coworkConfigPath() {
210
- return path.join(os.homedir(), ".cowork", "mcp.json");
211
- }
212
- function claudeCodeProjectConfig(cwd) {
213
- return path.join(envBaseDir(cwd), ".mcp.json");
214
- }
215
- function claudeCodeUserConfig() {
216
- return path.join(os.homedir(), ".claude.json");
217
- }
218
- function codexConfigPath() {
219
- const codexHome = process.env.CODEX_HOME?.trim();
220
- if (codexHome)
221
- return path.join(codexHome, "config.toml");
222
- return path.join(os.homedir(), ".codex", "config.toml");
223
- }
224
- /** The stdio (or http) server entry — shared by Claude Code & Cowork JSON. */
225
- function buildJsonServerEntry(i) {
226
- if (i.hostedUrl) {
227
- return {
228
- type: "http",
229
- url: i.hostedUrl,
230
- ...(i.token ? { headers: { Authorization: `Bearer ${i.token}` } } : {}),
231
- };
232
- }
190
+ function mcpServeArgs(i) {
233
191
  const args = ["mcp", "serve"];
234
192
  if (i.appId)
235
193
  args.push("--app", i.appId);
236
194
  if (i.standalone)
237
195
  args.push("--standalone");
196
+ return args;
197
+ }
198
+ function mcpServeEnv(i) {
238
199
  const env = {};
239
200
  if (i.token)
240
201
  env.ACCESS_TOKEN = i.token;
241
202
  if (i.ownerEmail)
242
203
  env.AGENT_NATIVE_OWNER_EMAIL = i.ownerEmail;
243
- return {
244
- command: "agent-native",
245
- args,
246
- ...(Object.keys(env).length ? { env } : {}),
247
- };
248
- }
249
- function readJsonFile(file) {
250
- try {
251
- const raw = fs.readFileSync(file, "utf-8");
252
- const parsed = JSON.parse(raw);
253
- return parsed && typeof parsed === "object" ? parsed : {};
254
- }
255
- catch {
256
- return {};
257
- }
204
+ return env;
258
205
  }
259
- /** Idempotently write `mcpServers[name] = entry` into a JSON config file. */
260
- function writeJsonMcpEntry(file, name, entry) {
261
- const config = readJsonFile(file);
262
- if (!config.mcpServers || typeof config.mcpServers !== "object") {
263
- config.mcpServers = {};
264
- }
265
- if (entry === null) {
266
- delete config.mcpServers[name];
267
- }
268
- else {
269
- config.mcpServers[name] = entry;
206
+ function buildJsonServerEntry(client, i) {
207
+ if (i.hostedUrl) {
208
+ return buildHttpMcpEntryForClient(client, i.hostedUrl, i.token);
270
209
  }
271
- writeFileAtomic(file, JSON.stringify(config, null, 2) + "\n");
272
- }
273
- function hasJsonMcpEntry(file, name) {
274
- const config = readJsonFile(file);
275
- return !!config?.mcpServers && name in config.mcpServers;
276
- }
277
- // --- Codex TOML (hand-rolled minimal block merge, no new dep) -------------
278
- function tomlQuote(s) {
279
- return `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
280
- }
281
- function codexMcpHeader(name) {
282
- return `[mcp_servers.${tomlQuote(name)}]`;
283
- }
284
- function legacyCodexMcpHeader(name) {
285
- return /^[A-Za-z0-9_-]+$/.test(name) ? `[mcp_servers.${name}]` : null;
210
+ return buildLocalMcpEntryForClient(client, mcpServeArgs(i), mcpServeEnv(i));
286
211
  }
287
212
  function buildCodexBlock(name, i) {
288
- const lines = [codexMcpHeader(name)];
289
213
  if (i.hostedUrl) {
290
- lines.push(`url = ${tomlQuote(i.hostedUrl)}`);
291
- if (i.token) {
292
- lines.push(`http_headers = { "Authorization" = ${tomlQuote(`Bearer ${i.token}`)} }`);
293
- }
294
- return lines.join("\n") + "\n";
295
- }
296
- const args = ["mcp", "serve"];
297
- if (i.appId)
298
- args.push("--app", i.appId);
299
- if (i.standalone)
300
- args.push("--standalone");
301
- lines.push(`command = "agent-native"`);
302
- lines.push(`args = [${args.map(tomlQuote).join(", ")}]`);
303
- const env = {};
304
- if (i.token)
305
- env.ACCESS_TOKEN = i.token;
306
- if (i.ownerEmail)
307
- env.AGENT_NATIVE_OWNER_EMAIL = i.ownerEmail;
308
- if (Object.keys(env).length) {
309
- const inline = Object.entries(env)
310
- .map(([k, v]) => `${k} = ${tomlQuote(v)}`)
311
- .join(", ");
312
- lines.push(`env = { ${inline} }`);
313
- }
314
- return lines.join("\n") + "\n";
315
- }
316
- /**
317
- * Replace (or append) the `[mcp_servers.<name>]` block in a TOML file
318
- * without disturbing other content. We treat a block as the header line plus
319
- * every following line until the next top-level `[` table header or EOF.
320
- */
321
- function writeCodexBlock(file, name, block) {
322
- let content = "";
323
- try {
324
- content = fs.readFileSync(file, "utf-8");
325
- }
326
- catch {
327
- content = "";
328
- }
329
- const headers = new Set([codexMcpHeader(name), legacyCodexMcpHeader(name)].filter(Boolean));
330
- const lines = content.split(/\r?\n/);
331
- const out = [];
332
- let i = 0;
333
- let removed = false;
334
- while (i < lines.length) {
335
- const line = lines[i];
336
- if (headers.has(line.trim())) {
337
- // Skip this block entirely (header + body until next table header).
338
- removed = true;
339
- i++;
340
- while (i < lines.length && !/^\s*\[/.test(lines[i]))
341
- i++;
342
- continue;
343
- }
344
- out.push(line);
345
- i++;
346
- }
347
- let next = out
348
- .join("\n")
349
- .replace(/\n{3,}/g, "\n\n")
350
- .replace(/\n*$/, "\n");
351
- if (block !== null) {
352
- next = next.replace(/\n*$/, "\n");
353
- if (next.trim().length)
354
- next += "\n";
355
- next += block;
356
- }
357
- if (block === null && !removed)
358
- return; // nothing to do
359
- writeFileAtomic(file, next);
360
- }
361
- function codexHasBlock(file, name) {
362
- try {
363
- const content = fs.readFileSync(file, "utf-8");
364
- const headers = new Set([codexMcpHeader(name), legacyCodexMcpHeader(name)].filter(Boolean));
365
- return content.split(/\r?\n/).some((line) => headers.has(line.trim()));
366
- }
367
- catch {
368
- return false;
214
+ return buildCodexHttpBlock(name, i.hostedUrl, i.token);
369
215
  }
216
+ return buildCodexLocalBlock(name, mcpServeArgs(i), mcpServeEnv(i));
370
217
  }
371
218
  // ---------------------------------------------------------------------------
372
219
  // Per-client install/uninstall/status
373
220
  // ---------------------------------------------------------------------------
374
221
  function configPathFor(client, cwd, scope) {
375
- switch (client) {
376
- case "claude-code":
377
- case "claude-code-cli":
378
- return scope === "user"
379
- ? claudeCodeUserConfig()
380
- : claudeCodeProjectConfig(cwd);
381
- case "cowork":
382
- return coworkConfigPath();
383
- case "codex":
384
- return codexConfigPath();
385
- }
222
+ return clientConfigPathFor(client, envBaseDir(cwd), scope);
386
223
  }
387
224
  function serverNameFor(appId) {
388
225
  return `${SERVER_NAME_PREFIX}-${appId}`;
389
226
  }
227
+ function normalizeClientId(raw) {
228
+ const value = (raw ?? "").toLowerCase();
229
+ if (value === "claude" || value === "claude-code-desktop") {
230
+ return "claude-code";
231
+ }
232
+ if (value === "open-code")
233
+ return "opencode";
234
+ if (value === "copilot" || value === "vscode" || value === "vs-code") {
235
+ return "github-copilot";
236
+ }
237
+ return CLIENTS.includes(value) ? value : null;
238
+ }
390
239
  function installForClient(client, inputs, cwd, scope) {
391
240
  const name = inputs.serverName;
392
241
  const file = configPathFor(client, cwd, scope);
@@ -394,7 +243,7 @@ function installForClient(client, inputs, cwd, scope) {
394
243
  writeCodexBlock(file, name, buildCodexBlock(name, inputs));
395
244
  }
396
245
  else {
397
- writeJsonMcpEntry(file, name, buildJsonServerEntry(inputs));
246
+ writeJsonMcpEntryForClient(client, file, name, buildJsonServerEntry(client, inputs));
398
247
  }
399
248
  return file;
400
249
  }
@@ -407,21 +256,20 @@ function uninstallForClient(client, appId, cwd, scope) {
407
256
  writeCodexBlock(file, name, null);
408
257
  return { file, removed: had };
409
258
  }
410
- const had = hasJsonMcpEntry(file, name);
259
+ const had = hasJsonMcpEntryForClient(client, file, name);
411
260
  if (had)
412
- writeJsonMcpEntry(file, name, null);
261
+ writeJsonMcpEntryForClient(client, file, name, null);
413
262
  return { file, removed: had };
414
263
  }
415
264
  function clientHasEntry(client, appId, cwd) {
416
265
  const name = serverNameFor(appId);
417
- // Check both scopes for Claude Code so `status` is informative.
418
- if (client === "claude-code" || client === "claude-code-cli") {
419
- return (hasJsonMcpEntry(claudeCodeProjectConfig(cwd), name) ||
420
- hasJsonMcpEntry(claudeCodeUserConfig(), name));
266
+ if (client === "codex")
267
+ return codexHasBlock(codexConfigPath(), name);
268
+ if (client === "cowork") {
269
+ return hasJsonMcpEntryForClient(client, configPathFor(client, cwd, undefined), name);
421
270
  }
422
- if (client === "cowork")
423
- return hasJsonMcpEntry(coworkConfigPath(), name);
424
- return codexHasBlock(codexConfigPath(), name);
271
+ return (hasJsonMcpEntryForClient(client, configPathFor(client, cwd, "project"), name) ||
272
+ hasJsonMcpEntryForClient(client, configPathFor(client, cwd, "user"), name));
425
273
  }
426
274
  // ---------------------------------------------------------------------------
427
275
  // Subcommands
@@ -434,8 +282,8 @@ async function cmdServe(p) {
434
282
  });
435
283
  }
436
284
  async function cmdInstall(p) {
437
- const client = (p.client ?? "").toLowerCase();
438
- if (!CLIENTS.includes(client)) {
285
+ const client = normalizeClientId(p.client);
286
+ if (!client) {
439
287
  logErr(`Usage: npx @agent-native/core@latest mcp install --client ${CLIENTS.join("|")} ` +
440
288
  `[--app <id>] [--scope user|project]`);
441
289
  process.exit(1);
@@ -483,8 +331,8 @@ async function cmdInstall(p) {
483
331
  logOut(` Restart ${client} to pick up the new MCP server.`);
484
332
  }
485
333
  function cmdUninstall(p) {
486
- const client = (p.client ?? "").toLowerCase();
487
- if (!CLIENTS.includes(client)) {
334
+ const client = normalizeClientId(p.client);
335
+ if (!client) {
488
336
  logErr(`Usage: npx @agent-native/core@latest mcp uninstall --client ${CLIENTS.join("|")} ` +
489
337
  `[--app <id>]`);
490
338
  process.exit(1);
@@ -554,7 +402,7 @@ Usage:
554
402
 
555
403
  npx @agent-native/core@latest mcp install --client <c> [--app <id>] [--scope user|project]
556
404
  Provision a token and write the client's MCP config (idempotent).
557
- Clients: claude-code, claude-code-cli, codex, cowork
405
+ Clients: claude-code, claude-code-cli, codex, cowork, cursor, opencode, github-copilot
558
406
 
559
407
  npx @agent-native/core@latest mcp uninstall --client <c> [--app <id>]
560
408
  Remove the named MCP entry from a client's config (idempotent).
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/cli/mcp.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `agent-native mcp <subcommand>` — connect external coding agents (Claude\n * Code desktop & CLI, Claude Cowork, Codex) to this agent-native app/workspace\n * over MCP.\n *\n * serve Run the MCP stdio transport (this is what client configs spawn).\n * install Provision a token + write the client's MCP config idempotently.\n * uninstall Remove the named entry from a client's MCP config.\n * status Print resolved MCP URL/port, token state, and per-client entries.\n * token Print or rotate the local ACCESS_TOKEN in the workspace .env.\n *\n * Node-only CLI module. Hand-rolled `.env` upsert + minimal TOML block merge\n * keep this dependency-free (no new npm deps).\n */\n\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport { runMCPStdio } from \"../mcp/stdio.js\";\nimport { writeFileAtomic } from \"./mcp-config-writers.js\";\nimport {\n findWorkspaceRoot,\n resolveLocalAppOrigin,\n resolveWorkspace,\n} from \"../mcp/workspace-resolve.js\";\n\nconst SERVER_NAME_PREFIX = \"agent-native\";\n\ntype ClientId = \"claude-code\" | \"claude-code-cli\" | \"codex\" | \"cowork\";\nconst CLIENTS: ClientId[] = [\n \"claude-code\",\n \"claude-code-cli\",\n \"codex\",\n \"cowork\",\n];\n\ninterface ParsedArgs {\n _: string[];\n client?: string;\n app?: string;\n port?: number;\n scope?: string;\n standalone: boolean;\n rotate: boolean;\n}\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const out: ParsedArgs = { _: [], standalone: false, rotate: false };\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n const eat = (flag: string): string | undefined => {\n if (a === flag) return argv[++i];\n if (a.startsWith(`${flag}=`)) return a.slice(flag.length + 1);\n return undefined;\n };\n let v: string | undefined;\n if ((v = eat(\"--client\")) !== undefined) out.client = v;\n else if ((v = eat(\"--app\")) !== undefined) out.app = v;\n else if ((v = eat(\"--port\")) !== undefined) out.port = Number(v);\n else if ((v = eat(\"--scope\")) !== undefined) out.scope = v;\n else if (a === \"--standalone\") out.standalone = true;\n else if (a === \"--rotate\") out.rotate = true;\n else if (!a.startsWith(\"-\")) out._.push(a);\n }\n return out;\n}\n\nfunction logErr(msg: string): void {\n process.stderr.write(`${msg}\\n`);\n}\nfunction logOut(msg: string): void {\n process.stdout.write(`${msg}\\n`);\n}\n\n// ---------------------------------------------------------------------------\n// .env token provisioning (local dev) — hand-rolled idempotent upsert\n// ---------------------------------------------------------------------------\n\n/** Workspace root (or cwd for a standalone app) — where .env lives. */\nfunction envBaseDir(cwd = process.cwd()): string {\n return findWorkspaceRoot(cwd) ?? path.resolve(cwd);\n}\n\n/** Prefer .env.local, else .env. Returns the path we should write to. */\nfunction envFilePath(baseDir: string): string {\n const local = path.join(baseDir, \".env.local\");\n if (fs.existsSync(local)) return local;\n return path.join(baseDir, \".env\");\n}\n\nfunction readEnvFile(file: string): string {\n try {\n return fs.readFileSync(file, \"utf-8\");\n } catch {\n return \"\";\n }\n}\n\n/** Read a single key from a dotenv-format string (last assignment wins). */\nfunction getEnvValue(content: string, key: string): string | undefined {\n let found: string | undefined;\n for (const line of content.split(/\\r?\\n/)) {\n const m = line.match(/^\\s*([A-Z0-9_]+)\\s*=\\s*(.*)\\s*$/i);\n if (m && m[1] === key) {\n found = m[2].replace(/^[\"']|[\"']$/g, \"\");\n }\n }\n return found;\n}\n\n/**\n * Idempotently set `key=value` in the dotenv file. If the key already exists\n * we leave it untouched unless `force` is set (used by `token --rotate`).\n * Never clobbers an existing token implicitly.\n */\nfunction upsertEnv(\n file: string,\n key: string,\n value: string,\n force = false,\n): { changed: boolean; value: string } {\n const content = readEnvFile(file);\n const existing = getEnvValue(content, key);\n if (existing && !force) return { changed: false, value: existing };\n\n const line = `${key}=${value}`;\n let next: string;\n if (new RegExp(`^\\\\s*${key}\\\\s*=`, \"m\").test(content)) {\n next = content.replace(new RegExp(`^\\\\s*${key}\\\\s*=.*$`, \"m\"), line);\n } else {\n next =\n content.length === 0\n ? `${line}\\n`\n : `${content.replace(/\\n*$/, \"\")}\\n${line}\\n`;\n }\n writeFileAtomic(file, next);\n return { changed: true, value };\n}\n\nfunction generateToken(): string {\n return crypto.randomBytes(24).toString(\"base64url\");\n}\n\n/**\n * Ensure a local ACCESS_TOKEN exists in the workspace .env and return it.\n * Existing tokens are reused (never clobbered). Set `rotate` to replace it.\n */\nfunction ensureLocalToken(\n cwd: string,\n rotate = false,\n): { token: string; file: string; created: boolean } {\n const baseDir = envBaseDir(cwd);\n const file = envFilePath(baseDir);\n const content = readEnvFile(file);\n const existing = getEnvValue(content, \"ACCESS_TOKEN\");\n if (existing && !rotate) {\n return { token: existing, file, created: false };\n }\n const token = generateToken();\n upsertEnv(file, \"ACCESS_TOKEN\", token, true);\n return { token, file, created: true };\n}\n\n// ---------------------------------------------------------------------------\n// Hosted vs local detection\n// ---------------------------------------------------------------------------\n\n/**\n * Detect a hosted deployment URL. When the workspace .env points at a hosted\n * origin (APP_URL / BETTER_AUTH_URL with a non-localhost host) we write an\n * `http` client entry pointing at `<origin>/_agent-native/mcp` with a JWT\n * bearer instead of a stdio entry.\n */\nfunction detectHostedUrl(cwd: string): string | undefined {\n const baseDir = envBaseDir(cwd);\n const content =\n readEnvFile(path.join(baseDir, \".env.local\")) +\n \"\\n\" +\n readEnvFile(path.join(baseDir, \".env\"));\n for (const key of [\"AGENT_NATIVE_MCP_URL\", \"APP_URL\", \"BETTER_AUTH_URL\"]) {\n const v = getEnvValue(content, key);\n if (!v) continue;\n try {\n const u = new URL(v);\n if (!/^(localhost|127\\.0\\.0\\.1|\\[::1\\])$/.test(u.hostname)) {\n return `${u.origin}/_agent-native/mcp`;\n }\n } catch {\n // not a URL — skip\n }\n }\n return undefined;\n}\n\nasync function mintHostedJwt(cwd: string): Promise<string | undefined> {\n // Reuse the existing A2A signer — do not reinvent JWT minting.\n const owner =\n process.env.AGENT_NATIVE_OWNER_EMAIL ||\n process.env.OWNER_EMAIL ||\n \"owner@localhost\";\n if (!process.env.A2A_SECRET) {\n const baseDir = envBaseDir(cwd);\n const content =\n readEnvFile(path.join(baseDir, \".env.local\")) +\n \"\\n\" +\n readEnvFile(path.join(baseDir, \".env\"));\n const secret = getEnvValue(content, \"A2A_SECRET\");\n if (secret) process.env.A2A_SECRET = secret;\n }\n try {\n const { signA2AToken } = await import(\"../a2a/client.js\");\n return await signA2AToken(owner, undefined, undefined, {\n preferGlobalSecret: true,\n expiresIn: \"30d\",\n });\n } catch (err: any) {\n logErr(\n ` Could not mint a hosted JWT (${err?.message ?? err}). ` +\n `Set A2A_SECRET in your workspace .env, or use the local stdio entry.`,\n );\n return undefined;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Client config file locations + writers\n// ---------------------------------------------------------------------------\n\n/**\n * Cowork consumes MCP exactly like Claude Code (same JSON server-entry\n * shape). The exact on-disk config path for Cowork may differ across builds —\n * this is the best-known location. **Confirm before relying on it in\n * production.** It is validated against the Claude Code JSON format below.\n *\n * Resolved lazily (not as a module-level constant) so `os.homedir()` reflects\n * the current `$HOME` rather than the value at module-load time.\n */\nfunction coworkConfigPath(): string {\n return path.join(os.homedir(), \".cowork\", \"mcp.json\");\n}\n\nfunction claudeCodeProjectConfig(cwd: string): string {\n return path.join(envBaseDir(cwd), \".mcp.json\");\n}\nfunction claudeCodeUserConfig(): string {\n return path.join(os.homedir(), \".claude.json\");\n}\nfunction codexConfigPath(): string {\n const codexHome = process.env.CODEX_HOME?.trim();\n if (codexHome) return path.join(codexHome, \"config.toml\");\n return path.join(os.homedir(), \".codex\", \"config.toml\");\n}\n\ninterface ServerEntryInputs {\n serverName: string;\n appId: string;\n token?: string;\n ownerEmail?: string;\n hostedUrl?: string;\n standalone: boolean;\n}\n\n/** The stdio (or http) server entry — shared by Claude Code & Cowork JSON. */\nfunction buildJsonServerEntry(i: ServerEntryInputs): Record<string, unknown> {\n if (i.hostedUrl) {\n return {\n type: \"http\",\n url: i.hostedUrl,\n ...(i.token ? { headers: { Authorization: `Bearer ${i.token}` } } : {}),\n };\n }\n const args = [\"mcp\", \"serve\"];\n if (i.appId) args.push(\"--app\", i.appId);\n if (i.standalone) args.push(\"--standalone\");\n const env: Record<string, string> = {};\n if (i.token) env.ACCESS_TOKEN = i.token;\n if (i.ownerEmail) env.AGENT_NATIVE_OWNER_EMAIL = i.ownerEmail;\n return {\n command: \"agent-native\",\n args,\n ...(Object.keys(env).length ? { env } : {}),\n };\n}\n\nfunction readJsonFile(file: string): Record<string, any> {\n try {\n const raw = fs.readFileSync(file, \"utf-8\");\n const parsed = JSON.parse(raw);\n return parsed && typeof parsed === \"object\" ? parsed : {};\n } catch {\n return {};\n }\n}\n\n/** Idempotently write `mcpServers[name] = entry` into a JSON config file. */\nfunction writeJsonMcpEntry(\n file: string,\n name: string,\n entry: Record<string, unknown> | null,\n): void {\n const config = readJsonFile(file);\n if (!config.mcpServers || typeof config.mcpServers !== \"object\") {\n config.mcpServers = {};\n }\n if (entry === null) {\n delete config.mcpServers[name];\n } else {\n config.mcpServers[name] = entry;\n }\n writeFileAtomic(file, JSON.stringify(config, null, 2) + \"\\n\");\n}\n\nfunction hasJsonMcpEntry(file: string, name: string): boolean {\n const config = readJsonFile(file);\n return !!config?.mcpServers && name in config.mcpServers;\n}\n\n// --- Codex TOML (hand-rolled minimal block merge, no new dep) -------------\n\nfunction tomlQuote(s: string): string {\n return `\"${s.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"')}\"`;\n}\n\nfunction codexMcpHeader(name: string): string {\n return `[mcp_servers.${tomlQuote(name)}]`;\n}\n\nfunction legacyCodexMcpHeader(name: string): string | null {\n return /^[A-Za-z0-9_-]+$/.test(name) ? `[mcp_servers.${name}]` : null;\n}\n\nfunction buildCodexBlock(name: string, i: ServerEntryInputs): string {\n const lines: string[] = [codexMcpHeader(name)];\n if (i.hostedUrl) {\n lines.push(`url = ${tomlQuote(i.hostedUrl)}`);\n if (i.token) {\n lines.push(\n `http_headers = { \"Authorization\" = ${tomlQuote(\n `Bearer ${i.token}`,\n )} }`,\n );\n }\n return lines.join(\"\\n\") + \"\\n\";\n }\n\n const args = [\"mcp\", \"serve\"];\n if (i.appId) args.push(\"--app\", i.appId);\n if (i.standalone) args.push(\"--standalone\");\n lines.push(`command = \"agent-native\"`);\n lines.push(`args = [${args.map(tomlQuote).join(\", \")}]`);\n const env: Record<string, string> = {};\n if (i.token) env.ACCESS_TOKEN = i.token;\n if (i.ownerEmail) env.AGENT_NATIVE_OWNER_EMAIL = i.ownerEmail;\n if (Object.keys(env).length) {\n const inline = Object.entries(env)\n .map(([k, v]) => `${k} = ${tomlQuote(v)}`)\n .join(\", \");\n lines.push(`env = { ${inline} }`);\n }\n return lines.join(\"\\n\") + \"\\n\";\n}\n\n/**\n * Replace (or append) the `[mcp_servers.<name>]` block in a TOML file\n * without disturbing other content. We treat a block as the header line plus\n * every following line until the next top-level `[` table header or EOF.\n */\nfunction writeCodexBlock(\n file: string,\n name: string,\n block: string | null,\n): void {\n let content = \"\";\n try {\n content = fs.readFileSync(file, \"utf-8\");\n } catch {\n content = \"\";\n }\n\n const headers = new Set(\n [codexMcpHeader(name), legacyCodexMcpHeader(name)].filter(\n Boolean,\n ) as string[],\n );\n const lines = content.split(/\\r?\\n/);\n const out: string[] = [];\n let i = 0;\n let removed = false;\n while (i < lines.length) {\n const line = lines[i];\n if (headers.has(line.trim())) {\n // Skip this block entirely (header + body until next table header).\n removed = true;\n i++;\n while (i < lines.length && !/^\\s*\\[/.test(lines[i])) i++;\n continue;\n }\n out.push(line);\n i++;\n }\n\n let next = out\n .join(\"\\n\")\n .replace(/\\n{3,}/g, \"\\n\\n\")\n .replace(/\\n*$/, \"\\n\");\n if (block !== null) {\n next = next.replace(/\\n*$/, \"\\n\");\n if (next.trim().length) next += \"\\n\";\n next += block;\n }\n if (block === null && !removed) return; // nothing to do\n\n writeFileAtomic(file, next);\n}\n\nfunction codexHasBlock(file: string, name: string): boolean {\n try {\n const content = fs.readFileSync(file, \"utf-8\");\n const headers = new Set(\n [codexMcpHeader(name), legacyCodexMcpHeader(name)].filter(\n Boolean,\n ) as string[],\n );\n return content.split(/\\r?\\n/).some((line) => headers.has(line.trim()));\n } catch {\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Per-client install/uninstall/status\n// ---------------------------------------------------------------------------\n\nfunction configPathFor(\n client: ClientId,\n cwd: string,\n scope: string | undefined,\n): string {\n switch (client) {\n case \"claude-code\":\n case \"claude-code-cli\":\n return scope === \"user\"\n ? claudeCodeUserConfig()\n : claudeCodeProjectConfig(cwd);\n case \"cowork\":\n return coworkConfigPath();\n case \"codex\":\n return codexConfigPath();\n }\n}\n\nfunction serverNameFor(appId: string): string {\n return `${SERVER_NAME_PREFIX}-${appId}`;\n}\n\nfunction installForClient(\n client: ClientId,\n inputs: ServerEntryInputs,\n cwd: string,\n scope: string | undefined,\n): string {\n const name = inputs.serverName;\n const file = configPathFor(client, cwd, scope);\n if (client === \"codex\") {\n writeCodexBlock(file, name, buildCodexBlock(name, inputs));\n } else {\n writeJsonMcpEntry(file, name, buildJsonServerEntry(inputs));\n }\n return file;\n}\n\nfunction uninstallForClient(\n client: ClientId,\n appId: string,\n cwd: string,\n scope: string | undefined,\n): { file: string; removed: boolean } {\n const name = serverNameFor(appId);\n const file = configPathFor(client, cwd, scope);\n if (client === \"codex\") {\n const had = codexHasBlock(file, name);\n if (had) writeCodexBlock(file, name, null);\n return { file, removed: had };\n }\n const had = hasJsonMcpEntry(file, name);\n if (had) writeJsonMcpEntry(file, name, null);\n return { file, removed: had };\n}\n\nfunction clientHasEntry(client: ClientId, appId: string, cwd: string): boolean {\n const name = serverNameFor(appId);\n // Check both scopes for Claude Code so `status` is informative.\n if (client === \"claude-code\" || client === \"claude-code-cli\") {\n return (\n hasJsonMcpEntry(claudeCodeProjectConfig(cwd), name) ||\n hasJsonMcpEntry(claudeCodeUserConfig(), name)\n );\n }\n if (client === \"cowork\") return hasJsonMcpEntry(coworkConfigPath(), name);\n return codexHasBlock(codexConfigPath(), name);\n}\n\n// ---------------------------------------------------------------------------\n// Subcommands\n// ---------------------------------------------------------------------------\n\nasync function cmdServe(p: ParsedArgs): Promise<void> {\n await runMCPStdio({\n appId: p.app,\n port: p.port,\n standalone: p.standalone,\n });\n}\n\nasync function cmdInstall(p: ParsedArgs): Promise<void> {\n const client = (p.client ?? \"\").toLowerCase() as ClientId;\n if (!CLIENTS.includes(client)) {\n logErr(\n `Usage: npx @agent-native/core@latest mcp install --client ${CLIENTS.join(\"|\")} ` +\n `[--app <id>] [--scope user|project]`,\n );\n process.exit(1);\n }\n const cwd = process.cwd();\n\n // Resolve which app this entry targets (default = workspace default app).\n let appId = p.app;\n if (!appId) {\n try {\n const resolved = await resolveLocalAppOrigin({ cwd });\n appId = resolved.appId;\n } catch {\n appId = \"app\";\n }\n }\n const serverName = serverNameFor(appId);\n\n const hostedUrl = detectHostedUrl(cwd);\n const ownerEmail = process.env.AGENT_NATIVE_OWNER_EMAIL;\n\n let token: string | undefined;\n if (hostedUrl) {\n token = await mintHostedJwt(cwd);\n logOut(`Detected hosted deployment: ${hostedUrl}`);\n } else {\n const t = ensureLocalToken(cwd, false);\n token = t.token;\n logOut(\n t.created\n ? `Provisioned ACCESS_TOKEN in ${t.file}`\n : `Reusing existing ACCESS_TOKEN from ${t.file}`,\n );\n }\n\n const inputs: ServerEntryInputs = {\n serverName,\n appId: appId!,\n token,\n ownerEmail,\n hostedUrl,\n standalone: p.standalone,\n };\n\n const file = installForClient(client, inputs, cwd, p.scope);\n logOut(`Installed \"${serverName}\" for ${client} → ${file}`);\n logOut(\n hostedUrl\n ? ` Mode: http (${hostedUrl})`\n : ` Mode: stdio (npx @agent-native/core@latest mcp serve --app ${appId}${\n p.standalone ? \" --standalone\" : \"\"\n })`,\n );\n logOut(` Restart ${client} to pick up the new MCP server.`);\n}\n\nfunction cmdUninstall(p: ParsedArgs): void {\n const client = (p.client ?? \"\").toLowerCase() as ClientId;\n if (!CLIENTS.includes(client)) {\n logErr(\n `Usage: npx @agent-native/core@latest mcp uninstall --client ${CLIENTS.join(\"|\")} ` +\n `[--app <id>]`,\n );\n process.exit(1);\n }\n const cwd = process.cwd();\n const appId = p.app ?? \"app\";\n const { file, removed } = uninstallForClient(client, appId, cwd, p.scope);\n logOut(\n removed\n ? `Removed \"${serverNameFor(appId)}\" from ${client} → ${file}`\n : `No \"${serverNameFor(appId)}\" entry found for ${client} (${file}) — nothing to do.`,\n );\n}\n\nasync function cmdStatus(): Promise<void> {\n const cwd = process.cwd();\n let appId = \"app\";\n let origin = \"(app not running)\";\n let port: number | undefined;\n try {\n const resolved = await resolveLocalAppOrigin({ cwd });\n appId = resolved.appId;\n origin = resolved.origin;\n const ws = await resolveWorkspace(cwd);\n port = ws.apps.find((a) => a.id === appId)?.port;\n } catch (err: any) {\n logErr(` Could not resolve app: ${err?.message ?? err}`);\n }\n\n const hostedUrl = detectHostedUrl(cwd);\n const baseDir = envBaseDir(cwd);\n const envContent =\n readEnvFile(path.join(baseDir, \".env.local\")) +\n \"\\n\" +\n readEnvFile(path.join(baseDir, \".env\"));\n const hasToken = !!getEnvValue(envContent, \"ACCESS_TOKEN\");\n const hasA2A =\n !!process.env.A2A_SECRET || !!getEnvValue(envContent, \"A2A_SECRET\");\n\n logOut(`Agent-Native MCP status`);\n logOut(` App: ${appId}`);\n logOut(\n hostedUrl\n ? ` MCP URL: ${hostedUrl} (hosted)`\n : ` MCP URL: ${origin}/_agent-native/mcp${\n port ? ` (port ${port})` : \"\"\n }`,\n );\n logOut(` ACCESS_TOKEN: ${hasToken ? \"set\" : \"not set\"} (.env)`);\n logOut(` A2A_SECRET: ${hasA2A ? \"set\" : \"not set\"}`);\n logOut(` Clients:`);\n for (const client of CLIENTS) {\n const present = clientHasEntry(client, appId, cwd);\n logOut(` ${client.padEnd(18)} ${present ? \"configured\" : \"—\"}`);\n }\n}\n\nfunction cmdToken(p: ParsedArgs): void {\n const cwd = process.cwd();\n const t = ensureLocalToken(cwd, p.rotate);\n logOut(\n p.rotate\n ? `Rotated ACCESS_TOKEN in ${t.file}`\n : t.created\n ? `Provisioned ACCESS_TOKEN in ${t.file}`\n : `ACCESS_TOKEN (${t.file}):`,\n );\n logOut(t.token);\n if (p.rotate) {\n logOut(\n ` Re-run \\`npx @agent-native/core@latest mcp install --client <c>\\` so client configs ` +\n `pick up the new token.`,\n );\n }\n}\n\nconst HELP = `npx @agent-native/core@latest mcp — connect external coding agents over MCP\n\nUsage:\n npx @agent-native/core@latest mcp serve [--app <id>] [--port <n>] [--standalone]\n Run the MCP stdio transport (what client configs spawn).\n Default: proxy to the running local app; --standalone builds from disk.\n\n npx @agent-native/core@latest mcp install --client <c> [--app <id>] [--scope user|project]\n Provision a token and write the client's MCP config (idempotent).\n Clients: claude-code, claude-code-cli, codex, cowork\n\n npx @agent-native/core@latest mcp uninstall --client <c> [--app <id>]\n Remove the named MCP entry from a client's config (idempotent).\n\n npx @agent-native/core@latest mcp status\n Show resolved MCP URL/port, token state, and per-client entries.\n\n npx @agent-native/core@latest mcp token [--rotate]\n Print (or rotate) the local ACCESS_TOKEN in the workspace .env.`;\n\nexport async function runMcp(args: string[]): Promise<void> {\n const p = parseArgs(args);\n const sub = p._[0];\n\n switch (sub) {\n case \"serve\":\n await cmdServe(p);\n return;\n case \"install\":\n await cmdInstall(p);\n return;\n case \"uninstall\":\n cmdUninstall(p);\n return;\n case \"status\":\n await cmdStatus();\n return;\n case \"token\":\n cmdToken(p);\n return;\n case undefined:\n case \"--help\":\n case \"-h\":\n case \"help\":\n logOut(HELP);\n return;\n default:\n logErr(`Unknown mcp subcommand: ${sub}`);\n logOut(HELP);\n process.exit(1);\n }\n}\n"]}
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../src/cli/mcp.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `agent-native mcp <subcommand>` — connect external coding agents (Claude\n * Code desktop & CLI, Claude Cowork, Codex, Cursor, OpenCode, GitHub Copilot /\n * VS Code) to this agent-native app/workspace over MCP.\n *\n * serve Run the MCP stdio transport (this is what client configs spawn).\n * install Provision a token + write the client's MCP config idempotently.\n * uninstall Remove the named entry from a client's MCP config.\n * status Print resolved MCP URL/port, token state, and per-client entries.\n * token Print or rotate the local ACCESS_TOKEN in the workspace .env.\n *\n * Node-only CLI module. Hand-rolled `.env` upsert + minimal TOML block merge\n * keep this dependency-free (no new npm deps).\n */\n\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\nimport { runMCPStdio } from \"../mcp/stdio.js\";\nimport {\n CLIENTS,\n type ClientId,\n buildCodexHttpBlock,\n buildCodexLocalBlock,\n buildHttpMcpEntryForClient,\n buildLocalMcpEntryForClient,\n codexConfigPath,\n codexHasBlock,\n configPathFor as clientConfigPathFor,\n hasJsonMcpEntryForClient,\n writeCodexBlock,\n writeFileAtomic,\n writeJsonMcpEntryForClient,\n} from \"./mcp-config-writers.js\";\nimport {\n findWorkspaceRoot,\n resolveLocalAppOrigin,\n resolveWorkspace,\n} from \"../mcp/workspace-resolve.js\";\n\nconst SERVER_NAME_PREFIX = \"agent-native\";\n\ninterface ParsedArgs {\n _: string[];\n client?: string;\n app?: string;\n port?: number;\n scope?: string;\n standalone: boolean;\n rotate: boolean;\n}\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const out: ParsedArgs = { _: [], standalone: false, rotate: false };\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n const eat = (flag: string): string | undefined => {\n if (a === flag) return argv[++i];\n if (a.startsWith(`${flag}=`)) return a.slice(flag.length + 1);\n return undefined;\n };\n let v: string | undefined;\n if ((v = eat(\"--client\")) !== undefined) out.client = v;\n else if ((v = eat(\"--app\")) !== undefined) out.app = v;\n else if ((v = eat(\"--port\")) !== undefined) out.port = Number(v);\n else if ((v = eat(\"--scope\")) !== undefined) out.scope = v;\n else if (a === \"--standalone\") out.standalone = true;\n else if (a === \"--rotate\") out.rotate = true;\n else if (!a.startsWith(\"-\")) out._.push(a);\n }\n return out;\n}\n\nfunction logErr(msg: string): void {\n process.stderr.write(`${msg}\\n`);\n}\nfunction logOut(msg: string): void {\n process.stdout.write(`${msg}\\n`);\n}\n\n// ---------------------------------------------------------------------------\n// .env token provisioning (local dev) — hand-rolled idempotent upsert\n// ---------------------------------------------------------------------------\n\n/** Workspace root (or cwd for a standalone app) — where .env lives. */\nfunction envBaseDir(cwd = process.cwd()): string {\n return findWorkspaceRoot(cwd) ?? path.resolve(cwd);\n}\n\n/** Prefer .env.local, else .env. Returns the path we should write to. */\nfunction envFilePath(baseDir: string): string {\n const local = path.join(baseDir, \".env.local\");\n if (fs.existsSync(local)) return local;\n return path.join(baseDir, \".env\");\n}\n\nfunction readEnvFile(file: string): string {\n try {\n return fs.readFileSync(file, \"utf-8\");\n } catch {\n return \"\";\n }\n}\n\n/** Read a single key from a dotenv-format string (last assignment wins). */\nfunction getEnvValue(content: string, key: string): string | undefined {\n let found: string | undefined;\n for (const line of content.split(/\\r?\\n/)) {\n const m = line.match(/^\\s*([A-Z0-9_]+)\\s*=\\s*(.*)\\s*$/i);\n if (m && m[1] === key) {\n found = m[2].replace(/^[\"']|[\"']$/g, \"\");\n }\n }\n return found;\n}\n\n/**\n * Idempotently set `key=value` in the dotenv file. If the key already exists\n * we leave it untouched unless `force` is set (used by `token --rotate`).\n * Never clobbers an existing token implicitly.\n */\nfunction upsertEnv(\n file: string,\n key: string,\n value: string,\n force = false,\n): { changed: boolean; value: string } {\n const content = readEnvFile(file);\n const existing = getEnvValue(content, key);\n if (existing && !force) return { changed: false, value: existing };\n\n const line = `${key}=${value}`;\n let next: string;\n if (new RegExp(`^\\\\s*${key}\\\\s*=`, \"m\").test(content)) {\n next = content.replace(new RegExp(`^\\\\s*${key}\\\\s*=.*$`, \"m\"), line);\n } else {\n next =\n content.length === 0\n ? `${line}\\n`\n : `${content.replace(/\\n*$/, \"\")}\\n${line}\\n`;\n }\n writeFileAtomic(file, next);\n return { changed: true, value };\n}\n\nfunction generateToken(): string {\n return crypto.randomBytes(24).toString(\"base64url\");\n}\n\n/**\n * Ensure a local ACCESS_TOKEN exists in the workspace .env and return it.\n * Existing tokens are reused (never clobbered). Set `rotate` to replace it.\n */\nfunction ensureLocalToken(\n cwd: string,\n rotate = false,\n): { token: string; file: string; created: boolean } {\n const baseDir = envBaseDir(cwd);\n const file = envFilePath(baseDir);\n const content = readEnvFile(file);\n const existing = getEnvValue(content, \"ACCESS_TOKEN\");\n if (existing && !rotate) {\n return { token: existing, file, created: false };\n }\n const token = generateToken();\n upsertEnv(file, \"ACCESS_TOKEN\", token, true);\n return { token, file, created: true };\n}\n\n// ---------------------------------------------------------------------------\n// Hosted vs local detection\n// ---------------------------------------------------------------------------\n\n/**\n * Detect a hosted deployment URL. When the workspace .env points at a hosted\n * origin (APP_URL / BETTER_AUTH_URL with a non-localhost host) we write an\n * `http` client entry pointing at `<origin>/_agent-native/mcp` with a JWT\n * bearer instead of a stdio entry.\n */\nfunction detectHostedUrl(cwd: string): string | undefined {\n const baseDir = envBaseDir(cwd);\n const content =\n readEnvFile(path.join(baseDir, \".env.local\")) +\n \"\\n\" +\n readEnvFile(path.join(baseDir, \".env\"));\n for (const key of [\"AGENT_NATIVE_MCP_URL\", \"APP_URL\", \"BETTER_AUTH_URL\"]) {\n const v = getEnvValue(content, key);\n if (!v) continue;\n try {\n const u = new URL(v);\n if (!/^(localhost|127\\.0\\.0\\.1|\\[::1\\])$/.test(u.hostname)) {\n return `${u.origin}/_agent-native/mcp`;\n }\n } catch {\n // not a URL — skip\n }\n }\n return undefined;\n}\n\nasync function mintHostedJwt(cwd: string): Promise<string | undefined> {\n // Reuse the existing A2A signer — do not reinvent JWT minting.\n const owner =\n process.env.AGENT_NATIVE_OWNER_EMAIL ||\n process.env.OWNER_EMAIL ||\n \"owner@localhost\";\n if (!process.env.A2A_SECRET) {\n const baseDir = envBaseDir(cwd);\n const content =\n readEnvFile(path.join(baseDir, \".env.local\")) +\n \"\\n\" +\n readEnvFile(path.join(baseDir, \".env\"));\n const secret = getEnvValue(content, \"A2A_SECRET\");\n if (secret) process.env.A2A_SECRET = secret;\n }\n try {\n const { signA2AToken } = await import(\"../a2a/client.js\");\n return await signA2AToken(owner, undefined, undefined, {\n preferGlobalSecret: true,\n expiresIn: \"30d\",\n });\n } catch (err: any) {\n logErr(\n ` Could not mint a hosted JWT (${err?.message ?? err}). ` +\n `Set A2A_SECRET in your workspace .env, or use the local stdio entry.`,\n );\n return undefined;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Client config entries\n// ---------------------------------------------------------------------------\n\ninterface ServerEntryInputs {\n serverName: string;\n appId: string;\n token?: string;\n ownerEmail?: string;\n hostedUrl?: string;\n standalone: boolean;\n}\n\nfunction mcpServeArgs(i: ServerEntryInputs): string[] {\n const args = [\"mcp\", \"serve\"];\n if (i.appId) args.push(\"--app\", i.appId);\n if (i.standalone) args.push(\"--standalone\");\n return args;\n}\n\nfunction mcpServeEnv(i: ServerEntryInputs): Record<string, string> {\n const env: Record<string, string> = {};\n if (i.token) env.ACCESS_TOKEN = i.token;\n if (i.ownerEmail) env.AGENT_NATIVE_OWNER_EMAIL = i.ownerEmail;\n return env;\n}\n\nfunction buildJsonServerEntry(\n client: ClientId,\n i: ServerEntryInputs,\n): Record<string, unknown> {\n if (i.hostedUrl) {\n return buildHttpMcpEntryForClient(client, i.hostedUrl, i.token);\n }\n return buildLocalMcpEntryForClient(client, mcpServeArgs(i), mcpServeEnv(i));\n}\n\nfunction buildCodexBlock(name: string, i: ServerEntryInputs): string {\n if (i.hostedUrl) {\n return buildCodexHttpBlock(name, i.hostedUrl, i.token);\n }\n return buildCodexLocalBlock(name, mcpServeArgs(i), mcpServeEnv(i));\n}\n\n// ---------------------------------------------------------------------------\n// Per-client install/uninstall/status\n// ---------------------------------------------------------------------------\n\nfunction configPathFor(\n client: ClientId,\n cwd: string,\n scope: string | undefined,\n): string {\n return clientConfigPathFor(client, envBaseDir(cwd), scope);\n}\n\nfunction serverNameFor(appId: string): string {\n return `${SERVER_NAME_PREFIX}-${appId}`;\n}\n\nfunction normalizeClientId(raw: string | undefined): ClientId | null {\n const value = (raw ?? \"\").toLowerCase();\n if (value === \"claude\" || value === \"claude-code-desktop\") {\n return \"claude-code\";\n }\n if (value === \"open-code\") return \"opencode\";\n if (value === \"copilot\" || value === \"vscode\" || value === \"vs-code\") {\n return \"github-copilot\";\n }\n return (CLIENTS as string[]).includes(value) ? (value as ClientId) : null;\n}\n\nfunction installForClient(\n client: ClientId,\n inputs: ServerEntryInputs,\n cwd: string,\n scope: string | undefined,\n): string {\n const name = inputs.serverName;\n const file = configPathFor(client, cwd, scope);\n if (client === \"codex\") {\n writeCodexBlock(file, name, buildCodexBlock(name, inputs));\n } else {\n writeJsonMcpEntryForClient(\n client,\n file,\n name,\n buildJsonServerEntry(client, inputs),\n );\n }\n return file;\n}\n\nfunction uninstallForClient(\n client: ClientId,\n appId: string,\n cwd: string,\n scope: string | undefined,\n): { file: string; removed: boolean } {\n const name = serverNameFor(appId);\n const file = configPathFor(client, cwd, scope);\n if (client === \"codex\") {\n const had = codexHasBlock(file, name);\n if (had) writeCodexBlock(file, name, null);\n return { file, removed: had };\n }\n const had = hasJsonMcpEntryForClient(client, file, name);\n if (had) writeJsonMcpEntryForClient(client, file, name, null);\n return { file, removed: had };\n}\n\nfunction clientHasEntry(client: ClientId, appId: string, cwd: string): boolean {\n const name = serverNameFor(appId);\n if (client === \"codex\") return codexHasBlock(codexConfigPath(), name);\n if (client === \"cowork\") {\n return hasJsonMcpEntryForClient(\n client,\n configPathFor(client, cwd, undefined),\n name,\n );\n }\n return (\n hasJsonMcpEntryForClient(\n client,\n configPathFor(client, cwd, \"project\"),\n name,\n ) ||\n hasJsonMcpEntryForClient(client, configPathFor(client, cwd, \"user\"), name)\n );\n}\n\n// ---------------------------------------------------------------------------\n// Subcommands\n// ---------------------------------------------------------------------------\n\nasync function cmdServe(p: ParsedArgs): Promise<void> {\n await runMCPStdio({\n appId: p.app,\n port: p.port,\n standalone: p.standalone,\n });\n}\n\nasync function cmdInstall(p: ParsedArgs): Promise<void> {\n const client = normalizeClientId(p.client);\n if (!client) {\n logErr(\n `Usage: npx @agent-native/core@latest mcp install --client ${CLIENTS.join(\"|\")} ` +\n `[--app <id>] [--scope user|project]`,\n );\n process.exit(1);\n }\n const cwd = process.cwd();\n\n // Resolve which app this entry targets (default = workspace default app).\n let appId = p.app;\n if (!appId) {\n try {\n const resolved = await resolveLocalAppOrigin({ cwd });\n appId = resolved.appId;\n } catch {\n appId = \"app\";\n }\n }\n const serverName = serverNameFor(appId);\n\n const hostedUrl = detectHostedUrl(cwd);\n const ownerEmail = process.env.AGENT_NATIVE_OWNER_EMAIL;\n\n let token: string | undefined;\n if (hostedUrl) {\n token = await mintHostedJwt(cwd);\n logOut(`Detected hosted deployment: ${hostedUrl}`);\n } else {\n const t = ensureLocalToken(cwd, false);\n token = t.token;\n logOut(\n t.created\n ? `Provisioned ACCESS_TOKEN in ${t.file}`\n : `Reusing existing ACCESS_TOKEN from ${t.file}`,\n );\n }\n\n const inputs: ServerEntryInputs = {\n serverName,\n appId: appId!,\n token,\n ownerEmail,\n hostedUrl,\n standalone: p.standalone,\n };\n\n const file = installForClient(client, inputs, cwd, p.scope);\n logOut(`Installed \"${serverName}\" for ${client} → ${file}`);\n logOut(\n hostedUrl\n ? ` Mode: http (${hostedUrl})`\n : ` Mode: stdio (npx @agent-native/core@latest mcp serve --app ${appId}${\n p.standalone ? \" --standalone\" : \"\"\n })`,\n );\n logOut(` Restart ${client} to pick up the new MCP server.`);\n}\n\nfunction cmdUninstall(p: ParsedArgs): void {\n const client = normalizeClientId(p.client);\n if (!client) {\n logErr(\n `Usage: npx @agent-native/core@latest mcp uninstall --client ${CLIENTS.join(\"|\")} ` +\n `[--app <id>]`,\n );\n process.exit(1);\n }\n const cwd = process.cwd();\n const appId = p.app ?? \"app\";\n const { file, removed } = uninstallForClient(client, appId, cwd, p.scope);\n logOut(\n removed\n ? `Removed \"${serverNameFor(appId)}\" from ${client} → ${file}`\n : `No \"${serverNameFor(appId)}\" entry found for ${client} (${file}) — nothing to do.`,\n );\n}\n\nasync function cmdStatus(): Promise<void> {\n const cwd = process.cwd();\n let appId = \"app\";\n let origin = \"(app not running)\";\n let port: number | undefined;\n try {\n const resolved = await resolveLocalAppOrigin({ cwd });\n appId = resolved.appId;\n origin = resolved.origin;\n const ws = await resolveWorkspace(cwd);\n port = ws.apps.find((a) => a.id === appId)?.port;\n } catch (err: any) {\n logErr(` Could not resolve app: ${err?.message ?? err}`);\n }\n\n const hostedUrl = detectHostedUrl(cwd);\n const baseDir = envBaseDir(cwd);\n const envContent =\n readEnvFile(path.join(baseDir, \".env.local\")) +\n \"\\n\" +\n readEnvFile(path.join(baseDir, \".env\"));\n const hasToken = !!getEnvValue(envContent, \"ACCESS_TOKEN\");\n const hasA2A =\n !!process.env.A2A_SECRET || !!getEnvValue(envContent, \"A2A_SECRET\");\n\n logOut(`Agent-Native MCP status`);\n logOut(` App: ${appId}`);\n logOut(\n hostedUrl\n ? ` MCP URL: ${hostedUrl} (hosted)`\n : ` MCP URL: ${origin}/_agent-native/mcp${\n port ? ` (port ${port})` : \"\"\n }`,\n );\n logOut(` ACCESS_TOKEN: ${hasToken ? \"set\" : \"not set\"} (.env)`);\n logOut(` A2A_SECRET: ${hasA2A ? \"set\" : \"not set\"}`);\n logOut(` Clients:`);\n for (const client of CLIENTS) {\n const present = clientHasEntry(client, appId, cwd);\n logOut(` ${client.padEnd(18)} ${present ? \"configured\" : \"—\"}`);\n }\n}\n\nfunction cmdToken(p: ParsedArgs): void {\n const cwd = process.cwd();\n const t = ensureLocalToken(cwd, p.rotate);\n logOut(\n p.rotate\n ? `Rotated ACCESS_TOKEN in ${t.file}`\n : t.created\n ? `Provisioned ACCESS_TOKEN in ${t.file}`\n : `ACCESS_TOKEN (${t.file}):`,\n );\n logOut(t.token);\n if (p.rotate) {\n logOut(\n ` Re-run \\`npx @agent-native/core@latest mcp install --client <c>\\` so client configs ` +\n `pick up the new token.`,\n );\n }\n}\n\nconst HELP = `npx @agent-native/core@latest mcp — connect external coding agents over MCP\n\nUsage:\n npx @agent-native/core@latest mcp serve [--app <id>] [--port <n>] [--standalone]\n Run the MCP stdio transport (what client configs spawn).\n Default: proxy to the running local app; --standalone builds from disk.\n\n npx @agent-native/core@latest mcp install --client <c> [--app <id>] [--scope user|project]\n Provision a token and write the client's MCP config (idempotent).\n Clients: claude-code, claude-code-cli, codex, cowork, cursor, opencode, github-copilot\n\n npx @agent-native/core@latest mcp uninstall --client <c> [--app <id>]\n Remove the named MCP entry from a client's config (idempotent).\n\n npx @agent-native/core@latest mcp status\n Show resolved MCP URL/port, token state, and per-client entries.\n\n npx @agent-native/core@latest mcp token [--rotate]\n Print (or rotate) the local ACCESS_TOKEN in the workspace .env.`;\n\nexport async function runMcp(args: string[]): Promise<void> {\n const p = parseArgs(args);\n const sub = p._[0];\n\n switch (sub) {\n case \"serve\":\n await cmdServe(p);\n return;\n case \"install\":\n await cmdInstall(p);\n return;\n case \"uninstall\":\n cmdUninstall(p);\n return;\n case \"status\":\n await cmdStatus();\n return;\n case \"token\":\n cmdToken(p);\n return;\n case undefined:\n case \"--help\":\n case \"-h\":\n case \"help\":\n logOut(HELP);\n return;\n default:\n logErr(`Unknown mcp subcommand: ${sub}`);\n logOut(HELP);\n process.exit(1);\n }\n}\n"]}
@@ -21,11 +21,12 @@ type LocalPlanPreviewInput = {
21
21
  kind?: LocalPlanKind;
22
22
  title?: string;
23
23
  brief?: string;
24
+ appUrl?: string;
24
25
  };
25
26
  type LocalPlanPreviewResult = {
26
27
  ok: true;
27
28
  dir: string;
28
- out: string;
29
+ out?: string;
29
30
  url: string;
30
31
  title: string;
31
32
  kind: LocalPlanKind;
@@ -48,6 +49,7 @@ export declare function writeLocalPlanPreview(input: {
48
49
  kind?: LocalPlanKind;
49
50
  title?: string;
50
51
  brief?: string;
52
+ appUrl?: string;
51
53
  open?: boolean;
52
54
  openUrl?: (url: string) => OpenLocalUrlResult;
53
55
  }): LocalPlanPreviewResult;
@@ -1 +1 @@
1
- {"version":3,"file":"plan-local.d.ts","sourceRoot":"","sources":["../../src/cli/plan-local.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAcH,KAAK,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC;AAEtC,KAAK,cAAc,GAAG;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,EAAE,EAAE,IAAI,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAyCF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUzD;AAyMD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAiB9D;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,qBAAqB,GAC3B,MAAM,CA2GR;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,kBAAkB,CAAC;CAC/C,GAAG,sBAAsB,CAoCzB;AAiMD,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA8C3D"}
1
+ {"version":3,"file":"plan-local.d.ts","sourceRoot":"","sources":["../../src/cli/plan-local.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAcH,KAAK,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC;AAEtC,KAAK,cAAc,GAAG;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,qBAAqB,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,sBAAsB,GAAG;IAC5B,EAAE,EAAE,IAAI,CAAC;IACT,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,KAAK,kBAAkB,GAAG;IACxB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAyCF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAUzD;AA2ND,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAiB9D;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,qBAAqB,GAC3B,MAAM,CA2GR;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,kBAAkB,CAAC;CAC/C,GAAG,sBAAsB,CAsCzB;AAsMD,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA8C3D"}
@@ -65,6 +65,17 @@ function normalizeKind(value) {
65
65
  function defaultPlansDir() {
66
66
  return path.resolve(process.env.PLAN_LOCAL_DIR || "plans");
67
67
  }
68
+ function defaultLocalPlanAppUrl() {
69
+ return (process.env.PLAN_LOCAL_APP_URL ||
70
+ process.env.PLAN_BASE_URL ||
71
+ "http://localhost:8096");
72
+ }
73
+ function normalizeAppUrl(value) {
74
+ return (value || defaultLocalPlanAppUrl()).replace(/\/+$/, "");
75
+ }
76
+ function localPlanPreviewUrl(dir, appUrl) {
77
+ return `${normalizeAppUrl(appUrl)}/local-plans/${encodeURIComponent(path.basename(path.resolve(dir)))}`;
78
+ }
68
79
  function openLocalUrl(url) {
69
80
  const platform = process.platform;
70
81
  const command = platform === "darwin" ? "open" : platform === "win32" ? "cmd" : "xdg-open";
@@ -353,9 +364,11 @@ export function writeLocalPlanPreview(input) {
353
364
  parsed.frontmatter.title ||
354
365
  firstHeading(parsed.body) ||
355
366
  path.basename(dir);
356
- const out = path.resolve(input.out || path.join(dir, "preview.html"));
357
- fs.mkdirSync(path.dirname(out), { recursive: true });
358
- fs.writeFileSync(out, buildLocalPlanPreviewHtml({ ...input, dir, kind }));
367
+ const out = input.out ? path.resolve(input.out) : undefined;
368
+ if (out) {
369
+ fs.mkdirSync(path.dirname(out), { recursive: true });
370
+ fs.writeFileSync(out, buildLocalPlanPreviewHtml({ ...input, dir, kind }));
371
+ }
359
372
  const files = [
360
373
  "plan.mdx",
361
374
  "canvas.mdx",
@@ -365,8 +378,8 @@ export function writeLocalPlanPreview(input) {
365
378
  const result = {
366
379
  ok: true,
367
380
  dir,
368
- out,
369
- url: pathToFileURL(out).href,
381
+ ...(out ? { out } : {}),
382
+ url: out ? pathToFileURL(out).href : localPlanPreviewUrl(dir, input.appUrl),
370
383
  title,
371
384
  kind,
372
385
  files,
@@ -461,6 +474,7 @@ function runPreview(args) {
461
474
  const result = writeLocalPlanPreview({
462
475
  dir: stringArg(args, "dir"),
463
476
  out: optionalArg(args, "out"),
477
+ appUrl: optionalArg(args, "app-url"),
464
478
  title: optionalArg(args, "title"),
465
479
  brief: optionalArg(args, "brief"),
466
480
  open: boolArg(args, "open"),
@@ -522,7 +536,7 @@ Usage:
522
536
  agent-native plan blocks [--format reference|schema] [--app-url <url>] [--out <file>] [--json]
523
537
  agent-native plan local init --title <title> [--brief <text>] [--kind plan|recap] [--dir <folder>] [--force]
524
538
  agent-native plan local check --dir <folder>
525
- agent-native plan local preview --dir <folder> [--out preview.html] [--kind plan|recap] [--open]
539
+ agent-native plan local preview --dir <folder> [--app-url <url>] [--kind plan|recap] [--open] [--out preview.html]
526
540
 
527
541
  The blocks command fetches the no-auth, read-only get-plan-blocks catalog from
528
542
  the Plan app and writes plan-blocks.md (or plan-blocks.schema.json). It sends no
@@ -539,6 +553,10 @@ Common flow:
539
553
  agent-native plan blocks --out plan-blocks.md
540
554
  agent-native plan local init --title "Checkout review" --kind plan
541
555
  agent-native plan local preview --dir plans/checkout-review --open
556
+
557
+ \`plan local preview\` opens the local Plan app route by default. Pass
558
+ \`--app-url\` when your local Plan app is on a non-default port. \`--out\` is a
559
+ legacy/debug escape hatch that writes a standalone static HTML file.
542
560
  `;
543
561
  export async function runPlan(argv) {
544
562
  const [area, sub, ...rest] = argv;