CLI Package - Development Guide
Note: This guide is for developers who want to understand, extend, or contribute to the command-line interface component of n8n-as-code.
๐ฏ Purposeโ
The CLI package (n8nac) provides a command-line interface for managing n8n workflows from the terminal. It offers:
- Project Management: Initialize and configure n8n-as-code projects
- Workflow Synchronization: Sync workflows between local files and n8n with git-like commands
- AI Assistance: AI-powered workflow generation and assistance
๐๏ธ Architectureโ
Package Structureโ
packages/cli/
โโโ src/
โ โโโ index.ts # CLI entry point (registers all commands)
โ โโโ commands/
โ โ โโโ base.ts # Base command class
โ โ โโโ init.ts # Init command
โ โ โโโ init-ai.ts # UpdateAiCommand (init-ai is a backward-compat alias)
โ โ โโโ list.ts # List command
โ โ โโโ switch.ts # Switch project command
โ โ โโโ convert.ts # Convert command (JSON โ TypeScript)
โ โ โโโ sync.ts # Sync command (pull / push / fetch / resolve)
โ โโโ core/
โ โ โโโ types.ts # WorkflowSyncStatus enum, interfaces
โ โ โโโ sync-manager.ts # Core sync engine
โ โ โโโ ... # API client, services
โ โโโ services/
โ โโโ config-service.ts # Configuration management
โโโ bin/
โ โโโ n8n-as-code.js # CLI executable
โโโ package.json # Package manifest
โโโ tsconfig.json # TypeScript configuration
Command Hierarchyโ
graph TD
A[n8n-as-code CLI] --> B[BaseCommand]
B --> C[InitCommand]
B --> D[UpdateAiCommand]
B --> E[SyncCommand]
B --> F[ListCommand]
B --> G[SwitchCommand]
B --> H[ConvertCommand]
D --> |init-ai alias| D
C --> I[CLI Core / Sync Engine]
E --> |pull/push/fetch/resolve| I
F --> I
G --> I
D --> J[AI Services]
H --> K[@n8n-as-code/transformer]
style A fill:#ff6b35
style B fill:#3498db
style C fill:#2ecc71
style D fill:#9b59b6
style E fill:#e74c3c
๐งฉ Sync Componentsโ
1. CLI Entry Point (index.ts)โ
The main entry point that sets up the CLI application.
Key Responsibilities:
- Parse command-line arguments
- Initialize configuration
- Execute appropriate command
- Handle global errors
Setup:
import { Command } from 'commander';
import { InitCommand, SyncCommand, ListCommand, InitAICommand } from './commands';
const program = new Command();
program
.name('n8n-as-code')
.description('Manage n8n workflows as code')
.version(version);
// Register commands
new InitCommand(program);
new SyncCommand(program);
new ListCommand(program);
new InitAICommand(program);
program.parse(process.argv);
2. Base Command (commands/base.ts)โ
Abstract base class for all commands.
Key Responsibilities:
- Provide common command functionality
- Handle error reporting
- Manage configuration loading
- Provide logging utilities
Base Implementation:
abstract class BaseCommand {
protected config: Config;
protected logger: Logger;
constructor(protected program: Command) {
this.config = ConfigService.load();
this.logger = new Logger(program.opts().verbose);
}
abstract execute(options: any): Promise<void>;
protected handleError(error: Error): void {
this.logger.error(error.message);
process.exit(1);
}
}
3. Init Command (commands/init.ts)โ
Initializes a new n8n-as-code project.
Key Responsibilities:
- Create project directory structure
- Generate configuration files
- Set up n8n instance connections
- Initialize Git repository (optional)
Implementation:
class InitCommand extends BaseCommand {
constructor(program: Command) {
super(program);
program
.command('init')
.description('Initialize a new n8n-as-code project')
.option('--host <url>', 'n8n instance URL')
.option('--api-key <key>', 'n8n API key')
.option('--no-git', 'Skip Git initialization')
.action(this.execute.bind(this));
}
async execute(options: any): Promise<void> {
// Create directory structure
// Generate config file
// Test connection to n8n
// Initialize Git if requested
}
}
4. Sync Command (commands/sync.ts)โ
Synchronizes workflows between local files and n8n.
Key Responsibilities:
- Pull workflows from n8n to local files
- Push local workflows to n8n
- Handle conflicts and resolutions
- Provide sync progress reporting
Sync Modes:
interface SyncOptions {
mode: 'pull' | 'push' | 'both';
force: boolean;
dryRun: boolean;
instance?: string;
}
5. List Command (commands/list.ts)โ
Shows current sync status of all workflows.
Key Responsibilities:
- Fetch fresh remote metadata on each invocation
- Calculate 3-way status (local vs remote vs base)
- Display color-coded status table
- Support
--local/--remotefilters for focused views
6. Update AI Command (commands/init-ai.ts)โ
Regenerates AI context files for the project.
Key Responsibilities:
- Generate
AGENTS.mdwith n8n-specific AI agent instructions - Generate
.vscode/n8n.code-snippetsfrom the n8n node index - Optionally connect to n8n to embed the running instance version
The class UpdateAiCommand registers the update-ai command. InitAiCommand extends it as a backward-compatible alias for init-ai.
7. Config Service (services/config-service.ts)โ
Manages CLI configuration.
Key Responsibilities:
- Load configuration from multiple sources
- Validate configuration
- Merge environment variables and file config
- Provide typed configuration access
Configuration Sources:
The CLI currently loads local configuration from n8nac-config.json in the current working directory and stores API keys in a secure global credential store.
๐ Integration with CLI Coreโ
Sync Engine Usageโ
The CLI commands use the sync engine (embedded in packages/cli/src/core/):
import { SyncManager, StateManager, N8nApiClient } from 'n8nac';
class SyncCommand extends BaseCommand {
private syncManager: SyncManager;
constructor() {
super();
this.syncManager = new SyncManager(this.config);
}
async execute(options: any): Promise<void> {
const result = await this.syncManager.sync({
mode: options.mode,
force: options.force
});
this.logger.reportSyncResult(result);
}
}
Event Handlingโ
The CLI listens to Sync library events:
syncManager.on('sync:progress', (progress) => {
this.logger.progress(progress);
});
syncManager.on('sync:conflict', (conflict) => {
this.logger.conflict(conflict);
// Prompt user for resolution
});
syncManager.on('sync:complete', (result) => {
this.logger.success(`Synced ${result.synced} workflows`);
});
๐ ๏ธ Development Setupโ
Prerequisitesโ
- Node.js 18+
- n8n instance for testing
- Git (for version control features)
Local Developmentโ
# Install dependencies
cd packages/cli
npm install
# Build CLI
npm run build
# Link for local testing
npm link
# Test commands
n8nac --help
Testing with Local n8nโ
- Start a local n8n instance
- Get API key from n8n settings
- Configure CLI:
n8nac init
๐ง Adding New Commandsโ
Step 1: Create Command Classโ
// commands/new-command.ts
import { Command } from 'commander';
import { BaseCommand } from './base';
export class NewCommand extends BaseCommand {
constructor(program: Command) {
super(program);
program
.command('new-command')
.description('Description of new command')
.option('--option <value>', 'Option description')
.action(this.execute.bind(this));
}
async execute(options: any): Promise<void> {
// Command implementation
this.logger.info('New command executed');
}
}
Step 2: Register Commandโ
// index.ts
import { NewCommand } from './commands/new-command';
// Add to command registration
new NewCommand(program);
Step 3: Update TypeScript Configurationโ
Ensure the new command is included in the build.
๐งช Testingโ
Test Structureโ
packages/cli/
โโโ tests/
โโโ unit/
โ โโโ commands/
โ โ โโโ init.test.ts
โ โ โโโ sync.test.ts
โ โโโ services/
โ โโโ config-service.test.ts
โโโ integration/
โโโ cli-integration.test.ts
Running Testsโ
cd packages/cli
npm test
Mockingโ
Mock file system and n8n API for testing:
import mockFs from 'mock-fs';
import nock from 'nock';
beforeEach(() => {
mockFs({
'workflows': {},
'n8nac-config.json': JSON.stringify({ host: 'http://test.n8n' })
});
nock('http://test.n8n')
.get('/api/v1/workflows')
.reply(200, []);
});
afterEach(() => {
mockFs.restore();
nock.cleanAll();
});
๐ฆ Packaging and Distributionโ
Building for Productionโ
npm run build
Creating Executableโ
The CLI uses pkg or nexe for creating standalone executables:
{
"bin": {
"n8nac": "./dist/index.js"
}
}
Publishing to npmโ
npm version patch
npm publish
๐ Security Considerationsโ
API Key Managementโ
- Never Log: API keys are never logged
- Environment Variables: Preferred over config files
- Encryption: Optional encryption for stored keys
Input Validationโ
- Validate All Inputs: Host URLs, file paths, etc.
- Sanitize Outputs: Prevent injection attacks
- Rate Limiting: Prevent abuse of n8n API
๐ Performance Optimizationโ
Command Performanceโ
- Lazy Loading: Load Sync library only when needed
- Caching: Cache configuration and API responses
- Parallel Processing: Sync multiple workflows in parallel
Memory Managementโ
- Stream Processing: Process large workflows as streams
- Cleanup: Proper disposal of resources
- Monitoring: Track memory usage
๐ Troubleshootingโ
Common Issuesโ
Connection Failedโ
# Test connection manually
curl -H "X-N8N-API-KEY: your-key" https://your-n8n.com/api/v1/workflows
Configuration Not Foundโ
- Check current directory for
n8nac-config.json - Run
n8nac initto create config
Sync Conflictsโ
- Review conflict details in output
- Use
--forceto overwrite (with caution) - Manually resolve in n8n UI
Debug Modeโ
Enable verbose logging:
DEBUG=n8n-as-code:* n8nac list
Log Filesโ
Check the terminal output (and VS Code Output panel when using the extension) for detailed error information.
๐ Related Documentationโ
- Sync Engine: Sync engine internals (embedded in CLI)
- Architecture Overview: Overall system architecture
- VS Code Extension: VS Code extension development
- Contribution Guide: How to contribute
The n8nac package provides powerful command-line tools for n8n workflow management, enabling automation, scripting, and integration with other development tools. It also exposes n8nac skills โ a subcommand group bridging to the @n8n-as-code/skills library for AI agent tooling.