- Updated AutoModeService to track model and provider for running features, improving logging and state management. - Modified AddFeatureDialog to handle model selection for both Claude and Cursor, adjusting thinking level logic accordingly. - Expanded ModelSelector to allow provider selection and dynamically display models based on the selected provider. - Introduced new model constants for Cursor models, integrating them into the existing model management structure. - Updated README and project plan to reflect the completion of task execution integration for Cursor models.
Cursor CLI Integration Plan
Integration of Cursor Agent CLI (
cursor-agent) as an alternative AI provider in AutoMaker
Status Overview
| Phase | Name | Status | Test Status |
|---|---|---|---|
| 0 | Analysis & Documentation | completed |
✅ |
| 1 | Core Types & Configuration | completed |
✅ |
| 2 | Cursor Provider Implementation | completed |
✅ |
| 3 | Provider Factory Integration | completed |
✅ |
| 4 | Setup Routes & Status Endpoints | completed |
✅ |
| 5 | Log Parser Integration | completed |
✅ |
| 6 | UI Setup Wizard | completed |
✅ |
| 7 | Settings View Provider Tabs | completed |
✅ |
| 8 | AI Profiles Integration | completed |
✅ |
| 9 | Task Execution Integration | completed |
✅ |
| 10 | Testing & Validation | pending |
- |
Status Legend: pending | in_progress | completed | blocked
Quick Links
- Reference PR: #279 (incomplete, patterns only)
- Cursor CLI Docs: cursor.com/docs/cli
- Output Format Spec: Output Format Reference
Architecture Summary
Existing Provider Pattern
AutoMaker uses an extensible provider architecture:
BaseProvider (abstract)
├── getName(): string
├── executeQuery(options): AsyncGenerator<ProviderMessage>
├── detectInstallation(): Promise<InstallationStatus>
└── getAvailableModels(): ModelDefinition[]
ClaudeProvider extends BaseProvider
└── Uses @anthropic-ai/claude-agent-sdk
ProviderFactory
└── getProviderForModel(modelId) → routes to correct provider
Target Architecture
BaseProvider
├── ClaudeProvider (existing)
└── CursorProvider (new)
├── Spawns cursor-agent CLI process
├── Uses --output-format stream-json
└── Normalizes events to ProviderMessage format
Key Requirements
- Model Selection: Explicit model selection via config (not just "auto" mode)
- Authentication: Browser login (
cursor-agent login) as primary method - Setup Wizard: Optional CLI status check (skippable, configure later)
- AI Profiles: Separate Cursor profiles with embedded thinking mode (e.g.,
claude-sonnet-4-thinking) - Settings View: Separate tabs/sections per provider
- Streaming: Full
stream-jsonparsing with tool call events for log-viewer - Error Handling: Detailed error mapping with recovery suggestions
Cursor CLI Reference
Installation
curl https://cursor.com/install -fsS | bash
Authentication Methods
- Browser Login (Recommended):
cursor-agent login - API Key:
CURSOR_API_KEYenvironment variable
CLI Flags for Integration
cursor-agent \
-p "prompt" # Print/non-interactive mode
--model gpt-4o # Explicit model selection
--output-format stream-json # NDJSON streaming
--stream-partial-output # Real-time character streaming
--force # Allow file modifications
Available Models (from Cursor docs)
| Model ID | Description | Thinking |
|---|---|---|
auto |
Auto-select best model | - |
claude-sonnet-4 |
Claude Sonnet 4 | No |
claude-sonnet-4-thinking |
Claude Sonnet 4 + Thinking | Yes |
gpt-4o |
GPT-4o | No |
gpt-4o-mini |
GPT-4o Mini | No |
gemini-2.5-pro |
Gemini 2.5 Pro | No |
o3-mini |
O3 Mini (reasoning) | Built-in |
Stream JSON Event Types
System Init
{
"type": "system",
"subtype": "init",
"apiKeySource": "login",
"cwd": "/path",
"session_id": "uuid",
"model": "Claude 4 Sonnet",
"permissionMode": "default"
}
User Message
{
"type": "user",
"message": { "role": "user", "content": [{ "type": "text", "text": "prompt" }] },
"session_id": "uuid"
}
Assistant Message
{
"type": "assistant",
"message": { "role": "assistant", "content": [{ "type": "text", "text": "response" }] },
"session_id": "uuid"
}
Tool Call Started
{
"type": "tool_call",
"subtype": "started",
"call_id": "id",
"tool_call": { "readToolCall": { "args": { "path": "file.txt" } } },
"session_id": "uuid"
}
Tool Call Completed
{
"type": "tool_call",
"subtype": "completed",
"call_id": "id",
"tool_call": {
"readToolCall": {
"args": { "path": "file.txt" },
"result": { "success": { "content": "...", "totalLines": 54 } }
}
},
"session_id": "uuid"
}
Result (Final)
{
"type": "result",
"subtype": "success",
"duration_ms": 1234,
"is_error": false,
"result": "full text",
"session_id": "uuid"
}
File Map
Files to Create
| File | Phase | Description |
|---|---|---|
libs/types/src/cursor-models.ts |
1 | Cursor model definitions |
apps/server/src/providers/cursor-provider.ts |
2 | Main provider implementation |
apps/server/src/providers/cursor-config-manager.ts |
2 | Config file management |
apps/server/src/routes/setup/routes/cursor-status.ts |
4 | CLI status endpoint |
apps/server/src/routes/setup/routes/cursor-config.ts |
4 | Config management endpoints |
apps/ui/src/components/views/setup-view/steps/cursor-setup-step.tsx |
6 | Setup wizard step |
apps/ui/src/components/views/settings-view/providers/cursor-settings-tab.tsx |
7 | Settings tab |
apps/ui/src/components/views/settings-view/providers/provider-tabs.tsx |
7 | Tab container |
apps/server/tests/unit/providers/cursor-provider.test.ts |
10 | Unit tests |
Files to Modify
| File | Phase | Changes |
|---|---|---|
libs/types/src/index.ts |
1 | Export Cursor types |
libs/types/src/settings.ts |
1 | Extend ModelProvider type |
apps/server/src/providers/provider-factory.ts |
3 | Add Cursor routing |
apps/server/src/routes/setup/index.ts |
4 | Register Cursor routes |
apps/ui/src/lib/log-parser.ts |
5 | Add Cursor event normalization |
apps/ui/src/components/views/setup-view.tsx |
6 | Add Cursor setup step |
apps/ui/src/components/views/profiles-view/components/profile-form.tsx |
8 | Add Cursor provider fields |
apps/server/src/services/agent-service.ts |
9 | Use ProviderFactory |
Dependencies
Between Phases
Phase 0 ─────────────────────────────────────────────┐
│ │
Phase 1 (Types) ─────────────────────────────────────┤
│ │
Phase 2 (Provider) ──────────────────────────────────┤
│ │
Phase 3 (Factory) ───────────────────────────────────┤
│ │
├── Phase 4 (Routes) ────────────────────────────┤
│ │ │
│ ├── Phase 6 (Setup Wizard) ──────────────┤
│ │ │
│ └── Phase 7 (Settings View) ─────────────┤
│ │
├── Phase 5 (Log Parser) ────────────────────────┤
│ │
└── Phase 8 (Profiles) ──────────────────────────┤
│ │
Phase 9 (Execution) ─────────────────────┤
│
Phase 10 (Tests) ┘
External Dependencies
cursor-agentCLI must be installed for testing- Cursor account for authentication testing
Design Decisions
1. Use HttpApiClient for All API Requests
All UI components must use HttpApiClient from @/lib/http-api-client.ts instead of raw fetch():
// ✓ Correct - uses HttpApiClient
import { api } from '@/lib/http-api-client';
const result = await api.setup.getCursorStatus();
// ✗ Incorrect - raw fetch
const response = await fetch('/api/setup/cursor-status');
New Cursor API methods added to HttpApiClient.setup:
getCursorStatus()- Installation and auth statusgetCursorConfig()- Configuration settingssetCursorDefaultModel(model)- Update default modelsetCursorModels(models)- Update enabled models
2. Use Existing UI Components
All UI must use components from @/components/ui/*:
Card,CardHeader,CardTitle,CardContent- LayoutButton,Badge,Label- ControlsSelect,SelectContent,SelectItem,SelectTrigger,SelectValue- SelectionCheckbox- Toggle inputsAlert,AlertDescription- MessagesTabs,TabsList,TabsTrigger,TabsContent- Navigation
Icons from lucide-react:
Terminal- Cursor providerBot- Claude providerCheckCircle2,XCircle- Status indicatorsLoader2- Loading statesRefreshCw- Refresh actionExternalLink- External links
3. Cursor CLI Installation Paths
Based on official cursor-agent install script:
Linux/macOS:
- Primary symlink:
~/.local/bin/cursor-agent - Versions directory:
~/.local/share/cursor-agent/versions/<version>/cursor-agent - Fallback:
/usr/local/bin/cursor-agent
Windows:
- Primary:
%APPDATA%\Local\Programs\cursor-agent\cursor-agent.exe - Fallback:
~/.local/bin/cursor-agent.exe - Fallback:
C:\Program Files\cursor-agent\cursor-agent.exe
4. Use @automaker/* Packages
All server-side code must use shared packages from libs/:
From @automaker/types:
- Reuse existing
InstallationStatus(don't createCursorInstallationStatus) - Extend
ModelProvidertype to include'cursor' - Extend
DEFAULT_MODELSto includecursor: 'auto' - Update
ModelOption.providerfrom'claude'toModelProvider
From @automaker/utils:
import { createLogger, isAbortError } from '@automaker/utils';
const logger = createLogger('CursorProvider');
// Use isAbortError() for abort signal detection
From @automaker/platform:
import { spawnJSONLProcess, getAutomakerDir } from '@automaker/platform';
// Use spawnJSONLProcess for JSONL streaming (handles buffering, timeout, abort)
// Use getAutomakerDir for consistent .automaker path resolution
5. Do NOT Extend @automaker/model-resolver
The model-resolver is Claude-specific and should not be extended for Cursor:
- Claude uses aliases (
sonnet→claude-sonnet-4-5-20250929) - Cursor model IDs are final-form (
claude-sonnet-4passed directly to CLI) - Cursor models have metadata (
hasThinking,tier) that doesn't fit the string-only map
Cursor models use their own CURSOR_MODEL_MAP in @automaker/types.
Risk Mitigation
- Phase Isolation: Each phase can be tested independently
- Feature Flags: Cursor provider can be disabled if issues arise
- Fallback: Default to Claude provider for unknown models
- Graceful Degradation: UI shows "not installed" state clearly
How to Use This Plan
- Start with Phase 0 - Read and understand existing patterns
- Complete phases sequentially - Dependencies require order
- Test each phase - Run the verification steps before moving on
- Update status - Mark phases as
in_progress,completed, orblocked - Document issues - Add notes to individual phase files
Changelog
| Date | Phase | Change |
|---|---|---|
| 2025-12-27 | - | Initial plan created |
| 2025-12-27 | 2 | Updated findCliPath() with platform-specific paths and versions directory scanning |
| 2025-12-27 | 4 | Updated to use HttpApiClient instead of raw fetch |
| 2025-12-27 | 6 | Updated to use HttpApiClient and existing UI components |
| 2025-12-27 | 7 | Updated to use HttpApiClient and existing UI components |
| 2025-12-27 | - | Added Design Decisions section to README |
| 2025-12-27 | 2 | Updated to use createLogger from @automaker/utils |
| 2025-12-27 | 4 | Updated to use createLogger from @automaker/utils |
| 2025-12-27 | 8 | Added proper UI component imports from @/components/ui/* |
| 2025-12-27 | 1 | Added tasks 1.5-1.7: ModelOption, DEFAULT_MODELS, reuse InstallationStatus |
| 2025-12-27 | 2 | Refactored to use spawnJSONLProcess and isAbortError from @automaker packages |
| 2025-12-27 | - | Added design decisions 4-5: @automaker packages usage, model-resolver note |
| 2025-12-28 | 9 | Completed: ModelSelector with Cursor models, provider tracking in execution events |