You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Lands a Cursor agent for Crow on the existing CodingAgent protocol that PR #197 established. Mirrors the Packages/CrowCodex/ pattern but reuses Packages/CrowClaude/-shaped implementations for the hook layer because Cursor's hook engine is a superset of Claude's, not a no-op like Codex's per-session writer.
Supersedes #401 (the broad investigation — Phases A & B from #197 already answered most of it; this ticket scopes the remaining Phase-C-equivalent work for Cursor specifically).
Config layered Enterprise → Team → Project → User. Project hooks live at <project>/.cursor/hooks.json; user hooks at ~/.cursor/hooks.json. Stdin JSON in, stdout JSON out. Exit code 0/2 convention "matches Claude Code behavior for compatibility." Cursor sets CLAUDE_PROJECT_DIR as an alias of CURSOR_PROJECT_DIR "for Claude compatibility" and "supports loading hooks from third-party tools like Claude Code."
Differences from Claude:
Event names are camelCase (preToolUse) vs PascalCase (PreToolUse). Mapping layer needed.
Cursor splits tool gating into generic (preToolUse) + specialized (beforeShellExecution/beforeMCPExecution/beforeReadFile). More granular state available.
Field correlation uses conversation_id + generation_id rather than Claude's session ids.
Cursor reads .claude/skills/, .codex/skills/, ~/.claude/skills/, ~/.codex/skills/ directly for compat. Crow's existing .claude/skills/* directory (/crow-create-ticket, /crow-workspace, /crow-review-pr, etc.) works in Cursor sessions out of the box. Schema: SKILL.md + YAML frontmatter (name, description, paths, disable-model-invocation). No scaffolder work required for slash commands.
Config / paths
Global CLI config: ~/.cursor/cli-config.json (pure JSON, no comments).
Project CLI config: <project>/.cursor/cli.json (permissions only — everything else global).
Override via CURSOR_CONFIG_DIR env or XDG_CONFIG_HOME on Linux.
Project rules (instruction file)
.cursor/rules/*.mdc with frontmatter alwaysApply, description, globs — modern.
AGENTS.md — simple alternative; same file Codex uses; reuse the existing Resources/AGENTS.md.template.
.cursorrules — silent in docs (presumed legacy; don't bother).
Implementation plan
Packages/CrowCursor/ (new package; mirrors Packages/CrowCodex/ shape)
CursorAgent — displayName: "Cursor", iconSystemName, launchCommandToken: "agent", findBinary(), autoLaunchCommand(...) that resolves to agent (interactive) / agent -p (one-shot) / agent --continue / agent --resume=<id> based on session state. supportsRemoteControl = true (hook engine + stop.followup_message for auto-continue).
CursorHookConfigWriter — writes ~/.cursor/hooks.json at app launch (global, same single-file pattern as CodexHookConfigWriter). Hooks resolved on Cursor's side use CLAUDE_PROJECT_DIR alias so Crow's per-worktree resolution still works. Per-worktree project-level hooks at <worktree>/.cursor/hooks.json if needed; start with global-only for MVP.
CursorSignalSource — subscribes to a curated event subset: sessionStart, preToolUse, postToolUse, postToolUseFailure, beforeShellExecution, afterShellExecution, beforeSubmitPrompt, stop, afterAgentResponse. CamelCase ↔ PascalCase mapping layer. Use conversation_id as the session correlation key. Same exit-code 0/2 protocol.
CursorScaffolder — reuses Resources/AGENTS.md.template already shipped by CrowCodex. Preserves the user's ## Known Issues / Corrections section. Optionally writes a .cursor/rules/crow.mdc per-worktree pointing back at AGENTS.md (TBD — empirical: do Cursor rules add anything Crow needs that AGENTS.md doesn't already give us?).
CursorLauncher, CursorNotifyPayload — bridge Cursor hook payloads → AgentHookEvent. For MVP, the notify channel can piggyback on the same crow hook-event --agent CLI used by Codex; new crow cursor-notify subcommand only if Cursor's emit shape diverges from what hook-event already accepts.
Wiring in AppDelegate / SessionService
Register CursorAgent at app launch alongside ClaudeCodeAgent and OpenAICodexAgent, gated on findBinary() returning a real path. No change if agent isn't installed.
New crow cursor-notify only if needed (defer until hook routing in MVP exposes a real gap).
Three things to confirm empirically during implementation
These are the only gaps the doc fetch didn't close. Address inline during C-equivalent dev work, not as a separate sub-issue.
Does agent -p (headless print mode) honor ~/.cursor/hooks.json? Docs detail hooks for Cmd+K + Agent Chat + Cloud Agents (reduced set), but headless mode is silent. Test: drop a beforeShellExecution hook that writes to a file, run agent -p with a prompt that triggers a shell call, see whether the hook fires. If it doesn't, fall back to --output-format stream-json as the signal source for headless runs — Cursor emits typed events (system, assistant, tool_call start/completed, result with duration_ms) on stdout. CursorSignalSource parses the JSONL stream as an alternate input path.
Exit codes for the agent binary. Docs only state "0 = success". Run failure scenarios (bad API key, rate limit, network failure, timeout, permission denied) and document the real codes. Drives the .error transitions in CursorSignalSource.
.cursorrules legacy file — does Cursor still read it, or is it dropped in current versions? Silent in docs. CursorScaffolder should not write one either way; just confirm Cursor doesn't surface a warning when only AGENTS.md is present.
Manual: submit a prompt to Cursor — sidebar transitions .idle → .working → .done on afterAgentResponse (or result event in stream-json fallback).
Manual: crow send to a Cursor session works (verifies supportsRemoteControl = true).
Manual: existing Claude session in parallel behaves identically — per-worktree .claude/settings.local.json, --continue, OTEL env unchanged.
Manual: Manager session still hardcoded to .claudeCode.
Manual: Cursor session reads Crow's .claude/skills/* slash commands (e.g. user can run /crow-create-ticket from inside a Cursor session). This verifies the Skills compat claim.
Manual: AGENTS.md written by CursorScaffolder doesn't clobber an existing one written by CodexScaffolder — preserves ## Known Issues / Corrections section.
L. Mirrors Codex's PR #197 sizing (~2,500 lines) but with a real HookConfigWriter and SignalSource (closer to CrowClaude shapes than CrowCodex no-ops), partially offset by reusing AGENTS.md.template and the existing CLI flag plumbing.
Lands a Cursor agent for Crow on the existing
CodingAgentprotocol that PR #197 established. Mirrors thePackages/CrowCodex/pattern but reusesPackages/CrowClaude/-shaped implementations for the hook layer because Cursor's hook engine is a superset of Claude's, not a no-op like Codex's per-session writer.Supersedes #401 (the broad investigation — Phases A & B from #197 already answered most of it; this ticket scopes the remaining Phase-C-equivalent work for Cursor specifically).
What's already in place from PR #197
CrowCore/Agent/*protocols:CodingAgent,AgentKind,AgentRegistry,StateSignalSource,AgentStateTransition,HookConfigWriter,AgentHookEvent.Session.agentKind,AppConfig.defaultAgentKind, picker inCreateSessionView+ Settings,crow new-session --agent <kind>, RPCagent_kind.Resources/AGENTS.md.template(written byCodexScaffoldertoday; reused here).So this ticket is Phase C analog only — a new
Packages/CrowCursor/package and the minimal wiring to register it.CLI surface (from docs.cursor.com)
agent, notcursor.agent. Initial prompt as positional:agent "refactor auth".agent -p "<prompt>" --output-format <text|json|stream-json>with optional--stream-partial-output.--force/--yoloenables file modifications.agent --continue,agent --resume="<chat-id>",agent ls,agent resume. Better parity than Codex.CURSOR_API_KEYenv var for scripts; GUI-stored creds inherited otherwise.--sandbox enabled|disabled(Cursor-specific)./plan,/ask,/sandbox,/max-mode [on|off].Hook surface (https://cursor.com/docs/hooks)
Superset of Claude Code's hook engine. 20+ events:
sessionStart,sessionEnd,preToolUse,postToolUse,postToolUseFailure,subagentStart,subagentStop,beforeShellExecution,afterShellExecution,beforeMCPExecution,afterMCPExecution,beforeReadFile,afterFileEdit,beforeSubmitPrompt,preCompact,stop,afterAgentResponse,afterAgentThought.beforeTabFileRead,afterTabFileEdit.workspaceOpen.Config layered Enterprise → Team → Project → User. Project hooks live at
<project>/.cursor/hooks.json; user hooks at~/.cursor/hooks.json. Stdin JSON in, stdout JSON out. Exit code 0/2 convention "matches Claude Code behavior for compatibility." Cursor setsCLAUDE_PROJECT_DIRas an alias ofCURSOR_PROJECT_DIR"for Claude compatibility" and "supports loading hooks from third-party tools like Claude Code."Differences from Claude:
preToolUse) vs PascalCase (PreToolUse). Mapping layer needed.preToolUse) + specialized (beforeShellExecution/beforeMCPExecution/beforeReadFile). More granular state available.conversation_id+generation_idrather than Claude's session ids.Skills compat (https://cursor.com/docs/skills)
Cursor reads
.claude/skills/,.codex/skills/,~/.claude/skills/,~/.codex/skills/directly for compat. Crow's existing.claude/skills/*directory (/crow-create-ticket,/crow-workspace,/crow-review-pr, etc.) works in Cursor sessions out of the box. Schema:SKILL.md+ YAML frontmatter (name,description,paths,disable-model-invocation). No scaffolder work required for slash commands.Config / paths
~/.cursor/cli-config.json(pure JSON, no comments).<project>/.cursor/cli.json(permissions only — everything else global).CURSOR_CONFIG_DIRenv orXDG_CONFIG_HOMEon Linux.Project rules (instruction file)
.cursor/rules/*.mdcwith frontmatteralwaysApply,description,globs— modern.AGENTS.md— simple alternative; same file Codex uses; reuse the existingResources/AGENTS.md.template..cursorrules— silent in docs (presumed legacy; don't bother).Implementation plan
Packages/CrowCursor/(new package; mirrorsPackages/CrowCodex/shape)CursorAgent—displayName: "Cursor",iconSystemName,launchCommandToken: "agent",findBinary(),autoLaunchCommand(...)that resolves toagent(interactive) /agent -p(one-shot) /agent --continue/agent --resume=<id>based on session state.supportsRemoteControl = true(hook engine +stop.followup_messagefor auto-continue).CursorHookConfigWriter— writes~/.cursor/hooks.jsonat app launch (global, same single-file pattern asCodexHookConfigWriter). Hooks resolved on Cursor's side useCLAUDE_PROJECT_DIRalias so Crow's per-worktree resolution still works. Per-worktree project-level hooks at<worktree>/.cursor/hooks.jsonif needed; start with global-only for MVP.CursorSignalSource— subscribes to a curated event subset:sessionStart,preToolUse,postToolUse,postToolUseFailure,beforeShellExecution,afterShellExecution,beforeSubmitPrompt,stop,afterAgentResponse. CamelCase ↔ PascalCase mapping layer. Useconversation_idas the session correlation key. Same exit-code 0/2 protocol.CursorScaffolder— reusesResources/AGENTS.md.templatealready shipped byCrowCodex. Preserves the user's## Known Issues / Correctionssection. Optionally writes a.cursor/rules/crow.mdcper-worktree pointing back at AGENTS.md (TBD — empirical: do Cursor rules add anything Crow needs that AGENTS.md doesn't already give us?).CursorLauncher,CursorNotifyPayload— bridge Cursor hook payloads →AgentHookEvent. For MVP, the notify channel can piggyback on the samecrow hook-event --agentCLI used by Codex; newcrow cursor-notifysubcommand only if Cursor's emit shape diverges from whathook-eventalready accepts.Wiring in
AppDelegate/SessionServiceCursorAgentat app launch alongsideClaudeCodeAgentandOpenAICodexAgent, gated onfindBinary()returning a real path. No change ifagentisn't installed.SessionService.launchAgentalready dispatches viaagent.autoLaunchCommandafter Phases A + B + C: agent abstraction + OpenAI Codex MVP #197 — no per-agent special-casing needed.RemoteControlBadgerenders for Cursor sessions (becausesupportsRemoteControl = true).cursorarrow.raysor similar SF symbol; final pick goes to the implementer).CLI changes
crow new-session --agent cursorworks via the existing flag plumbing from Phases A + B + C: agent abstraction + OpenAI Codex MVP #197 Phase B.crow hook-eventalready grew--agentin Phases A + B + C: agent abstraction + OpenAI Codex MVP #197 — accepts--agent cursorfor Cursor's emits.crow cursor-notifyonly if needed (defer until hook routing in MVP exposes a real gap).Three things to confirm empirically during implementation
These are the only gaps the doc fetch didn't close. Address inline during C-equivalent dev work, not as a separate sub-issue.
agent -p(headless print mode) honor~/.cursor/hooks.json? Docs detail hooks for Cmd+K + Agent Chat + Cloud Agents (reduced set), but headless mode is silent. Test: drop abeforeShellExecutionhook that writes to a file, runagent -pwith a prompt that triggers a shell call, see whether the hook fires. If it doesn't, fall back to--output-format stream-jsonas the signal source for headless runs — Cursor emits typed events (system,assistant,tool_callstart/completed,resultwithduration_ms) on stdout.CursorSignalSourceparses the JSONL stream as an alternate input path.agentbinary. Docs only state "0 = success". Run failure scenarios (bad API key, rate limit, network failure, timeout, permission denied) and document the real codes. Drives the.errortransitions inCursorSignalSource..cursorruleslegacy file — does Cursor still read it, or is it dropped in current versions? Silent in docs.CursorScaffoldershould not write one either way; just confirm Cursor doesn't surface a warning when onlyAGENTS.mdis present.Test plan (mirrors PR #197 Phase C)
swift testat repo root passes.swift testin every sub-package including newCrowCursor(target ~20–25 tests).agentinstalled — picker stays disabled with two agents; no~/.cursor/files written.agentinstalled — picker enables and shows all three agents;~/.cursor/hooks.jsonwritten at first launch.agent; sidebar icon shows the Cursor symbol; detail header shows "Agent: Cursor";RemoteControlBadgerenders..idle → .working → .doneonafterAgentResponse(orresultevent in stream-json fallback).crow sendto a Cursor session works (verifiessupportsRemoteControl = true)..claude/settings.local.json,--continue, OTEL env unchanged..claudeCode..claude/skills/*slash commands (e.g. user can run/crow-create-ticketfrom inside a Cursor session). This verifies the Skills compat claim.AGENTS.mdwritten byCursorScaffolderdoesn't clobber an existing one written byCodexScaffolder— preserves## Known Issues / Correctionssection.Supersedes / closes
Effort
L. Mirrors Codex's PR #197 sizing (~2,500 lines) but with a real
HookConfigWriterandSignalSource(closer toCrowClaudeshapes thanCrowCodexno-ops), partially offset by reusingAGENTS.md.templateand the existing CLI flag plumbing.🐦⬛ Created with Crow via Claude Code