| name | n8n-n8nac |
| description | Code-first n8n workflow development with n8nac (n8n-as-code). Workspace bootstrap, GitOps sync protocol, TypeScript decorator syntax, error classification, research protocol, and common mistakes. USE WHEN n8nac, n8n-as-code, code-first workflow, workflow.ts, n8nac init, n8nac push, n8nac pull, n8nac verify, n8nac test, n8nac list, workflow as code, TypeScript workflow, decorator workflow, GitOps n8n, push workflow, pull workflow, verify workflow, test workflow, Class A error, Class B error, n8nac bootstrap, n8nac setup, workflow sync. |
n8nac — Code-First n8n Workflow Development
n8nac (@n8n-as-code/cli) manages n8n workflows as clean, version-controlled TypeScript files using decorators. This skill covers the universal protocol — project-specific config is generated by n8nac update-ai.
Based on n8nac v1.6.x protocol. Run npx --yes n8nac update-ai in your project for the latest project-specific AGENTS.md.
Drift check: This skill captures the stable universal protocol. If n8nac has been updated since v1.6.x, run npx --yes n8nac update-ai and compare the generated AGENTS.md against this skill. If the protocol changed (new commands, renamed flags, new error classes), update this skill to match.
Workspace Bootstrap (MANDATORY)
Before ANY n8nac command, the workspace must be initialized.
Check
- Look for
n8nac-config.json at workspace root
- If missing or incomplete (no
projectId/projectName): not initialized
Initialize (2-step non-interactive)
npx --yes n8nac init-auth --host <url> --api-key <key>
npx --yes n8nac init-project --project-index 1 --sync-folder workflows
1-command alternative (when project is known)
npx --yes n8nac init --yes --host <url> --api-key <key> --project-index 1 --sync-folder workflows
Environment variables
If N8N_HOST and N8N_API_KEY are set in the shell, use them:
npx --yes n8nac init-auth --host "$N8N_HOST" --api-key "$N8N_API_KEY"
Instance management
npx --yes n8nac instance list --json
npx --yes n8nac instance select --instance-name <name>
npx --yes n8nac instance delete --instance-name <name> --yes
Rules:
- Never tell the user to run init — the agent runs it
- Never write
n8nac-config.json by hand
- Never run list/pull/push before init completes
- Don't assume init happened just because workflow files exist
GitOps Sync Protocol (CRITICAL)
n8nac uses a Git-like sync architecture. Local code is source of truth, but the user might have edited in n8n UI.
The 7-Step Workflow
1. LIST — Check status
npx --yes n8nac list
npx --yes n8nac list --local
npx --yes n8nac list --remote
2. PULL — Download remote changes before editing
npx --yes n8nac pull <workflowId>
Required if remote has newer changes. Skip = OCC rejection on push.
3. EDIT/CREATE — Work on local .workflow.ts
- Existing: edit the pulled file
- New: create in the
workflowDir from n8nac-config.json (the active instance's canonical path)
- Confirm with
npx --yes n8nac list --local before pushing
4. PUSH — Upload to n8n
npx --yes n8nac push <path>
npx --yes n8nac push <path> --verify
Path rules:
- Always use full path including
.workflow.ts suffix
- Use absolute or workspace-root-relative path (e.g.,
workflows/instance/project/my-workflow.workflow.ts)
- Never bare filename, never omit extension, never use workflow title
5. VERIFY — Validate live workflow
npx --yes n8nac verify <workflowId>
Catches: invalid typeVersion, bad operation values, missing required params, unknown node types.
6. TEST-PLAN — Check testability
npx --yes n8nac test-plan <workflowId>
npx --yes n8nac test-plan <workflowId> --json
7. TEST — Execute webhook/chat/form workflows
npx --yes n8nac workflow activate <workflowId>
npx --yes n8nac test <workflowId> --prod
npx --yes n8nac test <workflowId> --prod --data '{"key":"value"}'
Default rule: ALWAYS activate first, ALWAYS use --prod. Bare test <id> requires manual arm in n8n editor.
8. RESOLVE — Handle conflicts
npx --yes n8nac resolve <id> --mode keep-current
npx --yes n8nac resolve <id> --mode keep-incoming
Error Classification
n8nac test classifies failures into three buckets:
| Class | Exit Code | Action |
|---|
| Class A — Config gap | 0 | Missing credentials/model/env var. Inform user, do NOT re-edit code |
| Runtime state | 0 | Webhook not armed, production webhook not registered. Fix state, NOT code |
| Class B — Wiring error | 1 | Bad expression, wrong field. Fix .workflow.ts, push, re-test |
Critical: A Class A error is NOT a bug. Never push/edit to fix missing credentials.
Research Protocol (MANDATORY before creating/editing nodes)
Step 0: Pattern Discovery
npx --yes n8nac skills examples search "telegram chatbot"
Step 1: Search for the node
npx --yes n8nac skills search "google sheets"
Step 2: Get exact schema
npx --yes n8nac skills node-info googleSheets
npx --yes n8nac skills node-schema googleSheets
Step 3: Apply schema as absolute truth
- Use EXACT
type from schema (with full package prefix)
- Use HIGHEST
typeVersion from schema
- Use exact parameter names
Step 4: Validate before push
npx --yes n8nac skills validate workflow.workflow.ts
Step 5: Verify after push
npx --yes n8nac verify <workflowId>
TypeScript Decorator Syntax
Minimal workflow structure
import { workflow, node, links } from '@n8n-as-code/transformer';
@workflow({ name: 'Workflow Name', active: false })
export class MyWorkflow {
@node({
name: 'Descriptive Name',
type: '/* EXACT from search */',
version: 4,
position: [250, 300]
})
MyNode = { };
@links()
defineRouting() {
this.MyNode.out(0).to(this.NextNode.in(0));
}
}
AI Agent pattern (LangChain nodes)
@workflow({ name: 'AI Agent', active: false })
export class AIAgentWorkflow {
@node({ name: 'Chat Trigger', type: '@n8n/n8n-nodes-langchain.chatTrigger', version: 1.4 })
ChatTrigger = {};
@node({ name: 'AI Agent', type: '@n8n/n8n-nodes-langchain.agent', version: 3.1 })
AiAgent = {
promptType: 'define',
text: '={{ $json.chatInput }}',
hasOutputParser: true,
options: { systemMessage: 'You are a helpful assistant.' },
};
@node({ name: 'Model', type: '@n8n/n8n-nodes-langchain.lmChatOpenAi', version: 1.3,
credentials: { openAiApi: { id: 'xxx', name: 'OpenAI' } } })
Model = { model: { mode: 'list', value: 'gpt-4o-mini' }, options: {} };
()
() {
..().(..());
..({
: ..,
: [..],
});
}
}
Key rule: Regular nodes: .out(0).to(target.in(0)). AI sub-nodes (models, memory, tools, parsers): .uses() only.
Workflow Map Navigation
Every .workflow.ts starts with a <workflow-map> comment block — a compact index. Read this FIRST, then search for the specific property name you need. Never load the entire file into context.
13 Common Mistakes
- Wrong node type — missing package prefix (
switch vs n8n-nodes-base.switch)
- Outdated typeVersion — always use highest from schema
- Non-existent typeVersion — verify against exact array in node-schema
- Invalid operation value — check exact string in options[].value list
- Mismatched resource + operation — each resource has different valid operations
- Guessing parameter structure — always check schema for nested objects
- Wrong connection names — must match exact node
name field
- Inventing non-existent nodes — use
search to verify
- Wrong
.uses() syntax — ai_tool/ai_document are ALWAYS arrays; all others single refs
- Connecting AI sub-nodes with
.out().to() — use .uses() for anything flagged [ai_*]
- Guessing fixedCollection values — always run
node-info first
- Inverting value1/value2 in Switch/If — value1 = expression, value2 = literal
- Wrong formFields structure for Wait — use
{ values: [...] }, not formFieldsUi.fieldItems
Additional Tools
npx --yes n8nac execution list --workflow-id <id> --limit 5 --json
npx --yes n8nac execution get <execId> --include-data --json
npx --yes n8nac workflow credential-required <id> --json
npx --yes n8nac credential schema <type>
npx --yes n8nac credential list --json
npx --yes n8nac credential create --type <type> --name <name> --file cred.json --json
npx --yes n8nac workflow activate <id>
npx --yes n8nac workflow deactivate <id>
npx --yes n8nac skills docs "OpenAI"
npx --yes n8nac skills guides "webhook"
When in doubt: npx --yes n8nac skills node-info <nodeName> — the schema is always the source of truth.