Help us improve
Share bugs, ideas, or general feedback.
From n8n-autopilot
Writes JavaScript code in n8n Code nodes, covering $input/$json/$node syntax, HTTP requests with $helpers, DateTime (Luxon), mode selection, and troubleshooting. Also advises when to use native nodes instead.
npx claudepluginhub neurawork-git/n8n-autopilot --plugin n8n-autopilotHow this skill is triggered — by the user, by Claude, or both
Slash command
/n8n-autopilot:n8n-code-javascriptThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Expert guidance for writing JavaScript code in n8n Code nodes.
Writes JavaScript for n8n Code nodes using $input/$json/$node syntax, $helpers for HTTP requests, DateTime for dates; guides 'Run Once for All Items' vs 'Each Item' modes and error troubleshooting.
Writes JavaScript for n8n Code nodes using $input/$json/$node syntax, $helpers HTTP requests, DateTime handling, mode selection between All Items and Each Item, and error troubleshooting.
Writes JavaScript for n8n Code nodes using $input/$json/$node, $helpers.httpRequest, DateTime; covers modes, error troubleshooting, data aggregation, filtering, API calls, batch processing.
Share bugs, ideas, or general feedback.
Expert guidance for writing JavaScript code in n8n Code nodes.
// Basic template for Code nodes
const items = $input.all();
// Process data
const processed = items.map(item => ({
json: {
...item.json,
processed: true,
timestamp: new Date().toISOString()
}
}));
return processed;
$input.all(), $input.first(), or $input.item[{json: {...}}] format$json.body (not $json directly)Reach for a native node before writing JavaScript — Code nodes are harder to read, review, and they run V8 in-process (OOM risk on large data, see below). In a real production audit, Code nodes outnumbered native conditional nodes ~2.5:1 — much of it avoidable:
| If you are doing… | Use this native node, NOT Code |
|---|---|
| Branching on a condition | IF (2 branches) / Switch (n branches) |
| Dropping items by a rule | Filter |
| Setting / renaming / mapping fields | Set (Edit Fields) |
| Merging / combining streams | Merge |
| Aggregating into one item | Aggregate / Summarize |
| Looping over large batches | Loop Over Items (SplitInBatches) |
Memory / OOM (real production incident): a Code node that loads or iterates a large dataset — especially a full DB result set (>~10k rows), binary, or file contents — can spike the V8 heap (~3 GB cap) and crash the n8n pod (OOM). For large data: page/limit at the source, process in
SplitInBatches, or push the work into the database/native node instead of materializing it all in JS.
Use a Code node when the logic genuinely has no native equivalent (custom parsing, multi-field computation, shaping a bespoke payload).
Use for: aggregation, batch processing, transformations that have no native-node equivalent
const allItems = $input.all();
const total = allItems.reduce((sum, item) => sum + (item.json.amount || 0), 0);
return [{
json: { total, count: allItems.length, average: total / allItems.length }
}];
Use for: Specialized cases — per-item validation, independent operations
const item = $input.item;
return [{
json: { ...item.json, processed: true, processedAt: new Date().toISOString() }
}];
Decision: Need to compare multiple items? → All Items. Each item independent? → Each Item. Not sure? → All Items.
// Most common: all items
const allItems = $input.all();
// Single result
const firstItem = $input.first();
const data = firstItem.json;
// Reference other nodes
const webhookData = $node["Webhook"].json;
const httpData = $node["HTTP Request"].json;
Webhook data is nested under .body:
// ❌ WRONG
const name = $json.name;
// ✅ CORRECT
const name = $json.body.name;
const webhookData = $input.first().json.body;
// ✅ Single result
return [{ json: { field1: value1 } }];
// ✅ Multiple results
return items.map(item => ({ json: { id: item.json.id, processed: true } }));
// ✅ Empty result
return [];
WRONG: return {json: {...}} (no array), return [{field: value}] (no json key)
const response = await $helpers.httpRequest({
method: 'GET',
url: 'https://api.example.com/data',
headers: { 'Authorization': 'Bearer token' }
});
return [{ json: { data: response } }];
const now = DateTime.now();
const formatted = now.toFormat('yyyy-MM-dd');
const tomorrow = now.plus({ days: 1 });
const adults = $jmespath(data, 'users[?age >= `18`]');
const names = $jmespath(data, 'users[*].name');
const items = $input.all();
const total = items.reduce((sum, item) => sum + (item.json.amount || 0), 0);
return [{ json: { total, count: items.length, average: total / items.length } }];
return $input.all()
.filter(item => item.json.status === 'active')
.map(item => ({ json: { id: item.json.id, name: item.json.name } }));
try {
const response = await $helpers.httpRequest({ url: 'https://api.example.com/data' });
return [{ json: { success: true, data: response } }];
} catch (error) {
return [{ json: { success: false, error: error.message } }];
}
return items.map(item => ({json: item.json}));{{ }} in Code node → Use $json.field directly (no braces)[{json: {...}}], not {json: {...}}item.json?.user?.email || 'fallback'$json.email ❌ → $json.body.email ✅if (!items || items.length === 0) return [];map/filter over manual loopsconsole.log()✅ Complex transformations, custom calculations, API response parsing, multi-step conditionals, data aggregation
❌ Simple field mapping → Set node | Basic filtering → Filter node | HTTP requests → HTTP Request node