From bfa16ce1afc4263531e0628fb2217da15fece09f Mon Sep 17 00:00:00 2001 From: aditya mer Date: Sun, 21 Jun 2026 16:56:07 +0530 Subject: [PATCH 1/2] fix(cursor): default binary path to cursor-agent (#3479) When Grok CLI is installed alongside Cursor, the shared `agent` command name resolves to Grok and breaks Cursor ACP discovery. Default Cursor to `cursor-agent`, map legacy `agent` configs on decode, and align update probes and spawn fallbacks with the new binary name. --- .../src/provider/acp/CursorAcpSupport.ts | 8 +++++-- packages/contracts/src/settings.test.ts | 19 +++++++++++++++++ packages/contracts/src/settings.ts | 21 ++++++++++++++++++- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/apps/server/src/provider/acp/CursorAcpSupport.ts b/apps/server/src/provider/acp/CursorAcpSupport.ts index 30203ad77b1..1112b6f4ef1 100644 --- a/apps/server/src/provider/acp/CursorAcpSupport.ts +++ b/apps/server/src/provider/acp/CursorAcpSupport.ts @@ -1,4 +1,8 @@ -import { type CursorSettings, type ProviderOptionSelection } from "@t3tools/contracts"; +import { + DEFAULT_CURSOR_BINARY_PATH, + type CursorSettings, + type ProviderOptionSelection, +} from "@t3tools/contracts"; import * as Crypto from "effect/Crypto"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; @@ -36,7 +40,7 @@ export function buildCursorAcpSpawnInput( environment?: NodeJS.ProcessEnv, ): AcpSessionRuntime.AcpSpawnInput { return { - command: cursorSettings?.binaryPath || "cursor-agent", + command: cursorSettings?.binaryPath || DEFAULT_CURSOR_BINARY_PATH, args: [ ...(cursorSettings?.apiEndpoint ? (["-e", cursorSettings.apiEndpoint] as const) : []), "acp", diff --git a/packages/contracts/src/settings.test.ts b/packages/contracts/src/settings.test.ts index ac2d47ca336..3f3b39c828a 100644 --- a/packages/contracts/src/settings.test.ts +++ b/packages/contracts/src/settings.test.ts @@ -4,6 +4,7 @@ import * as Schema from "effect/Schema"; import { ProviderInstanceId } from "./providerInstance.ts"; import { ClientSettingsSchema, + CursorSettings, DEFAULT_SERVER_SETTINGS, ServerSettings, ServerSettingsPatch, @@ -129,6 +130,24 @@ describe("ServerSettingsPatch.providerInstances", () => { }); }); +describe("CursorSettings binary path", () => { + const decodeCursorSettings = Schema.decodeUnknownSync(CursorSettings); + + it("defaults to cursor-agent", () => { + expect(decodeCursorSettings({}).binaryPath).toBe("cursor-agent"); + }); + + it("maps the legacy agent binary name to cursor-agent", () => { + expect(decodeCursorSettings({ binaryPath: "agent" }).binaryPath).toBe("cursor-agent"); + }); + + it("preserves explicit binary paths", () => { + expect(decodeCursorSettings({ binaryPath: "/usr/local/bin/agent" }).binaryPath).toBe( + "/usr/local/bin/agent", + ); + }); +}); + describe("ServerSettingsPatch string normalization", () => { it("trims string settings while decoding patches", () => { const patch = decodeServerSettingsPatch({ diff --git a/packages/contracts/src/settings.ts b/packages/contracts/src/settings.ts index b05f397bf5c..4ffab78391b 100644 --- a/packages/contracts/src/settings.ts +++ b/packages/contracts/src/settings.ts @@ -114,6 +114,25 @@ const makeBinaryPathSetting = (fallback: string) => Schema.withDecodingDefault(Effect.succeed(fallback)), ); +export const LEGACY_CURSOR_BINARY_PATH = "agent"; +export const DEFAULT_CURSOR_BINARY_PATH = "cursor-agent"; + +export const normalizeCursorBinaryPath = (value: string): string => + value === LEGACY_CURSOR_BINARY_PATH ? DEFAULT_CURSOR_BINARY_PATH : value; + +const makeCursorBinaryPathSetting = () => + TrimmedString.pipe( + Schema.decodeTo( + Schema.String, + SchemaTransformation.transformOrFail({ + decode: (value) => + Effect.succeed(normalizeCursorBinaryPath(value || DEFAULT_CURSOR_BINARY_PATH)), + encode: (value) => Effect.succeed(value), + }), + ), + Schema.withDecodingDefault(Effect.succeed(DEFAULT_CURSOR_BINARY_PATH)), + ); + export type ProviderSettingsFormControl = "text" | "password" | "textarea" | "switch"; export interface ProviderSettingsFormAnnotation { @@ -252,7 +271,7 @@ export const CursorSettings = makeProviderSettingsSchema( Schema.withDecodingDefault(Effect.succeed(false)), Schema.annotateKey({ providerSettingsForm: { hidden: true } }), ), - binaryPath: makeBinaryPathSetting("cursor-agent").pipe( + binaryPath: makeCursorBinaryPathSetting().pipe( Schema.annotateKey({ title: "Binary path", description: "Path to the Cursor agent binary.", From 220eab8083108066bd8d17d49584487583d52ddc Mon Sep 17 00:00:00 2001 From: aditya mer Date: Sun, 21 Jun 2026 17:02:43 +0530 Subject: [PATCH 2/2] refactor(cursor): use literal cursor-agent fallback in ACP spawn --- apps/server/src/provider/acp/CursorAcpSupport.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/server/src/provider/acp/CursorAcpSupport.ts b/apps/server/src/provider/acp/CursorAcpSupport.ts index 1112b6f4ef1..30203ad77b1 100644 --- a/apps/server/src/provider/acp/CursorAcpSupport.ts +++ b/apps/server/src/provider/acp/CursorAcpSupport.ts @@ -1,8 +1,4 @@ -import { - DEFAULT_CURSOR_BINARY_PATH, - type CursorSettings, - type ProviderOptionSelection, -} from "@t3tools/contracts"; +import { type CursorSettings, type ProviderOptionSelection } from "@t3tools/contracts"; import * as Crypto from "effect/Crypto"; import * as Effect from "effect/Effect"; import * as Layer from "effect/Layer"; @@ -40,7 +36,7 @@ export function buildCursorAcpSpawnInput( environment?: NodeJS.ProcessEnv, ): AcpSessionRuntime.AcpSpawnInput { return { - command: cursorSettings?.binaryPath || DEFAULT_CURSOR_BINARY_PATH, + command: cursorSettings?.binaryPath || "cursor-agent", args: [ ...(cursorSettings?.apiEndpoint ? (["-e", cursorSettings.apiEndpoint] as const) : []), "acp",