Skip to main content

Engine Overview

The @a16njs/engine package provides the core conversion engine that orchestrates the translation between AI agent configuration formats. Use this for programmatic integrations or building custom tools.

Installation

npm install @a16njs/engine

Quick Start

import { A16nEngine } from '@a16njs/engine';
import cursorPlugin from '@a16njs/plugin-cursor';
import claudePlugin from '@a16njs/plugin-claude';

// Create engine with plugins
const engine = new A16nEngine([cursorPlugin, claudePlugin]);

// Convert between formats
const result = await engine.convert({
source: 'cursor',
target: 'claude',
root: './my-project',
});

console.log(`Wrote ${result.written.length} files`);
console.log(`Warnings: ${result.warnings.length}`);

Architecture

The engine uses a plugin-based architecture and a sequential pipeline.


API Reference

For complete API documentation including all methods, interfaces, and types, see the Engine API Reference.

Key classes and methods:

  • A16nEngine - Main engine class
    • convert(options) - Convert customizations between formats
    • discover(pluginId, root) - Find customizations without converting
    • listPlugins() - List registered plugins
    • registerPlugin(plugin) - Add a plugin at runtime

Error Handling

The engine throws errors for:

  • Unknown source or target plugin
  • File system errors (permissions, missing directories)
  • Plugin validation errors
try {
const result = await engine.convert({
source: 'unknown',
target: 'claude',
root: '.',
});
} catch (error) {
if (error instanceof Error) {
console.error('Conversion failed:', error.message);
// → "Unknown source: unknown"
}
}

Error Types

ErrorCause
Unknown source: <id>Source plugin not registered
Unknown target: <id>Target plugin not registered
ENOENT: no such filePath doesn't exist
EACCES: permission deniedFile system permission error

Complete Example

import { A16nEngine } from '@a16njs/engine';
import cursorPlugin from '@a16njs/plugin-cursor';
import claudePlugin from '@a16njs/plugin-claude';

async function migrateProject(projectPath: string) {
// Create engine
const engine = new A16nEngine([cursorPlugin, claudePlugin]);

// First, discover what exists
console.log('Discovering Cursor customizations...');
const discovery = await engine.discover('cursor', projectPath);
console.log(`Found ${discovery.items.length} items`);

if (discovery.items.length === 0) {
console.log('No customizations found.');
return;
}

// Show what was found
for (const item of discovery.items) {
console.log(` - ${item.type}: ${item.sourcePath}`);
}

// Preview conversion
console.log('\nPreviewing conversion...');
const preview = await engine.convert({
source: 'cursor',
target: 'claude',
root: projectPath,
dryRun: true,
});

console.log(`Would write ${preview.written.length} files:`);
for (const file of preview.written) {
console.log(` - ${file.path}`);
}

if (preview.warnings.length > 0) {
console.log(`\nWarnings (${preview.warnings.length}):`);
for (const warning of preview.warnings) {
console.log(` ⚠ [${warning.code}] ${warning.message}`);
}
}

// Perform actual conversion
console.log('\nConverting...');
const result = await engine.convert({
source: 'cursor',
target: 'claude',
root: projectPath,
});

console.log(`\nDone! Wrote ${result.written.length} files.`);
}

migrateProject('./my-project').catch(console.error);

See Also