OpenWriterControle/packages/compatibility-layer/docs/migration-guides/cursor-to-oac.md
Alexander Daza ca2e35c30b
feat(lint): resolve all ESLint errors and complete compatibility layer (Issue #141) (#176)
* feat: implement compatibility layer foundation (Issue #141)

- Add TypeScript project setup with strict mode and Vitest
- Implement 20+ Zod validation schemas for OpenAgent format
- Create BaseAdapter abstract class with template method pattern
- Add context documentation for compatibility layer workflow
- Setup ESLint, TypeScript, and test configuration

Phase 1 Foundation: 50% complete (subtasks 01-03)
Related: #141

* feat: implement AgentLoader with TypeScript (Issue #141)

- Add AgentLoader class for loading OAC agent files
- Implement parseFrontmatter() for YAML extraction
- Add extractSections() for markdown parsing (skills, examples, commands, workflow)
- Create custom error classes: AgentLoadError, FrontmatterParseError, ValidationError
- Support single file and recursive directory loading
- Add metadata merging from agent-metadata.json
- Export convenience functions: loadAgent(), loadAgents()
- Full Zod schema validation with descriptive error messages
- 386 lines, type-safe with strict mode

Phase 1 Foundation: 66.7% complete (subtask 04/06)
Related: #141

* feat: implement AdapterRegistry with TypeScript (Issue #141)

- Add AdapterRegistry class for managing tool adapters
- Implement type-safe registration with Map<string, BaseAdapter>
- Add alias support for adapter names (case-insensitive)
- Create custom error class: AdapterRegistryError
- Implement methods: register(), get(), list(), has(), getAll(), unregister(), clear()
- Add capability-based adapter discovery: getCapabilities(), findByFeature()
- Export singleton registry instance and convenience functions
- Support lazy loading of built-in adapters (placeholder for Phase 2)
- 416 lines, fully type-safe with strict mode

Features:
- Duplicate registration prevention
- Alias conflict detection
- O(1) adapter lookup
- Sorted adapter listings
- Comprehensive JSDoc documentation

Phase 1 Foundation: 83.3% complete (subtask 05/06)
Related: #141

* feat: create main entry point index.ts (Issue #141)

- Add comprehensive barrel exports for public API
- Export all Zod schemas and TypeScript types
- Export AgentLoader class and convenience functions
- Export AdapterRegistry, singleton, and helpers
- Export error classes: AgentLoadError, FrontmatterParseError, ValidationError, AdapterRegistryError
- Export BaseAdapter for custom adapter creation
- Add package VERSION constant
- Include JSDoc documentation with usage examples
- Organized exports by category (types, core, adapters)
- 168 lines with comprehensive documentation

All exports:
- Types: All Zod schemas and inferred TypeScript types
- Core: AgentLoader, AdapterRegistry, registry singleton
- Adapters: BaseAdapter abstract class
- Errors: All custom error classes
- Utilities: Convenience functions (loadAgent, getAdapter, etc.)

Phase 1 Foundation: 100% COMPLETE! 🎉 (6/6 subtasks)
Related: #141

* feat: implement ClaudeAdapter with bidirectional conversion (Issue #141)

- Implement ClaudeAdapter extending BaseAdapter
- Support toOAC() conversion from Claude Code format to OAC
- Support fromOAC() conversion from OAC to Claude Code format
- Handle .claude/config.json for primary agents
- Handle .claude/agents/*.md for subagents with YAML frontmatter
- Map Claude Skills system to/from OAC contexts
- Map hooks (PreToolUse, PostToolUse, etc.) bidirectionally
- Degrade granular OAC permissions to Claude permissionMode
- Add warnings for unsupported features (temperature, maxSteps)
- Export ClaudeAdapter from main index.ts

Capabilities:
- supportsMultipleAgents: true
- supportsSkills: true
- supportsHooks: true
- supportsGranularPermissions: false (binary only)
- supportsTemperature: false
- Model ID mapping (claude-sonnet-4 <-> claude-sonnet-4-20250514)
- Tool access mapping (OAC ToolAccess <-> Claude tools array)

Subtask: compatibility-layer-141-07
Phase: 2 (Adapters Migration)

* feat: implement CursorAdapter with single-file format support (Issue #141)

- Implement CursorAdapter extending BaseAdapter
- Support toOAC() conversion from .cursorrules to OAC
- Support fromOAC() conversion from OAC to .cursorrules format
- Handle single-file limitation (no multiple agents)
- Implement mergeAgents() for combining multiple OAC agents
- Parse optional YAML frontmatter in .cursorrules
- Inline context files into .cursorrules content
- Add comprehensive warnings for lost features

Key limitations:
- supportsMultipleAgents: false (single .cursorrules file)
- supportsSkills: false (must inline content)
- supportsHooks: false (not supported by Cursor)
- supportsGranularPermissions: false (binary only)
- supportsTemperature: true (limited support)

Features:
- Model ID mapping (gpt-4, claude-3-opus, etc.)
- Tool access parsing and generation
- Context file inlining with references
- Multi-agent merge capability
- Frontmatter parsing for metadata

Export CursorAdapter from main index.ts

Subtask: compatibility-layer-141-08
Phase: 2 (Adapters Migration)

* feat: implement WindsurfAdapter with bidirectional conversion (Issue #141)

- Add WindsurfAdapter.ts (514 lines) extending BaseAdapter
- Support bidirectional OAC ↔ Windsurf JSON conversion
- Implement toOAC() for Windsurf config → OpenAgent parsing
- Implement fromOAC() for OpenAgent → Windsurf config generation
- Add temperature ↔ creativity setting mapping (low/medium/high)
- Add model ID mapping (claude-sonnet-4 ↔ claude-4-sonnet)
- Support multi-agent configuration via .windsurf/agents/
- Support context files via .windsurf/context/
- Implement binary permission mapping with degradation warnings
- Add priority level normalization (critical/high/medium/low → high/low)
- Export WindsurfAdapter in index.ts
- All adapters now complete: Claude, Cursor, Windsurf
- Compilation successful: 0 errors, 0 warnings

Phase 2 (Adapters): 50% complete (3/6 subtasks)
Total progress: 28.13% (9/32 subtasks)
Code stats: 3,333 lines TypeScript (Foundation + Adapters)

* docs: add compatibility layer context files and progress tracking (Issue #141)

- Add baseadapter-implementation.md with detailed adapter pattern and testing examples
- Add compatibility-layer-development.md with development workflow and best practices
- Add compatibility-layer-adapters.md lookup table with adapter specifications
- Add compatibility-layer-progress.md tracking Phase 1 completion and Phase 2 status
- Add compatibility-learnings.md documenting implementation learnings
- Update compatibility-layer.md with latest architecture insights

These context files support Phase 2 adapter unit testing and future adapter development.

* test: implement comprehensive unit tests for ClaudeAdapter (Issue #141 - Subtask 10)

Implemented 80 test cases covering:
- toOAC() parsing of config.json and agent.md (YAML frontmatter)
- fromOAC() conversion to config.json and agent.md formats
- Capabilities and feature validation
- Model, tool, skill, hook, and permission mapping
- Skill generation from contexts
- Edge cases and error handling
- Roundtrip conversion validation

Coverage achieved:
- 96.32% statements (target: 80%+) ✅
- 100% functions (target: 80%+) ✅
- 82.14% branches (target: 75%+) ✅

All test cases follow AAA pattern (Arrange-Act-Assert) and test standards
from .opencode/context/core/standards/test-coverage.md

* test: implement comprehensive unit tests for CursorAdapter (Issue #141 - Subtask 11)

Implemented 78 test cases covering:
- toOAC() parsing of plain .cursorrules and YAML frontmatter
- fromOAC() conversion to .cursorrules format
- Capabilities and feature validation
- Agent merging (CURSOR-SPECIFIC - unique feature)
- Model, tool mapping
- Context inlining
- Temperature and configuration handling
- Edge cases and error handling
- Roundtrip conversion validation

Coverage achieved:
- 98.55% statements (target: 80%+) ✅
- 100% functions (target: 80%+) ✅
- 89.65% branches (target: 75%+) ✅

Key test areas:
- Plain text .cursorrules parsing (no frontmatter)
- YAML frontmatter parsing with type coercion
- Agent merging (single, two, three+ agents)
- Tool union and temperature MAX behavior
- Context inlining with proper formatting
- Model mapping (Cursor ↔ OAC)

All test cases follow AAA pattern and test standards.

* test: implement comprehensive unit tests for WindsurfAdapter (Issue #141 - Subtask 12)

* feat: implement Phase 3 mappers and translation engine with tests (Issue #141)

- Add ToolMapper: maps tool names between OAC and Claude/Cursor/Windsurf
- Add PermissionMapper: translates granular to binary permissions
- Add ModelMapper: maps AI model IDs between platforms
- Add ContextMapper: maps context file paths between platforms
- Add CapabilityMatrix: feature compatibility analysis across platforms
- Add TranslationEngine: orchestrates all mappers for complete translation

Test coverage:
- ToolMapper: 100% statements, 100% branches
- PermissionMapper: 98% statements, 96% branches
- ModelMapper: 99% statements, 90% branches
- ContextMapper: 97% statements, 94% branches
- CapabilityMatrix: 99% statements, 96% branches
- TranslationEngine: 99% statements, 93% branches

Total: 485 tests passing (249 new tests added)

* docs: update Issue #141 context files to reflect Phase 3 completion

- Update progress from 28% to 59.4% (19/32 subtasks)
- Mark Phases 1-3 as complete (Foundation, Adapters, Mappers)
- Update code stats: 5,799 source lines, 6,322 test lines
- Add test coverage metrics: 485 tests, 97-100% on Phase 3
- Update structure with all implemented files
- Add executive summary for token-efficient context loading
- Document next steps: Phase 4 CLI implementation

* docs(context): harvest Claude Code docs and fix MVI compliance (Phase 1)

- Harvest external Claude Code documentation into context system:
  - hooks-system, agent-skills, subagents-system concepts
  - hook-events, skill-metadata, builtin-subagents lookups
  - Example files for hooks, skills, and subagents
  - Plugin architecture and migration guides

- Fix 6 critical MVI violations (files > 200 lines):
  - Split adding-agent.md → adding-agent-basics.md + adding-agent-testing.md
  - Split adding-skill.md → 3 files (basics, implementation, example)
  - Split task-delegation.md → 3 files (basics, specialists, caching)
  - Split external-libraries.md → 3 files (workflow, scenarios, faq)
  - Split design-assets.md → 4 files (images, icons, fonts, cdn)
  - Split navigation-design.md → 2 files (basics, templates)

- Update navigation files with new references
- Remove consumed source docs from to-be-consumed/

Total: 17 new files created, 6 large files replaced, 5 source docs consumed

* docs(context): MVI compliance Phase 2 - split large workflow and UI files

Split 3 large files into MVI-compliant modules (< 200 lines each):

- design-iteration.md (1058 lines) → 9 files:
  - design-iteration-overview.md (overview, when to use)
  - design-iteration-plan-file.md (mandatory plan template)
  - design-iteration-stage-layout.md (Stage 1)
  - design-iteration-stage-theme.md (Stage 2)
  - design-iteration-stage-animation.md (Stage 3)
  - design-iteration-stage-implementation.md (Stage 4)
  - design-iteration-visual-content.md (Image Specialist)
  - design-iteration-best-practices.md (quality, troubleshooting)
  - design-iteration-plan-iterations.md (managing iterations)

- animation-patterns.md (753 lines) → 6 files:
  - animation-basics.md (fundamentals, timing, easing)
  - animation-components.md (buttons, cards, modals)
  - animation-chat.md (message, typing animations)
  - animation-loading.md (skeleton, spinner, progress)
  - animation-forms.md (focus, validation, scroll)
  - animation-advanced.md (recipes, best practices)

- premium-dark-ui-quick-start.md (638 lines) → 4 files:
  - premium-dark-ui-colors.md (palette, typography, spacing)
  - premium-dark-ui-components.md (core building blocks)
  - premium-dark-ui-layouts.md (hero, features, CTA)
  - premium-dark-ui-advanced.md (animations, accessibility)

Updated navigation files with new references.

* feat(cli): implement CLI scaffolding with Commander.js (Issue #141 - Subtask 20)

- Add src/cli/index.ts: CLI entry point with convert, validate, migrate, info commands
- Add src/cli/types.ts: TypeScript type definitions for CLI options
- Add src/cli/utils.ts: Logging, spinner, and formatting utilities
- Add "type": "module" to package.json for ESM support
- Global options: --verbose, --quiet, --output-format (json|text)
- Commands are placeholders pending implementation in subtasks 21-24

* feat(cli): implement convert command with full format support (Issue #141 - Subtask 21)

- Add src/cli/commands/convert.ts: Complete convert command implementation
- Auto-detect input format from file path and content
- Support bidirectional conversion: OAC <-> Cursor/Claude/Windsurf
- Output to stdout by default, file with --output flag
- Display warnings for feature loss during conversion
- Enable registerBuiltInAdapters in AdapterRegistry
- Add public constructors to all adapters (CursorAdapter, ClaudeAdapter, WindsurfAdapter)
- Fix ESM imports: add .js extensions to all relative imports across codebase

All 485 tests passing.

* feat(cli): implement validate and info commands (Issue #141 - Subtasks 22, 24)

- validate: Checks agent compatibility with target format
  - Reports compatibility score (0-100%)
  - Lists preserved/degraded/lost features
  - Provides suggestions for unsupported features
  - Exit codes: 0=compatible, 1=partial, 2=incompatible
  - Supports --strict and --output-format json

- info: Displays tool capabilities and feature parity
  - Shows feature matrix for all platforms
  - Detailed view for single platform
  - Platform comparison with --compare
  - Documentation links
  - Supports --output-format json

* feat(cli): implement migrate command and add migration guides (Issue #141)

- Add migrate command for full project migration with batch conversion
- Support --dry-run, --force, and --out-dir options
- Generate migration reports with success/failure summaries
- Preserve directory structure in output

Documentation:
- Add 5 migration guides (cursor↔oac, claude↔oac, oac→windsurf)
- Add comprehensive feature-matrices.md with platform comparisons
- Document lossless vs lossy conversion impacts

Completes subtasks: 23, 26, 27, 28, 29, 30, 31

* test(cli): add comprehensive integration tests for all CLI commands (Issue #141)

- Add convert.test.ts with 23 tests for format conversions
- Add validate.test.ts with 21 tests for compatibility validation
- Add migrate.test.ts with 25 tests for batch migration
- Add info.test.ts with 30 tests for capability queries
- Add test fixtures for OAC, Cursor, and Claude formats
- Fix empty directory warning in migrate command

All 584 tests passing with full coverage of CLI modules.

Completes subtask 25

* docs: update README with comprehensive CLI and API documentation (Issue #141)

- Add complete CLI command reference with all options
- Add programmatic API usage examples
- Add feature parity matrix summary
- Add links to all migration guides
- Add architecture overview
- Add custom adapter creation guide

Completes subtask 32 - Feature #141 fully implemented

* docs: add visual examples and format improvements to README

- Add Cursor IDE screenshot (contextscout-cursor.png)
- Add Claude Code validation screenshot (claude-code-validation.png)
- Format code examples with consistent double quotes
- Align feature parity matrix table
- Add .cursorrules and bun.lock to .gitignore

* fix(lint): resolve all ESLint errors in compatibility layer

- Remove async from methods with no await expressions (toOAC, fromOAC, loadFromFile)
- Wrap Promise-returning methods with Promise.resolve/reject
- Fix unsafe type assertions (replace 'as any' with proper type validation)
- Add missing getConfigPath() method to WindsurfAdapter
- Validate AgentCategory enum values before assignment
- Fix return type compatibility issues

All 584 tests passing, 0 ESLint errors (7 acceptable warnings for missing callback return types)

* chore: update package.json author and contributors metadata

- Update author from string to object format with name and GitHub URL
- Add Alexander Daza as contributor with email and GitHub profile
- Maintain npm package.json standard format for author/contributors fields
2026-02-06 00:08:14 +00:00

9.5 KiB

Migrating from Cursor to OAC

Convert your .cursorrules to OpenAgents Control format and unlock Skills, Hooks, multi-agent support, and granular permissions.

Overview

Why migrate?

Feature Cursor OAC
Multiple agents Single file only Unlimited agents
Skills system Not supported Full support
Hooks Not supported Event-driven hooks
Permissions Binary (on/off) Granular (allow/deny/ask per path)
Contexts Inline only External context files

OAC provides a superset of Cursor's capabilities while maintaining backward compatibility.

Prerequisites

Required:

  • Node.js >= 18
  • npm or pnpm

Install the compatibility layer:

npm install @openagents-control/compatibility-layer

Quick Migration

One command conversion:

oac-compat convert .cursorrules -f oac -o agent.md

This reads your .cursorrules file and generates an OAC-compatible agent.md.

Verify the result:

oac-compat validate agent.md

Step-by-Step Manual Migration

1. Cursor Rules Structure

Cursor uses a single .cursorrules file in the project root. Two formats are supported:

Plain text format:

You are a senior TypeScript developer.
Always use strict mode.
Prefer functional programming patterns.
Write comprehensive tests for all code.

Frontmatter format (optional):

---
name: typescript-dev
description: TypeScript development assistant
model: gpt-4
temperature: 0.7
---

You are a senior TypeScript developer.
Always use strict mode.
Prefer functional programming patterns.
Write comprehensive tests for all code.

2. OAC Agent Structure

OAC agents use markdown with YAML frontmatter:

---
name: typescript-dev
description: TypeScript development assistant
mode: primary
model: gpt-4
temperature: 0.7
tools:
  read: true
  write: true
  edit: true
  bash: true
  grep: true
  glob: true
---

# TypeScript Developer

You are a senior TypeScript developer.

## Guidelines

- Always use strict mode
- Prefer functional programming patterns
- Write comprehensive tests for all code

## Skills

<!-- Skills can be loaded dynamically -->

## Contexts

<!-- External context files for domain knowledge -->

3. Key Differences

Aspect Cursor OAC
File format .cursorrules (plain/YAML) .md with YAML frontmatter
Location Project root .opencode/agent/ directory
Multiple agents Not supported Full support
Tool config Implicit or comma-separated Explicit object with booleans
Permissions Binary only Granular rules per path
Context handling Inline in prompt External files with priority
Skills Not supported Dynamic skill loading
Hooks Not supported Event-driven lifecycle hooks

4. Feature Mapping

Cursor Feature OAC Equivalent Notes
name frontmatter.name Direct mapping
description frontmatter.description Direct mapping
model: gpt-4 frontmatter.model: gpt-4 Direct mapping
model: claude-3-opus frontmatter.model: claude-opus-3 Model ID normalized
model: claude-3-sonnet frontmatter.model: claude-sonnet-3 Model ID normalized
model: claude-3-haiku frontmatter.model: claude-haiku-3 Model ID normalized
temperature frontmatter.temperature Direct mapping
tools: "read, write" tools: { read: true, write: true } Object format
Plain text body systemPrompt Becomes the agent prompt
(not available) frontmatter.mode Set to primary or subagent
(not available) frontmatter.skills Add skill references
(not available) frontmatter.hooks Add lifecycle hooks
(not available) frontmatter.permission Add granular permissions
(not available) contexts Add external context files

5. Common Patterns

Pattern 1: Basic Rules

Before (Cursor):

You are a helpful coding assistant.
Follow best practices for clean code.
Always explain your changes.

After (OAC):

---
name: code-assistant
description: Helpful coding assistant
mode: primary
---

# Code Assistant

You are a helpful coding assistant.

## Guidelines

- Follow best practices for clean code
- Always explain your changes

Pattern 2: Tool Configuration

Before (Cursor):

---
name: restricted-agent
tools: read, grep, glob
---

You can only read and search files.
Do not modify any files.

After (OAC):

---
name: restricted-agent
description: Read-only agent for code analysis
mode: primary
tools:
  read: true
  grep: true
  glob: true
  write: false
  edit: false
  bash: false
---

# Restricted Agent

You can only read and search files.

## Restrictions

- Read files: ALLOWED
- Search files: ALLOWED  
- Modify files: DENIED
- Execute commands: DENIED

Pattern 3: Model Configuration

Before (Cursor):

---
name: creative-writer
model: claude-3-opus
temperature: 0.9
---

Write creative and engaging documentation.

After (OAC):

---
name: creative-writer
description: Creative documentation writer
mode: primary
model: claude-opus-3
temperature: 0.9
tools:
  read: true
  write: true
  edit: true
---

# Creative Writer

Write creative and engaging documentation.

## Style Guidelines

- Use vivid language
- Include examples
- Make content accessible

Note: Claude model IDs are normalized (claude-3-opus → claude-opus-3).


Pattern 4: Adding OAC-Exclusive Features

After migrating, enhance your agent with OAC-exclusive features:

Add Skills:

---
name: full-stack-dev
description: Full-stack development assistant
mode: primary
skills:
  - context-manager
  - task-management
---

Add Hooks:

---
name: validated-writer
description: Writer with validation hooks
mode: primary
hooks:
  - event: PreToolUse
    matchers:
      - "write"
      - "edit"
    commands:
      - type: command
        command: "npm run lint:check"
---

Add Granular Permissions:

---
name: safe-modifier
description: Agent with path-based permissions
mode: primary
permission:
  write:
    "/src/**": allow
    "/tests/**": allow
    "/config/**": ask
    "/**": deny
---

Add Contexts:

---
name: context-aware
description: Agent with external context files
mode: primary
---

# Context-Aware Agent

<!-- Contexts loaded automatically -->

With context files in .opencode/context/:

.opencode/context/
├── core/
│   ├── architecture.md
│   └── conventions.md
└── domain/
    └── business-rules.md

6. Limitations

Features that don't exist in Cursor (gained during migration):

Feature Cursor OAC Workaround
Multiple agents Single file Unlimited Create separate agent files
Skills system None Full support Inline skill content in prompt
Hooks None Event-driven Manual validation steps
Granular permissions Binary Per-path rules Document restrictions in prompt
External contexts None Priority-based Inline context in prompt
Subagent mode None Delegation support Use primary mode only
Max steps None Configurable Not available in Cursor

7. Validation

Validate your migrated agent:

# Check OAC format validity
oac-compat validate agent.md

# Compare capabilities
oac-compat info --tool cursor
oac-compat info --tool oac

# Test round-trip conversion
oac-compat convert agent.md -f cursor -o .cursorrules.test

Programmatic validation:

import { loadAgent, validateAgent } from '@openagents-control/compatibility-layer';

const agent = await loadAgent('./agent.md');
const errors = validateAgent(agent);

if (errors.length === 0) {
  console.log('Agent is valid!');
} else {
  console.error('Validation errors:', errors);
}

Troubleshooting

Frontmatter not parsing

Symptom: Agent name shows as cursor-agent instead of your custom name.

Cause: Frontmatter must have exact format with --- delimiters.

Fix:

---
name: my-agent
---

Content here...

Not:

---
name: my-agent
Content here...

Model not recognized

Symptom: Model defaults to gpt-4.

Cause: Cursor model IDs differ from OAC.

Fix: Use OAC model IDs:

Cursor OAC
claude-3-opus claude-opus-3
claude-3-sonnet claude-sonnet-3
claude-3-haiku claude-haiku-3
gpt-4 gpt-4
gpt-4-turbo gpt-4-turbo
gpt-4o gpt-4o

Tools not working

Symptom: Agent can't use expected tools.

Cause: Tools must be explicitly enabled in OAC.

Fix: Add tools to frontmatter:

tools:
  read: true
  write: true
  edit: true
  bash: true
  grep: true
  glob: true

Content appears duplicated

Symptom: System prompt contains frontmatter text.

Cause: Frontmatter delimiters missing or malformed.

Fix: Ensure proper YAML frontmatter format:

---
name: agent-name
---

Content starts here (not in frontmatter).

Next Steps