@heyditto/cli 3.13.0 → 3.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -734,6 +734,19 @@ How the wiring works:
734
734
  schemas behind its own `search_tool` / `use_tool`. The Ditto model entry
735
735
  sends `X-Ditto-Tool-Surface: mcp`. `--no-mcp` or `grok_tool_surface =
736
736
  "router"` keeps the router surface.
737
+ - **Cursor CLI** (`heyditto cursor`, runs `cursor-agent`) keeps inference on
738
+ your own Cursor account; Ditto supplies only the endpoint's tools. Cursor
739
+ has no per-launch MCP flag, so they go in a private per-launch plugin
740
+ (`--plugin-dir`, a `.cursor-plugin/plugin.json` plus `.mcp.json`) and
741
+ nothing is written to `~/.cursor`. The servers show up as
742
+ `plugin-ditto-<server>`, and the key is read from
743
+ `${env:DITTO_ROUTER_MCP_KEY}`. Cursor asks before each MCP call unless
744
+ `--yolo` (`--force`). A `-p` run adds no Cursor-wide flag of its
745
+ own: Cursor's `-p` edits and runs commands, but rejects every MCP call it
746
+ cannot ask about, so Ditto's tools need `--yolo` there (an explicit choice,
747
+ since `--force` also allows any command). An untrusted workspace needs
748
+ Cursor's own `--trust`. Remote control and
749
+ `--headless` are not available for Cursor yet.
737
750
 
738
751
  ### `codex-app`
739
752
 
@@ -133,7 +133,7 @@ export interface SettingsIO {
133
133
  * keeps reading its settings for as long as it runs. A dead owner's directory
134
134
  * is kept for a short grace period after its last write.
135
135
  */
136
- export declare function sweepStaleSettings(tmp: string, isAlive?: (pid: number) => boolean, now?: number): void;
136
+ export declare function sweepStaleSettings(tmp: string, isAlive?: (pid: number) => boolean, now?: number, prefix?: string): void;
137
137
  /**
138
138
  * A private copy of merged settings for the life of this process. A user's
139
139
  * settings file can hold secrets, so its contents never go into Claude's
@@ -178,9 +178,11 @@ export function mergeSettings(a, b) {
178
178
  const PRIVATE_SETTINGS_PREFIX = "ditto-claude-settings-";
179
179
  /** One private directory per temp root for the life of this process. */
180
180
  const privateSettingsDirs = new Map();
181
- /** The pid a settings directory belongs to: ditto-claude-settings-<pid>-<random>. */
182
- function ownerPid(name) {
183
- const m = /^ditto-claude-settings-(\d+)-/.exec(name);
181
+ /** The pid a private directory belongs to: <prefix><pid>-<random>. */
182
+ function ownerPid(name, prefix) {
183
+ if (!name.startsWith(prefix))
184
+ return undefined;
185
+ const m = /^(\d+)-/.exec(name.slice(prefix.length));
184
186
  return m ? Number(m[1]) : undefined;
185
187
  }
186
188
  function alive(pid) {
@@ -204,7 +206,7 @@ const STALE_SETTINGS_GRACE_MS = 5 * 60 * 1000;
204
206
  * keeps reading its settings for as long as it runs. A dead owner's directory
205
207
  * is kept for a short grace period after its last write.
206
208
  */
207
- export function sweepStaleSettings(tmp, isAlive = alive, now = Date.now()) {
209
+ export function sweepStaleSettings(tmp, isAlive = alive, now = Date.now(), prefix = PRIVATE_SETTINGS_PREFIX) {
208
210
  let entries;
209
211
  try {
210
212
  entries = readdirSync(tmp);
@@ -214,9 +216,7 @@ export function sweepStaleSettings(tmp, isAlive = alive, now = Date.now()) {
214
216
  }
215
217
  const uid = process.getuid?.();
216
218
  for (const name of entries) {
217
- if (!name.startsWith(PRIVATE_SETTINGS_PREFIX))
218
- continue;
219
- const pid = ownerPid(name);
219
+ const pid = ownerPid(name, prefix);
220
220
  if (pid === undefined || pid === process.pid || isAlive(pid))
221
221
  continue;
222
222
  const dir = path.join(tmp, name);
@@ -1 +1 @@
1
- {"version":3,"file":"claude-mcp.js","sourceRoot":"","sources":["../../src/agents/claude-mcp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"claude-mcp.js","sourceRoot":"","sources":["../../src/agents/claude-mcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { type McpAttachment } from "./claude-mcp.js";
3
+ import type { HarnessPlan, PlanInput } from "./types.js";
4
+ /**
5
+ * Cursor CLI (`cursor-agent`) through Ditto.
6
+ *
7
+ * Cursor's own service runs inference, so Ditto supplies only the endpoint's
8
+ * tools, as native MCP servers. Cursor has no per-launch MCP flag, but it
9
+ * loads a plugin directory per launch (`--plugin-dir`), and a plugin's
10
+ * `.mcp.json` declares servers, so the attachment goes there and nothing is
11
+ * written to ~/.cursor. Cursor names a plugin's servers after the plugin
12
+ * directory, `plugin-ditto-<server>`. The key stays out of the file: Cursor
13
+ * expands `${env:DITTO_ROUTER_MCP_KEY}` in headers.
14
+ */
15
+ /** The plugin directory's name, which Cursor puts in every server's name. */
16
+ export declare const CURSOR_PLUGIN_NAME = "ditto";
17
+ /**
18
+ * The plugin's `.mcp.json`. Cursor's permission rules live only in its own
19
+ * config files, so Cursor itself asks before every call (or runs them all
20
+ * under --yolo); Ditto's gate still holds what the endpoint's policy holds.
21
+ */
22
+ export declare function cursorMcpConfig(mcp: McpAttachment): string;
23
+ /**
24
+ * Writes the launch's plugin into a private temporary directory and returns
25
+ * its path. It holds no secret, but it is the session's tool wiring, so it is
26
+ * 0700 and removed when the CLI exits; one a killed CLI left behind is swept
27
+ * by a later launch once its process is gone, like Claude's settings copies.
28
+ */
29
+ export declare function writeCursorPlugin(mcp: McpAttachment, tmp?: string): string;
30
+ /**
31
+ * A new, empty Cursor chat for this session, so the session can name its own
32
+ * conversation: `--resume <id>` reopens exactly it, where `--continue` would
33
+ * pick whichever chat in the directory is newest. Undefined when Cursor does
34
+ * not answer with an id.
35
+ */
36
+ export declare function createCursorChat(cwd: string, run?: typeof spawnSync): string | undefined;
37
+ /**
38
+ * Builds the `cursor-agent` invocation. `pluginDir` is the directory
39
+ * writeCursorPlugin made for this launch (absent: no tools attached).
40
+ */
41
+ export declare function planCursor(input: PlanInput, pluginDir?: string): HarnessPlan;
@@ -0,0 +1,103 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { chmodSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import { MCP_KEY_ENV, sweepStaleSettings } from "./claude-mcp.js";
6
+ /**
7
+ * Cursor CLI (`cursor-agent`) through Ditto.
8
+ *
9
+ * Cursor's own service runs inference, so Ditto supplies only the endpoint's
10
+ * tools, as native MCP servers. Cursor has no per-launch MCP flag, but it
11
+ * loads a plugin directory per launch (`--plugin-dir`), and a plugin's
12
+ * `.mcp.json` declares servers, so the attachment goes there and nothing is
13
+ * written to ~/.cursor. Cursor names a plugin's servers after the plugin
14
+ * directory, `plugin-ditto-<server>`. The key stays out of the file: Cursor
15
+ * expands `${env:DITTO_ROUTER_MCP_KEY}` in headers.
16
+ */
17
+ /** The plugin directory's name, which Cursor puts in every server's name. */
18
+ export const CURSOR_PLUGIN_NAME = "ditto";
19
+ /**
20
+ * The plugin's `.mcp.json`. Cursor's permission rules live only in its own
21
+ * config files, so Cursor itself asks before every call (or runs them all
22
+ * under --yolo); Ditto's gate still holds what the endpoint's policy holds.
23
+ */
24
+ export function cursorMcpConfig(mcp) {
25
+ const mcpServers = {};
26
+ for (const server of mcp.attached) {
27
+ mcpServers[server.name] = { url: server.url, headers: { Authorization: `Bearer \${env:${MCP_KEY_ENV}}`, ...server.headers } };
28
+ }
29
+ return JSON.stringify({ mcpServers }, null, 2);
30
+ }
31
+ /** Plugin directories made by this process, removed when it exits. */
32
+ const pluginRoots = [];
33
+ const PLUGIN_PREFIX = "ditto-cursor-";
34
+ /**
35
+ * Writes the launch's plugin into a private temporary directory and returns
36
+ * its path. It holds no secret, but it is the session's tool wiring, so it is
37
+ * 0700 and removed when the CLI exits; one a killed CLI left behind is swept
38
+ * by a later launch once its process is gone, like Claude's settings copies.
39
+ */
40
+ export function writeCursorPlugin(mcp, tmp = os.tmpdir()) {
41
+ if (pluginRoots.length === 0)
42
+ sweepStaleSettings(tmp, undefined, undefined, PLUGIN_PREFIX);
43
+ const root = mkdtempSync(path.join(tmp, `${PLUGIN_PREFIX}${process.pid}-`));
44
+ chmodSync(root, 0o700);
45
+ if (pluginRoots.push(root) === 1)
46
+ process.once("exit", () => { for (const dir of pluginRoots)
47
+ rmSync(dir, { recursive: true, force: true }); });
48
+ const dir = path.join(root, CURSOR_PLUGIN_NAME);
49
+ mkdirSync(path.join(dir, ".cursor-plugin"), { recursive: true });
50
+ writeFileSync(path.join(dir, ".cursor-plugin", "plugin.json"), JSON.stringify({ name: CURSOR_PLUGIN_NAME, version: "1.0.0", description: "Ditto endpoint tools" }, null, 2));
51
+ writeFileSync(path.join(dir, ".mcp.json"), cursorMcpConfig(mcp));
52
+ return dir;
53
+ }
54
+ /**
55
+ * A new, empty Cursor chat for this session, so the session can name its own
56
+ * conversation: `--resume <id>` reopens exactly it, where `--continue` would
57
+ * pick whichever chat in the directory is newest. Undefined when Cursor does
58
+ * not answer with an id.
59
+ */
60
+ export function createCursorChat(cwd, run = spawnSync) {
61
+ const res = run("cursor-agent", ["create-chat"], { cwd, encoding: "utf8", timeout: 15_000 });
62
+ const id = typeof res.stdout === "string" ? res.stdout.trim() : "";
63
+ return res.status === 0 && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(id) ? id : undefined;
64
+ }
65
+ /**
66
+ * Builds the `cursor-agent` invocation. `pluginDir` is the directory
67
+ * writeCursorPlugin made for this launch (absent: no tools attached).
68
+ */
69
+ export function planCursor(input, pluginDir) {
70
+ if (input.yellow)
71
+ throw new Error("--yellow is not supported for Cursor CLI; use --yolo (--force) or Cursor's own prompts");
72
+ const args = [];
73
+ if (pluginDir)
74
+ args.push("--plugin-dir", pluginDir);
75
+ if (input.resumeId)
76
+ args.push("--resume", input.resumeId);
77
+ else if (input.resumeLast)
78
+ args.push("--continue");
79
+ if (input.model)
80
+ args.push("--model", input.model);
81
+ if (input.plan)
82
+ args.push("--plan");
83
+ // --force is Cursor-wide (any command, any MCP call), so only an explicit
84
+ // --yolo adds it, and workspace trust stays the user's decision. A -p run
85
+ // without it still edits and runs shell commands, but Cursor rejects every
86
+ // MCP call it cannot ask about (the launch says so).
87
+ if (input.yolo)
88
+ args.push("--force");
89
+ if (input.prompt !== undefined) {
90
+ args.push("-p", input.prompt, ...input.passthrough);
91
+ }
92
+ else {
93
+ args.push(...input.passthrough);
94
+ }
95
+ return {
96
+ command: "cursor-agent",
97
+ args,
98
+ envSet: input.mcp ? { [MCP_KEY_ENV]: input.mcpApiKey ?? input.apiKey } : {},
99
+ envUnset: [],
100
+ installHint: "install Cursor CLI: curl https://cursor.com/install -fsS | bash (then `cursor-agent login`)",
101
+ };
102
+ }
103
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../src/agents/cursor.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,7 @@ import { findTranscriptById, isUuid, listTranscriptsIn } from "./claude-transcri
22
22
  import { watchClaudeSessionTitle } from "./claude-title-sync.js";
23
23
  import { claudeHookAttachment } from "./claude-hooks.js";
24
24
  import { planCodex } from "./codex.js";
25
+ import { createCursorChat, planCursor, writeCursorPlugin } from "./cursor.js";
25
26
  import { cliProxyModel, resolveCliProxy } from "./cliproxy.js";
26
27
  import { readHarnessVersion } from "./harness-headers.js";
27
28
  import { ensureGrokHome, planGrok } from "./grok.js";
@@ -65,7 +66,12 @@ export function resolveClaudeLaunchDefaults(options, defaults = {}) {
65
66
  }
66
67
  const DRY_RUN_KEY = "ditto_inf_<minted-at-launch>";
67
68
  /** Harnesses that can attach an endpoint's tools as their own MCP servers. */
68
- export const MCP_HARNESSES = ["claude", "codex", "grok"];
69
+ export const MCP_HARNESSES = ["claude", "codex", "grok", "cursor"];
70
+ /**
71
+ * Harnesses whose own service runs inference: Ditto supplies only the
72
+ * endpoint's tools as MCP servers, so a launch without them is pointless.
73
+ */
74
+ const MCP_ONLY_HARNESSES = ["cursor"];
69
75
  /**
70
76
  * `--mcp` / `--no-mcp`, else the endpoint's `<harness>_tool_surface`, else
71
77
  * native MCP: the agent gets an endpoint's tools as its own servers unless the
@@ -132,9 +138,14 @@ function mcpBanner(mcp, opts) {
132
138
  return c("dim", "none (the endpoint has no tools)");
133
139
  if (!mcp)
134
140
  return opts.dryRun ? "mcp (catalog read at launch)" : c(opts.chosen ? "yellow" : "dim", "router (MCP not attached)");
135
- return `mcp ${c("dim", `(${mcp.servers} servers, ${mcp.tools} tools; ${mcpApprovalNote(mcp, opts.agent)})`)}`;
141
+ // An unattended Grok run refuses what it would have asked about (grok.ts);
142
+ // Cursor's -p without --yolo rejects every MCP call, gated or not (cursor.ts).
143
+ const note = opts.rejectsAll ? "every call rejected: Cursor's -p needs --yolo"
144
+ : opts.refusesAsked && mcp.ask.length ? `${mcp.ask.length} gated refused: nobody to approve them`
145
+ : mcpApprovalNote(mcp, opts.agent);
146
+ return `mcp ${c("dim", `(${mcp.servers} servers, ${mcp.tools} tools; ${note})`)}`;
136
147
  }
137
- const AGENT_LABELS = { claude: "Claude Code", codex: "Codex", grok: "Grok" };
148
+ const AGENT_LABELS = { claude: "Claude Code", codex: "Codex", grok: "Grok", cursor: "Cursor CLI" };
138
149
  function log(line, options) {
139
150
  writeNote(`${c("dim", "ditto:")} ${line}\n`, options);
140
151
  }
@@ -146,11 +157,13 @@ function log(line, options) {
146
157
  function logResumeHint(harness, sessionId) {
147
158
  writeNote(`${c("dim", "ditto:")} resume this session with:\n\n ${c(["bold", "green"], `heyditto ${harness} --resume ${sessionId}`)}\n\n`);
148
159
  }
149
- function planFor(harness, input, grokHome) {
160
+ function planFor(harness, input, grokHome, cursorPlugin) {
150
161
  if (harness === "claude")
151
162
  return planClaude(input);
152
163
  if (harness === "grok")
153
164
  return planGrok(input, grokHome ?? "");
165
+ if (harness === "cursor")
166
+ return planCursor(input, cursorPlugin);
154
167
  return planCodex(input);
155
168
  }
156
169
  function binaryAvailable(command) {
@@ -345,7 +358,7 @@ async function ensureLoggedIn(harness, endpoint) {
345
358
  await listEndpoints(); // throws the shared "no Ditto API key configured" error
346
359
  return undefined;
347
360
  }
348
- log(`no Ditto login yet — opening your browser to sign in and pick an endpoint for ${harness === "claude" ? "Claude Code" : "Codex"}.`);
361
+ log(`no Ditto login yet — opening your browser to sign in and pick an endpoint for ${AGENT_LABELS[harness]}.`);
349
362
  return browserLogin(harness, endpoint);
350
363
  }
351
364
  /**
@@ -354,7 +367,8 @@ async function ensureLoggedIn(harness, endpoint) {
354
367
  */
355
368
  async function browserLogin(harness, endpoint) {
356
369
  const result = await deviceLogin({
357
- intent: harness,
370
+ // The sign-in page knows the agents it routes; an MCP-only one just signs in.
371
+ intent: harness === "cursor" ? "login" : harness,
358
372
  endpoint,
359
373
  onCode: (userCode, url) => {
360
374
  process.stderr.write(`\n ${url}\n\n Code: ${userCode}\n\n`);
@@ -418,8 +432,16 @@ export async function launchHarness(harness, rawArgs, options) {
418
432
  }
419
433
  const budget = parseBudget(options.budget);
420
434
  const expiresIn = parseExpiry(options.expires);
421
- if (options.plan && harness !== "claude")
422
- throw new Error("--plan is only supported for claude");
435
+ if (options.plan && harness === "codex")
436
+ throw new Error("--plan is not supported for codex");
437
+ if (MCP_ONLY_HARNESSES.includes(harness)) {
438
+ if (options.mcp === false)
439
+ throw new Error(`${AGENT_LABELS[harness]} gets Ditto only as MCP tools; --no-mcp would attach nothing`);
440
+ if (options.headless)
441
+ throw new Error(`--headless is not supported for ${AGENT_LABELS[harness]} yet`);
442
+ if (options.yellow)
443
+ throw new Error(`--yellow is not supported for ${AGENT_LABELS[harness]}; use --yolo or its own prompts`);
444
+ }
423
445
  if ([options.yolo, options.yellow, options.plan].filter(Boolean).length > 1) {
424
446
  throw new Error("choose only one of --yolo, --yellow, --plan");
425
447
  }
@@ -427,15 +449,9 @@ export async function launchHarness(harness, rawArgs, options) {
427
449
  throw new Error("use either --resume or --continue");
428
450
  if (options.resume !== undefined && options.session)
429
451
  throw new Error("--session cannot be combined with --resume");
430
- if (!options.dryRun && !binaryAvailable(harness)) {
431
- const hint = planFor(harness, {
432
- baseUrl: "",
433
- apiKey: "",
434
- sessionId: "",
435
- passthrough: [],
436
- env: {},
437
- }).installHint;
438
- throw new Error(`"${harness}" is not on your PATH; ${hint}`);
452
+ const probe = planFor(harness, { baseUrl: "", apiKey: "", sessionId: "", passthrough: [], env: {} });
453
+ if (!options.dryRun && !binaryAvailable(probe.command)) {
454
+ throw new Error(`"${probe.command}" is not on your PATH; ${probe.installHint}`);
439
455
  }
440
456
  // Resume: reuse the local record's Ditto session id so the traces stay in
441
457
  // the same thread; a fresh key is minted every launch.
@@ -522,7 +538,7 @@ export async function launchHarness(harness, rawArgs, options) {
522
538
  // probe overlaps the key and MCP setup below instead of delaying the
523
539
  // launch. It never rejects: unreadable means the header is left out,
524
540
  // never guessed. grok has no version-specific prompts.
525
- const harnessVersionProbe = harness === "grok" ? Promise.resolve(undefined) : readHarnessVersion(harness);
541
+ const harnessVersionProbe = harness === "grok" || MCP_ONLY_HARNESSES.includes(harness) ? Promise.resolve(undefined) : readHarnessVersion(harness);
526
542
  let cwd = process.cwd();
527
543
  let worktreePath;
528
544
  if (options.cwd) {
@@ -588,7 +604,8 @@ export async function launchHarness(harness, rawArgs, options) {
588
604
  endpoint = { ...endpoint, providerOptions: { ...endpoint.providerOptions, ...repoLaunchDefaults } };
589
605
  if (harness === "claude")
590
606
  options = resolveClaudeLaunchDefaults(options, endpoint.providerOptions);
591
- if (!options.mcpOnly && !proxy)
607
+ const mcpOnlyHarness = MCP_ONLY_HARNESSES.includes(harness);
608
+ if (!options.mcpOnly && !proxy && !mcpOnlyHarness)
592
609
  await assertEndpointActive(endpoint);
593
610
  if (options.mcpOnly && (harness !== "claude" || options.mcp === false))
594
611
  throw new Error("--mcp-only requires Claude Code with MCP tools enabled");
@@ -601,10 +618,14 @@ export async function launchHarness(harness, rawArgs, options) {
601
618
  throw new Error("--session must match ^[A-Za-z0-9._:@-]{1,128}$");
602
619
  }
603
620
  // Claude: the resumed conversation, or the id a fresh one is created under.
604
- const harnessSessionId = harness === "claude"
621
+ // Cursor: a fresh session opens a chat of its own, so a later resume names it.
622
+ if (harness === "cursor" && record && !record.harnessSessionId) {
623
+ throw new Error(`session ${record.id} has no Cursor chat id to resume; start a new one, or reopen it with cursor-agent --resume`);
624
+ }
625
+ let harnessSessionId = harness === "claude"
605
626
  ? (transcript?.id ?? (resumeLast ? undefined : sessionId))
606
627
  : record?.harnessSessionId;
607
- const resumeId = harness === "claude" ? transcript?.id : record?.harnessSessionId;
628
+ let resumeId = harness === "claude" ? transcript?.id : record?.harnessSessionId;
608
629
  // No model flag means the harness's own model choice passes through and the
609
630
  // endpoint routes it (Codex's default gpt-* id normalizes like Claude's
610
631
  // claude-* ids). Earlier releases pinned Codex sessions to the endpoint
@@ -629,7 +650,9 @@ export async function launchHarness(harness, rawArgs, options) {
629
650
  // than launching an agent with none. Native MCP is the default, so the
630
651
  // fallback is only flagged when someone asked for MCP; an endpoint the
631
652
  // surface refuses (an app's) would otherwise warn on every launch.
632
- const wantMcp = options.mcpOnly || wantsMcp(options, endpoint, harness);
653
+ // An MCP-only harness has nothing else from Ditto, whatever the endpoint's
654
+ // <harness>_tool_surface says (--no-mcp was refused above).
655
+ const wantMcp = options.mcpOnly || mcpOnlyHarness || wantsMcp(options, endpoint, harness);
633
656
  const chosen = mcpChosen(options, endpoint, harness);
634
657
  let mcp;
635
658
  let noTools = false;
@@ -647,7 +670,7 @@ export async function launchHarness(harness, rawArgs, options) {
647
670
  log(c("yellow", `MCP server ${JSON.stringify(name)} left out: its name cannot be used in an agent's config`));
648
671
  }
649
672
  catch (err) {
650
- if (options.mcpOnly || proxy) {
673
+ if (options.mcpOnly || proxy || mcpOnlyHarness) {
651
674
  if (!options.keepKey) {
652
675
  try {
653
676
  await revokeKey(endpoint.id, key.id);
@@ -656,7 +679,7 @@ export async function launchHarness(harness, rawArgs, options) {
656
679
  log(`could not revoke session key …${key.keyHint}; it expires in ${expiresIn}`);
657
680
  }
658
681
  }
659
- throw new Error(`${proxy ? "CLIProxy MCP" : "MCP-only"} setup failed; no inference Router fallback: ${err.message}`);
682
+ throw new Error(`${proxy ? "CLIProxy MCP" : mcpOnlyHarness ? `${AGENT_LABELS[harness]} MCP` : "MCP-only"} setup failed; no inference Router fallback: ${err.message}`);
660
683
  }
661
684
  const note = c(chosen ? "yellow" : "dim", "native MCP unavailable");
662
685
  log(`${note} (${err.message}); the router keeps this endpoint's tools`);
@@ -685,6 +708,31 @@ export async function launchHarness(harness, rawArgs, options) {
685
708
  : undefined;
686
709
  // Read once per launch and reused by every turn.
687
710
  const harnessVersion = await harnessVersionProbe;
711
+ if (mcpOnlyHarness && !mcp && key) {
712
+ if (!options.keepKey)
713
+ await revokeKey(endpoint.id, key.id).catch(() => log(`could not revoke session key …${key.keyHint}; it expires in ${expiresIn}`));
714
+ throw new Error(`${endpoint.slug} has no tools to attach, and ${AGENT_LABELS[harness]} gets nothing else from Ditto`);
715
+ }
716
+ // Cursor CLI loads the attachment as a per-launch plugin (cursor.ts).
717
+ let cursorPlugin;
718
+ if (harness === "cursor" && mcp && key) {
719
+ try {
720
+ cursorPlugin = writeCursorPlugin(mcp);
721
+ }
722
+ catch (err) {
723
+ if (!options.keepKey)
724
+ await revokeKey(endpoint.id, key.id).catch(() => log(`could not revoke session key …${key.keyHint}; it expires in ${expiresIn}`));
725
+ throw err;
726
+ }
727
+ // Last, once nothing above can abort the launch: a fresh session opens a
728
+ // chat of its own in the user's Cursor account. --continue means Cursor's
729
+ // newest chat in this directory, so it opens none.
730
+ if (!record && !resumeLast) {
731
+ harnessSessionId = resumeId = createCursorChat(cwd);
732
+ if (!harnessSessionId)
733
+ log(c("yellow", "Cursor did not create a chat id; this session cannot be resumed with heyditto cursor --resume"));
734
+ }
735
+ }
688
736
  const plan = planFor(harness, {
689
737
  baseUrl: proxy?.baseUrl ?? catalog.baseUrl,
690
738
  apiKey: proxy?.apiKey ?? key?.key ?? DRY_RUN_KEY,
@@ -707,17 +755,19 @@ export async function launchHarness(harness, rawArgs, options) {
707
755
  remoteTransport: options.remoteTransport,
708
756
  cwd,
709
757
  env: process.env,
710
- }, grokHome);
758
+ }, grokHome, cursorPlugin);
759
+ // Cursor's -p rejects every MCP call it cannot ask about unless --force (planCursor).
760
+ const cursorPRejectsMcp = harness === "cursor" && Boolean(mcp) && options.prompt !== undefined && !options.yolo;
711
761
  const field = (name, value) => `${c("dim", `${name}=`)}${value}`;
712
762
  const banner = [
713
763
  field("endpoint", c(["bold", "cyan"], endpoint.slug)),
714
- field("inference", proxy ? `CLIProxy (${proxy.baseUrl})` : options.mcpOnly ? "native Claude Code account (MCP only)" : "Ditto Router"),
715
- field("model", model ?? c("dim", options.mcpOnly ? "(native Claude Code default)" : "(harness default → endpoint routes)")),
764
+ field("inference", proxy ? `CLIProxy (${proxy.baseUrl})` : options.mcpOnly || mcpOnlyHarness ? `native ${AGENT_LABELS[harness]} account (MCP only)` : "Ditto Router"),
765
+ field("model", model ?? c("dim", options.mcpOnly || mcpOnlyHarness ? `(native ${AGENT_LABELS[harness]} default)` : "(harness default → endpoint routes)")),
716
766
  field("key", key ? `…${key.keyHint || maskKey(key.key ?? "")}` : "(dry run)"),
717
767
  field("expires", `${expiresIn}${options.keepKey ? "" : c("dim", " (revoked on exit)")}`),
718
768
  budget !== undefined ? field("budget", `${budget.toLocaleString()} tokens`) : undefined,
719
769
  field("session", c("bold", sessionId)),
720
- wantMcp ? field("tools", mcpBanner(mcp, { dryRun: options.dryRun, noTools, chosen, agent: AGENT_LABELS[harness] })) : undefined,
770
+ wantMcp ? field("tools", mcpBanner(mcp, { dryRun: options.dryRun, noTools, chosen, agent: AGENT_LABELS[harness], refusesAsked: harness === "grok" && (options.prompt !== undefined || options.headless), rejectsAll: cursorPRejectsMcp })) : undefined,
721
771
  hooks?.banner ? field("hooks", hooks.banner) : undefined,
722
772
  ]
723
773
  .filter(Boolean)
@@ -725,8 +775,12 @@ export async function launchHarness(harness, rawArgs, options) {
725
775
  log(banner);
726
776
  if (proxy)
727
777
  log("inference stays on CLIProxy; Ditto provides MCP tools/remote control, without Router inference optimizations or inference traces");
778
+ else if (mcpOnlyHarness)
779
+ log(`inference stays on your ${AGENT_LABELS[harness]} account; Ditto provides the endpoint's tools, whose calls are traced at ${c(["underline", "cyan"], endpointURL(endpoint.id))}`);
728
780
  else
729
781
  log(`traces: ${c(["underline", "cyan"], endpointURL(endpoint.id))}`);
782
+ if (cursorPRejectsMcp)
783
+ log(c("yellow", "Cursor's -p rejects every MCP call it cannot ask about; pass --yolo (Cursor's --force, which also allows any command) to let it use Ditto's tools"));
730
784
  if (options.dryRun) {
731
785
  const env = Object.fromEntries(Object.entries(plan.envSet).map(([k, v]) => [k, v === DRY_RUN_KEY || v === proxy?.apiKey ? "<key>" : v]));
732
786
  process.stdout.write(`${JSON.stringify({
@@ -740,9 +794,9 @@ export async function launchHarness(harness, rawArgs, options) {
740
794
  sessionId,
741
795
  // A dry run reads no catalog, so the plan above is the router's; say
742
796
  // which surface a real launch would ask for, separately.
743
- toolSurface: mcp ? "mcp" : proxy ? "none" : "router",
797
+ toolSurface: mcp ? "mcp" : proxy || mcpOnlyHarness ? "none" : "router",
744
798
  toolSurfaceRequested: wantMcp ? "mcp" : proxy ? "none" : "router",
745
- inference: proxy ? "cliproxy" : options.mcpOnly ? "native" : "router",
799
+ inference: proxy ? "cliproxy" : options.mcpOnly || mcpOnlyHarness ? "native" : "router",
746
800
  remoteTransport: options.remoteTransport ?? "cli",
747
801
  hooks: hooks?.attachment?.summary ?? [],
748
802
  key: { name: keyName, expiresIn, spendLimitTokens: budget ?? null },
@@ -772,10 +826,12 @@ export async function launchHarness(harness, rawArgs, options) {
772
826
  ...(explicitLaunchTitle ? { explicitLaunchTitle } : {}),
773
827
  };
774
828
  await writeSession(nextRecord);
775
- const remote = remoteMode(options);
829
+ // Remote Control needs the harness's turn-boundary hooks, which only the
830
+ // agents with a hook bridge (remote/hooks.ts) report.
831
+ const remote = mcpOnlyHarness ? "off" : remoteMode(options);
776
832
  const launchRegistration = {
777
833
  sessionId, endpointId: endpoint.id, harness: harness === "claude" ? "claude-code" : harness,
778
- inference: proxy || options.mcpOnly ? "native" : "router", transport: options.remoteTransport ?? "cli",
834
+ inference: proxy || options.mcpOnly || mcpOnlyHarness ? "native" : "router", transport: options.remoteTransport ?? "cli",
779
835
  title: explicitLaunchTitle || `${path.basename(cwd)} · ${sessionId.slice(0, 8)}`,
780
836
  ...(harness === "claude" && harnessSessionId && isUuid(harnessSessionId) ? { nativeSessionId: harnessSessionId } : {}),
781
837
  };
@@ -863,7 +919,9 @@ export async function launchHarness(harness, rawArgs, options) {
863
919
  !(await findTranscriptById(harnessSessionId, cwd));
864
920
  if (empty)
865
921
  log(`nothing was sent, so there is no conversation to resume ${c("dim", "(heyditto claude --resume lists the ones there are)")}`);
866
- else
922
+ // A Cursor session without its own chat id cannot be resumed by name
923
+ // (the launch refuses it), so it gets no hint that would fail.
924
+ else if (harness !== "cursor" || harnessSessionId)
867
925
  logResumeHint(harness, sessionId);
868
926
  }
869
927
  await writeSession({ ...nextRecord, endedAt: new Date().toISOString(), exitCode });