refactor(cli): restore exact-match Cursor rule (revert unsourced loosening) (#1334)

Follow-up to #1328. That PR loosened the Cursor TERM_PROGRAM check from exact
`=== "cursor"` to `?.toLowerCase() === "cursor"` "for parity with Windsurf" —
but the parity is false. Windsurf is matched case-insensitively because its
sources genuinely disagree on casing ("windsurf" vs "Windsurf"); Cursor
consistently emits lowercase "cursor", so nothing justified loosening an
existing, working, exact-match rule. Per review feedback on #1328
(Magi/Hermes), revert Cursor to exact match and drop the TERM_PROGRAM=Cursor
test. Windsurf stays case-insensitive (sourced); its comment now documents the
asymmetry as intentional.

No functional change — Cursor always emitted lowercase, so detection is
unchanged; this just removes an unsourced false-positive surface.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
James Russo
2026-06-10 18:35:01 -07:00
committed by GitHub
co-authored by Claude Fable 5
parent e6b8d66c2d
commit 30fcede44e
2 changed files with 12 additions and 19 deletions
@@ -120,12 +120,6 @@ describe("detectAgentRuntime — Cursor / Copilot / cohort", () => {
expect(detectAgentRuntime()).toBe("cursor");
});
it("detects Cursor case-insensitively (TERM_PROGRAM=Cursor)", async () => {
process.env["TERM_PROGRAM"] = "Cursor";
const { detectAgentRuntime } = await import("./agent_runtime.js");
expect(detectAgentRuntime()).toBe("cursor");
});
it("detects Copilot Coding Agent via GITHUB_ACTIONS + COPILOT_AGENT_ID", async () => {
process.env["GITHUB_ACTIONS"] = "true";
process.env["COPILOT_AGENT_ID"] = "abc123";
+12 -13
View File
@@ -74,22 +74,21 @@ const VENDOR_RULES: VendorRule[] = [
typeof env["CODEX_CI"] === "string" ||
typeof env["CODEX_SANDBOX_NETWORK_DISABLED"] === "string",
},
// Cursor IDE integrated terminal — exports TERM_PROGRAM=cursor. Compared
// case-insensitively for parity with the Windsurf rule below: Cursor sets
// lowercase today, but matching loosely costs nothing and won't miss a
// capitalized variant. Cursor Background Agent env vars are not publicly
// documented; if a canonical marker is identified later, add it here.
// Cursor IDE integrated terminal — exports TERM_PROGRAM=cursor (exact,
// lowercase). Cursor Background Agent env vars are not publicly documented;
// if a canonical marker is identified later, add it here.
{
name: "cursor",
check: (env) => env["TERM_PROGRAM"]?.toLowerCase() === "cursor",
check: (env) => env["TERM_PROGRAM"] === "cursor",
},
// Windsurf (Codeium) integrated terminal — exports TERM_PROGRAM=windsurf, the
// direct analog of the Cursor rule above. Attested across many independent
// detectors (nx packages/nx/src/native/ide/detection.rs, adonisjs/application,
// ag-grid git-hooks). Compared case-insensitively because sources disagree on
// casing ("windsurf" vs "Windsurf"). Like Cursor this marks the editor's
// integrated terminal, not specifically that the Cascade agent is driving;
// under WSL/remote it can also fall back to TERM_PROGRAM=vscode.
// Windsurf (Codeium) integrated terminal — exports TERM_PROGRAM=windsurf.
// Attested across many independent detectors (nx
// packages/nx/src/native/ide/detection.rs, adonisjs/application, ag-grid
// git-hooks). Compared case-INsensitively (unlike the exact Cursor rule
// above) because Windsurf sources disagree on casing ("windsurf" vs
// "Windsurf"); Cursor's do not, so it stays exact. Like Cursor this marks the
// editor's integrated terminal, not specifically that the Cascade agent is
// driving; under WSL/remote it can also fall back to TERM_PROGRAM=vscode.
{
name: "windsurf",
check: (env) => env["TERM_PROGRAM"]?.toLowerCase() === "windsurf",