Skip to main content

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 / --remote filters for focused views

6. Update AI Command (commands/init-ai.ts)โ€‹

Regenerates AI context files for the project.

Key Responsibilities:

  • Generate AGENTS.md with n8n-specific AI agent instructions
  • Generate .vscode/n8n.code-snippets from the n8n node index
  • Optionally connect to n8n to embed the running instance version
note

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โ€‹

  1. Start a local n8n instance
  2. Get API key from n8n settings
  3. 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โ€‹

  1. Check current directory for n8nac-config.json
  2. Run n8nac init to create config

Sync Conflictsโ€‹

  1. Review conflict details in output
  2. Use --force to overwrite (with caution)
  3. 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.


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.