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 (@n8n-as-code/cli) 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
- Watch Mode: Real-time synchronization on file changes
- AI Assistance: AI-powered workflow generation and assistance
๐๏ธ Architectureโ
Package Structureโ
packages/cli/
โโโ src/
โ โโโ index.ts # CLI entry point
โ โโโ commands/
โ โ โโโ base.ts # Base command class
โ โ โโโ init.ts # Init command
โ โ โโโ init-ai.ts # AI-assisted init
โ โ โโโ sync.ts # Sync command
โ โ โโโ watch.ts # Watch command
โ โโโ 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[InitAICommand]
B --> E[SyncCommand]
B --> F[WatchCommand]
C --> G[Core Library]
D --> H[AI Services]
E --> G
F --> G
style A fill:#ff6b35
style B fill:#3498db
style C fill:#2ecc71
style D fill:#9b59b6
style E fill:#e74c3c
๐งฉ Core 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, WatchCommand, 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 WatchCommand(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. Watch Command (commands/watch.ts)โ
Watches for file changes and automatically syncs.
Key Responsibilities:
- Monitor workflow directory for changes
- Trigger sync on file modifications
- Debounce events to prevent excessive syncing
- Provide real-time status updates
Watch Implementation:
class WatchCommand extends BaseCommand {
private watcher: chokidar.FSWatcher;
async execute(options: any): Promise<void> {
this.watcher = chokidar.watch('workflows/**/*.json', {
ignored: /(^|[\/\\])\../, // ignore dotfiles
persistent: true
});
this.watcher
.on('change', this.handleChange.bind(this))
.on('add', this.handleAdd.bind(this))
.on('unlink', this.handleDelete.bind(this));
}
}
6. Init AI Command (commands/init-ai.ts)โ
AI-assisted project initialization.
Key Responsibilities:
- Generate configuration using AI
- Suggest workflow templates
- Provide intelligent defaults
- Learn from user preferences
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:
- File:
n8n-as-code.jsonorn8n-as-code.config.js - Environment Variables:
N8N_HOST,N8N_API_KEY, etc. - Command Line: CLI arguments
- Defaults: Built-in default values
๐ Integration with Core Libraryโ
Core Library Usageโ
The CLI uses the Core library for all n8n operations:
import { SyncManager, StateManager, N8nApiClient } from '@n8n-as-code/core';
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 Core 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
n8n-as-code --help
Testing with Local n8nโ
- Start a local n8n instance
- Get API key from n8n settings
- Configure CLI:
n8n-as-code init --host http://localhost:5678 --api-key your-key
๐ง 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': {},
'n8n-as-code.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": {
"n8n-as-code": "./bin/n8n-as-code.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 Core 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
n8n-as-code.json - Verify environment variables are set
- Run
n8n-as-code 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:
n8n-as-code sync --verbose
Log Filesโ
Check log files in ~/.n8n-as-code/logs/ for detailed error information.
๐ Related Documentationโ
- Core Package: Core library details
- Architecture Overview: Overall system architecture
- VS Code Extension: VS Code extension development
- Contribution Guide: How to contribute
The CLI package provides powerful command-line tools for n8n workflow management, enabling automation, scripting, and integration with other development tools.