fix(#59): disable claude-code IDE auto-connect to stop spurious macOS Apple-Events prompt #68

Merged
benstull merged 1 commits from s60-59-apple-events-prompt into main 2026-06-26 20:12:24 +00:00
2 changed files with 57 additions and 0 deletions
+19
View File
@@ -64,6 +64,25 @@ export async function runEditTurn(
providerId: "claude-code", providerId: "claude-code",
modelId, modelId,
systemPrompt: SYSTEM_PROMPT, systemPrompt: SYSTEM_PROMPT,
// The claude-code provider spawns the bundled `claude` CLI. On macOS, when
// that process is launched from inside VS Code it performs IDE auto-connect,
// which shells out to `osascript` (`tell application …`) to identify/activate
// the editor — raising the macOS "control other applications" (Apple Events)
// permission prompt (#59). We only consume the turn's text result and never
// use the IDE connection, so we disable it: `CLAUDE_CODE_AUTO_CONNECT_IDE=0`
// hard-returns out of the auto-connect path in the binary, and
// `CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL=1` skips the extension-install deep link.
// Seeding with the full `process.env` keeps the default inheritance intact
// (login under HOME, proxy/CA vars) — we only add the two switches. The
// provider forwards `options.env` into the spawned child (verified end to end
// through @cline/sdk → ai-sdk-provider-claude-code → @anthropic-ai/claude-agent-sdk).
options: {
env: {
...process.env,
CLAUDE_CODE_AUTO_CONNECT_IDE: "0",
CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL: "1",
},
},
}); });
// Stream reduced progress snapshots out (INV-44 additive) and wire cancellation // Stream reduced progress snapshots out (INV-44 additive) and wire cancellation
+38
View File
@@ -52,6 +52,44 @@ describe("extractReplacement", () => {
}); });
}); });
describe("runEditTurn macOS automation prompt (#59)", () => {
// The claude-code provider spawns the bundled `claude` CLI, which on macOS
// performs IDE auto-connect when launched inside VS Code — sending Apple Events
// that raise the "control other applications" prompt. The extension only
// consumes the text result and never needs that connection, so we disable it.
it("spawns the agent with IDE auto-connect + auto-install disabled, preserving the rest of the environment", async () => {
vi.resetModules();
const cfgs: any[] = [];
vi.doMock("@cline/sdk", () => ({
Agent: class {
constructor(cfg: any) {
cfgs.push(cfg);
}
subscribe() {
return () => {};
}
abort() {}
async run() {
return { status: "completed", outputText: "X", runId: "r" };
}
},
}));
process.env.__WGL_TEST_SENTINEL__ = "keep-me";
await runEditTurn("do it", "old");
const cfg = cfgs[0];
// mK("0") === true in the claude binary → hard-disables IDE auto-connect,
// so no osascript / Apple Event fires.
expect(cfg.options?.env?.CLAUDE_CODE_AUTO_CONNECT_IDE).toBe("0");
// Belt-and-suspenders: skip the IDE-extension auto-install (deep-link path).
expect(cfg.options?.env?.CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL).toBe("1");
// The full process environment must survive (login under HOME, proxy/CA vars).
expect(cfg.options?.env?.__WGL_TEST_SENTINEL__).toBe("keep-me");
delete process.env.__WGL_TEST_SENTINEL__;
vi.doUnmock("@cline/sdk");
vi.resetModules();
});
});
describe("runEditTurn progress + cancel", () => { describe("runEditTurn progress + cancel", () => {
it("emits progress snapshots and returns the replacement unchanged (INV-44)", async () => { it("emits progress snapshots and returns the replacement unchanged (INV-44)", async () => {
vi.resetModules(); vi.resetModules();