Summary
Investigate and plan what it would take to make Crow agent-agnostic — allowing users to choose OpenAI Codex (or other AI coding agents) as an alternative to Claude Code. This requires a full audit of every Claude Code touchpoint in the codebase and a design for an abstraction layer that supports multiple agents.
Important: Wizard-Style Questions
When working this ticket, present any questions or decisions as a wizard — step-by-step prompts asking me to choose between options, one decision at a time. Don't dump all questions at once.
Why
Crow currently assumes Claude Code as the only AI coding agent. Users may prefer or need to use other tools (Codex, Aider, Cursor agent, etc.). Making the agent pluggable increases Crow's value and reach.
Scope of Investigation
Below is a complete inventory of every Claude Code integration point that needs to be studied and abstracted.
1. Binary Resolution & Launch (3 touchpoints)
| File |
Location |
What It Does |
SessionService.swift |
lines 551-562 |
findClaudeBinary() — searches hardcoded paths (~/.local/bin/claude, /usr/local/bin/claude, /opt/homebrew/bin/claude) |
AppDelegate.swift |
lines 780-799 |
resolveClaudeInCommand() — replaces bare "claude" tokens in terminal commands with full path |
SessionService.swift |
lines 98-99 |
launchClaude(terminalID:) — sends claude --continue\n to terminal after shell readiness |
Questions to answer: How does Codex launch? Is it a CLI binary like Claude? What are its CLI flags? Does it support --continue equivalent?
2. Hook System (17 event types, 3 touchpoints)
| File |
Location |
What It Does |
HookConfigGenerator.swift |
lines 7-13 |
Defines 17 hook events: SessionStart, SessionEnd, Stop, StopFailure, Notification, PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest, PermissionDenied, UserPromptSubmit, TaskCreated, TaskCompleted, SubagentStart, SubagentStop, PreCompact, PostCompact |
HookConfigGenerator.swift |
lines 28-90 |
generateHooks() / writeHookConfig() — writes hook entries to .claude/settings.local.json that invoke crow hook-event |
HookConfigGenerator.swift |
lines 93-120 |
removeHookConfig() — cleans up hook entries on session deletion |
Questions to answer: Does Codex support lifecycle hooks? What events does it emit? Can we get equivalent state signals (working, waiting, idle)?
3. Hook Event State Machine (1 large touchpoint)
| File |
Location |
What It Does |
AppDelegate.swift |
lines 572-749 |
hook-event RPC handler — receives events from crow hook-event CLI calls, updates SessionHookState with Claude-specific state transitions (idle → working → waiting → done) |
Questions to answer: Can we map Codex lifecycle events to the same state machine? Or do we need a per-agent state mapping?
4. Settings & Skills Scaffolding (3 touchpoints)
| File |
Location |
What It Does |
Scaffolder.swift |
lines 114-143 |
bundledSettings() — generates .claude/settings.json with pre-approved permissions for Bash, Read, Write, Edit, etc. |
Scaffolder.swift |
lines 93-111 |
bundledSkill() — deploys skills/crow-workspace/SKILL.md to .claude/skills/ |
Scaffolder.swift |
lines 69-90 |
bundledCLAUDEMD() — generates/updates CLAUDE.md context file |
Questions to answer: Does Codex have an equivalent to .claude/ config directory? Skills? Settings? Context files like CLAUDE.md?
5. Prompt Generation & Templates (2 touchpoints)
| File |
Location |
What It Does |
ClaudeLauncher.swift |
lines 9-51 |
generatePrompt() — builds /plan prefixed prompt with workspace context table, ticket info, gh/glab commands |
ClaudeLauncher.swift |
lines 54-62 |
launchCommand() — writes prompt to temp file, returns cd {path} && claude "$(cat {promptPath})"\n |
Questions to answer: How does Codex accept initial prompts? File-based? Stdin? CLI arg? Does it support plan mode?
6. Terminal Readiness & Auto-Launch (3 touchpoints)
| File |
Location |
What It Does |
SessionDetailView.swift |
lines 350-389 |
ReadinessAwareTerminal — triggers onLaunchClaude callback when shell reaches .shellReady |
AppState.swift |
line 83 |
onLaunchClaude: ((UUID) -> Void)? closure |
Enums.swift |
lines 37-45 |
TerminalReadiness enum (uninitialized → surfaceCreated → shellReady → claudeLaunched) and ClaudeState enum (idle, working, waiting, done) |
Questions to answer: Should the readiness enum be renamed to be agent-agnostic? Is the launch flow the same for Codex?
7. UI & Branding References (2 touchpoints)
| File |
Location |
What It Does |
SessionListView.swift |
lines 217-414 |
claudeStateBadge — shows Claude state with icon and color in sidebar |
SessionDetailView.swift |
lines 370-380 |
Loading overlay text while terminal initializes |
Questions to answer: Should the UI show which agent is active? Agent-specific icons/colors?
8. Manager Session Integration (1 touchpoint)
| File |
Location |
What It Does |
AppDelegate.swift |
lines 139-149 |
onWorkOnIssue — sends /crow-workspace {issueURL}\n to Manager terminal (assumes Claude Code is running) |
Questions to answer: The Manager session itself runs Claude Code. Should this also be swappable? Or is the Manager always Claude Code?
9. Notification System (1 touchpoint)
| File |
Location |
What It Does |
NotificationManager.swift |
lines 51-98 |
handleEvent() — processes hook events for system notifications and sounds |
Questions to answer: Notification events are currently keyed to Claude Code hook names. Need agent-agnostic event mapping.
10. Documentation & Context Files (4 touchpoints)
| File |
Description |
CLAUDE.md |
Manager tab context document (139 lines) |
README.md |
Architecture docs reference Claude Code throughout |
skills/crow-workspace/SKILL.md |
Full workspace setup skill (423 lines) |
Resources/*.template |
Bundled templates for CLAUDE.md and SKILL.md |
11. Configuration & Models (2 touchpoints)
| File |
Description |
settings.json |
Pre-approved permissions template (Claude Code specific format) |
WorkspaceConfig.swift |
References CLAUDE.md in keyword sources |
Architectural Decisions to Make
- Abstraction layer — Should we introduce an
AgentProtocol / AgentProvider abstraction? Or use config-driven switching?
- Per-session vs global — Can different sessions use different agents? Or is it a global app setting?
- Hook compatibility — If Codex doesn't support hooks, do we poll terminal output instead? Or require hooks?
- Skill system — Do we need agent-specific skill files, or one universal format?
- Manager session — Is the Manager tab always Claude Code? Or also swappable?
- Feature parity — What Claude Code features does Codex lack? What's the minimum viable integration?
Suggested Approach
- Research Codex CLI capabilities, flags, config format, and lifecycle events
- Design an
AgentProvider protocol with methods: findBinary(), launchCommand(), generatePrompt(), hookConfig(), settingsConfig()
- Implement
ClaudeCodeProvider (extracting current behavior) and CodexProvider
- Add agent selection to workspace config or session creation
- Update UI to be agent-aware
- Update documentation and templates
Files That Will Need Changes
~20 files across the codebase:
SessionService.swift, AppDelegate.swift, HookConfigGenerator.swift, Scaffolder.swift, ClaudeLauncher.swift
SessionDetailView.swift, SessionListView.swift, AppState.swift, Enums.swift
NotificationManager.swift, CrowCLI.swift, WorkspaceConfig.swift
CLAUDE.md, README.md, SKILL.md, settings.json, template files
Priority: 3/10
Effort: Large (multi-day)
Summary
Investigate and plan what it would take to make Crow agent-agnostic — allowing users to choose OpenAI Codex (or other AI coding agents) as an alternative to Claude Code. This requires a full audit of every Claude Code touchpoint in the codebase and a design for an abstraction layer that supports multiple agents.
Important: Wizard-Style Questions
When working this ticket, present any questions or decisions as a wizard — step-by-step prompts asking me to choose between options, one decision at a time. Don't dump all questions at once.
Why
Crow currently assumes Claude Code as the only AI coding agent. Users may prefer or need to use other tools (Codex, Aider, Cursor agent, etc.). Making the agent pluggable increases Crow's value and reach.
Scope of Investigation
Below is a complete inventory of every Claude Code integration point that needs to be studied and abstracted.
1. Binary Resolution & Launch (3 touchpoints)
SessionService.swiftfindClaudeBinary()— searches hardcoded paths (~/.local/bin/claude,/usr/local/bin/claude,/opt/homebrew/bin/claude)AppDelegate.swiftresolveClaudeInCommand()— replaces bare "claude" tokens in terminal commands with full pathSessionService.swiftlaunchClaude(terminalID:)— sendsclaude --continue\nto terminal after shell readinessQuestions to answer: How does Codex launch? Is it a CLI binary like Claude? What are its CLI flags? Does it support
--continueequivalent?2. Hook System (17 event types, 3 touchpoints)
HookConfigGenerator.swiftHookConfigGenerator.swiftgenerateHooks()/writeHookConfig()— writes hook entries to.claude/settings.local.jsonthat invokecrow hook-eventHookConfigGenerator.swiftremoveHookConfig()— cleans up hook entries on session deletionQuestions to answer: Does Codex support lifecycle hooks? What events does it emit? Can we get equivalent state signals (working, waiting, idle)?
3. Hook Event State Machine (1 large touchpoint)
AppDelegate.swifthook-eventRPC handler — receives events fromcrow hook-eventCLI calls, updatesSessionHookStatewith Claude-specific state transitions (idle → working → waiting → done)Questions to answer: Can we map Codex lifecycle events to the same state machine? Or do we need a per-agent state mapping?
4. Settings & Skills Scaffolding (3 touchpoints)
Scaffolder.swiftbundledSettings()— generates.claude/settings.jsonwith pre-approved permissions for Bash, Read, Write, Edit, etc.Scaffolder.swiftbundledSkill()— deploysskills/crow-workspace/SKILL.mdto.claude/skills/Scaffolder.swiftbundledCLAUDEMD()— generates/updatesCLAUDE.mdcontext fileQuestions to answer: Does Codex have an equivalent to
.claude/config directory? Skills? Settings? Context files like CLAUDE.md?5. Prompt Generation & Templates (2 touchpoints)
ClaudeLauncher.swiftgeneratePrompt()— builds/planprefixed prompt with workspace context table, ticket info, gh/glab commandsClaudeLauncher.swiftlaunchCommand()— writes prompt to temp file, returnscd {path} && claude "$(cat {promptPath})"\nQuestions to answer: How does Codex accept initial prompts? File-based? Stdin? CLI arg? Does it support plan mode?
6. Terminal Readiness & Auto-Launch (3 touchpoints)
SessionDetailView.swiftReadinessAwareTerminal— triggersonLaunchClaudecallback when shell reaches.shellReadyAppState.swiftonLaunchClaude: ((UUID) -> Void)?closureEnums.swiftTerminalReadinessenum (uninitialized → surfaceCreated → shellReady → claudeLaunched) andClaudeStateenum (idle, working, waiting, done)Questions to answer: Should the readiness enum be renamed to be agent-agnostic? Is the launch flow the same for Codex?
7. UI & Branding References (2 touchpoints)
SessionListView.swiftclaudeStateBadge— shows Claude state with icon and color in sidebarSessionDetailView.swiftQuestions to answer: Should the UI show which agent is active? Agent-specific icons/colors?
8. Manager Session Integration (1 touchpoint)
AppDelegate.swiftonWorkOnIssue— sends/crow-workspace {issueURL}\nto Manager terminal (assumes Claude Code is running)Questions to answer: The Manager session itself runs Claude Code. Should this also be swappable? Or is the Manager always Claude Code?
9. Notification System (1 touchpoint)
NotificationManager.swifthandleEvent()— processes hook events for system notifications and soundsQuestions to answer: Notification events are currently keyed to Claude Code hook names. Need agent-agnostic event mapping.
10. Documentation & Context Files (4 touchpoints)
CLAUDE.mdREADME.mdskills/crow-workspace/SKILL.mdResources/*.template11. Configuration & Models (2 touchpoints)
settings.jsonWorkspaceConfig.swiftCLAUDE.mdin keyword sourcesArchitectural Decisions to Make
AgentProtocol/AgentProviderabstraction? Or use config-driven switching?Suggested Approach
AgentProviderprotocol with methods:findBinary(),launchCommand(),generatePrompt(),hookConfig(),settingsConfig()ClaudeCodeProvider(extracting current behavior) andCodexProviderFiles That Will Need Changes
~20 files across the codebase:
SessionService.swift,AppDelegate.swift,HookConfigGenerator.swift,Scaffolder.swift,ClaudeLauncher.swiftSessionDetailView.swift,SessionListView.swift,AppState.swift,Enums.swiftNotificationManager.swift,CrowCLI.swift,WorkspaceConfig.swiftCLAUDE.md,README.md,SKILL.md,settings.json, template filesPriority: 3/10
Effort: Large (multi-day)