N8

n8n-code-to-native

Converts n8n JavaScript Code nodes into readable native workflow nodes.

Install

mkdir -p .claude/skills/n8n-code-to-native && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/16187" && unzip -o skill.zip -d .claude/skills/n8n-code-to-native && rm skill.zip

Installs to .claude/skills/n8n-code-to-native

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Convert n8n Code (JS) nodes into native declarative nodes (Set / Filter / Merge / Crypto / Aggregate / ConvertToFile) so the workflow is readable by n8n-experts who don't know JavaScript. Use when the user asks to "原生化", "改成 n8n 原生 node", "reduce Code nodes", or refactor an n8n workflow JSON to remove JS where possible.
321 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Advanced

Key capabilities

  • Identify n8n Code nodes in workflow JSONs.
  • Classify Code nodes based on their JavaScript patterns.
  • Convert Code nodes returning field assignments to Set nodes.
  • Convert Code nodes filtering items to Filter nodes.
  • Convert Code nodes writing files from strings to Set and Convert to File nodes.
  • Update the workflow's sticky note with a change-history line after conversion.

How it works

The skill inventories Code nodes in n8n workflow JSON, classifies their intent, and converts them into native n8n nodes like Set, Filter, or Merge, updating the workflow's change log.

Inputs & outputs

You give it
n8n workflow JSON containing Code nodes.
You get back
Refactored n8n workflow JSON with Code nodes replaced by native declarative nodes where possible.

When to use n8n-code-to-native

  • 原生化 (make n8n workflow native)
  • Refactor JS code nodes
  • Reduce JavaScript usage in n8n

About this skill

n8n Code → Native node refactor

The audience for these workflows is n8n experts who read the canvas but cannot read JavaScript. A Code node is opaque to them. Replacing it with declarative native nodes — even if the result has more nodes — is the right trade-off.

Hard rules

  1. Every conversion bumps the workflow's sticky note with a v<N> <date>: ... change-history line. The first sticky note in the file is the change log. Do not skip this — it is the audit trail.
  2. Never break in-place semantics without confirming with the user. If a single Code node becomes 1 native node → safe (swap-in-place, no connection edits). If it becomes 2+ nodes → confirm scope first (connections must be re-wired).
  3. Connections in n8n JSON are by node name. Keep the node name identical when swapping types in-place; connections will survive automatically.
  4. n8n expressions support array methods. .map, .reduce, .filter, .includes, regex .match, Math.max(...arr), ternaries, optional chaining ?., nullish ??, spread ... — all work inside ={{ ... }}. Use them. They are NOT "code" — they are expressions inside declarative nodes.
  5. Do NOT introduce IIFE (() => { ... })() in expressions. That is JS in disguise and defeats the purpose. If the logic needs IIFE, either (a) split into two sequential Set nodes so each step is one expression, or (b) keep it as a Code node.
  6. Keep what genuinely belongs in code. See "Keep as Code" below. Forcing every Code node into native makes things worse.

Process

Step 1 — Inventory

For each workflow JSON, list every n8n-nodes-base.code node with its name and JS body. Group by intent (callback builder, parser, aggregator, file builder, …). Useful Python:

import json, glob
for f in sorted(glob.glob("*.json")):
    d = json.load(open(f, encoding="utf-8"))
    codes = [n for n in d["nodes"] if n["type"] == "n8n-nodes-base.code"]
    for n in codes:
        print(f, "::", n["name"], "::", n["parameters"]["jsCode"][:120])

Step 2 — Classify each Code node

PatternAction
Returns one item with field assignments (constants + expressions)Set (swap-in-place)
Reduces array → scalar (sum/count/max/avg) for fieldsSet with .reduce/.map/Math.max expression
Filters items by criteriaFilter node (in-place)
Pairs items from two upstream nodes by indexMerge (mode: combine, combineBy: position) + Set (structural, 2 nodes)
Writes file from stringSet (build content) + Convert to File (structural, 2 nodes)
Parses LLM JSON with multi-shape fallback (try/catch over Ollama/OpenAI shapes, regex extract on parse failure)Keep as Code — fallback logic is too branchy for expressions
Pure-JS crypto polyfill (SHA-1, UUID v5)Crypto node (n8n native) for SHA-1; UUID v5 needs Crypto + Set + bit-twiddling expressions — feasible but separate effort. Default: keep
Dynamic nested object/filter assembly with conditional branches (e.g. Qdrant filter built from for-loops)Keep as Code

Step 3 — Convert in-place (Set node, typeVersion 3.4)

The Set v3.4 node shape used in these workflows:

{
  "name": "Build Callback",
  "type": "n8n-nodes-base.set",
  "typeVersion": 3.4,
  "parameters": {
    "assignments": {
      "assignments": [
        { "id": "a1", "name": "folder_path",  "value": "={{ $('Extract Payload').first().json.folder_path }}", "type": "string" },
        { "id": "a2", "name": "chunk_count",  "value": "={{ $input.all().reduce((s, x) => s + (x.json.chunk_count || 0), 0) }}", "type": "number" },
        { "id": "a3", "name": "results",      "value": "={{ $input.all().map(i => i.json).filter(r => r.file_name) }}", "type": "array" },
        { "id": "a4", "name": "status",       "value": "Step 03 進行中", "type": "string" }
      ]
    },
    "options": {}
  }
}
  • value starting with = is treated as an expression. Otherwise it is a literal.
  • type must match the expression's actual return: string, number, boolean, array, object.
  • For empty literal arrays/objects, use ={{ [] }} / ={{ {} }} (expression returning the value) with type: "array" / "object".
  • Newlines inside expression-built strings: use \\n in the JSON source (which encodes to \n in the actual string value).
  • Preserve every other field on the node (id, position, credentials, disabled, notes, webhookId, …) — only change type, typeVersion, and parameters. Conversions are surgical.

Step 4 — Update the sticky note (MANDATORY)

The first sticky note in the workflow is the change log. Append a line like:

--- v1.0.2 2026-05-30: Code -> Set (Build Callback x5 + Build Exclude Request + Build RAG Context, native expressions with .reduce/.map/.filter)

Format: v<file-internal-version> <YYYY-MM-DD>: <what changed in plain language>. Do not rename the workflow file (filename version stays — internal patch bump only). If the file has no sticky note, create one — that file was non-conformant.

Step 5 — Verify before committing

  • Re-read the node JSON: type is n8n-nodes-base.set, typeVersion is 3.4, parameters has assignments.assignments[].
  • Node count and connections unchanged for in-place swaps (count by n['type'] before/after; connections map is by name → still valid).
  • Manually import one converted workflow into n8n and run an execution if the user can spare the time; otherwise list the converted nodes in the commit message so the user can spot-check.

What to KEEP as Code (do not convert)

  1. LLM output parsers with multi-shape fallback. Example pattern:

    const raw = r.message?.content || r.choices?.[0]?.message?.content || r.response || '';
    let s = raw.trim().replace(/^```(?:json)?\s*/i, '').replace(/```\s*$/i, '').trim();
    let parsed; try { parsed = JSON.parse(s); } catch (e) { const m = s.match(/\[[\s\S]*\]/); ... }
    

    The branchy try/catch + regex-extract fallback is unreadable as a chain of native nodes.

  2. Pure-JS crypto polyfills. n8n sandbox blocks require('crypto'). SHA-1 and UUID v5 implementations are long but they belong in Code (or can be replaced by the native Crypto node — separate, deeper refactor).

  3. Dynamic nested object assembly. Building something like a Qdrant filter: { should: [...] } where the should array is built from a for-loop over field names × keywords is genuinely loop-shaped. Native node doesn't model this naturally.

  4. Per-item branching on shape detection. e.g. if Array.isArray(item.json) ... else if Array.isArray(item.json.data) ... else if (item.json.text) ... else continue. An IF node only branches the whole stream, not per-item.

n8n expression cheat sheet

  • Current item: {{ $json.x }} (NOT $.x)
  • All items from current input: {{ $input.all() }} → returns [{json,binary}, ...]
  • First item: {{ $input.first().json.x }}
  • Reference another node by name: {{ $('Node Name').first().json.x }} or {{ $('Node Name').all() }}
  • Array methods: {{ $input.all().map(i => i.json.x) }}, {{ ... .filter(x => x > 0) }}, {{ ... .reduce((s, x) => s + x.json.n, 0) }}
  • Conditionals: {{ x > 0 ? 'pos' : 'neg' }}, {{ x?.y ?? 0 }}
  • Math: {{ Math.max(...arr) }}, {{ Math.round(n) }}
  • String building: {{ 'Got ' + n + ' items' }} or backticks via {{ \Got ${n} items` }}` (works in expressions)

Common pitfalls

  • includeOtherFields semantics: by default Set v3.4 returns ONLY the assigned fields. To preserve input fields and add new ones, set parameters.includeOtherFields: true at the parameter level (NOT inside options). Verify in the n8n UI after import.
  • $('NodeName').first() errors if the referenced node hasn't run on this execution path. Wrap with ?.: {{ $('X')?.first()?.json?.y ?? 0 }}. If the original Code wrapped this in try/catch, that's a signal the node may be optional — preserve safety.
  • Sticky note encoding: workflow JSONs are UTF-8. When editing via Python, open with encoding='utf-8' and dump with ensure_ascii=False to keep Chinese readable in the JSON.
  • Don't rename nodes. Connections key by node name. Renaming requires also updating d['connections']. Not worth it.
  • Math.max(...[]) returns -Infinity. Guard with (arr.length ? Math.max(...arr) : 0).

When user asks "原生化" — recommended interaction

  1. Inventory all Code nodes; classify by the table above.
  2. Report counts: how many fall in each category (in-place Set / structural / keep).
  3. Recommend doing in-place swaps first as Phase 1 (safe, no connection edits, fast).
  4. For structural (Phase 2) and complex (Phase 3), get explicit go-ahead per node — they involve adding nodes or non-trivial expression chains.
  5. After each phase: commit with a clear message listing what converted, what stayed and why; push.

When not to use it

  • When the logic needs IIFE (Immediately Invoked Function Expression) in expressions.
  • When the logic involves complex fallback logic for LLM JSON parsing.
  • When the logic involves dynamic nested object/filter assembly with conditional branches.

Limitations

  • It never breaks in-place semantics without user confirmation.
  • It does not introduce IIFE in expressions.
  • It keeps what genuinely belongs in code, such as complex fallback logic.

How it compares

This skill refactors n8n workflows to use native nodes instead of JavaScript Code nodes, making them more readable for non-developers.

Compared to similar skills

n8n-code-to-native side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
n8n-code-to-native (this skill)02moNo flagsAdvanced
telegram-bot-builder1066moReviewIntermediate
mcp-integration219moReviewIntermediate
n8n-workflow-patterns162moNo flagsAdvanced

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

telegram-bot-builder

davila7

Expert in building Telegram bots that solve real problems - from simple automation to complex AI-powered bots. Covers bot architecture, the Telegram Bot API, user experience, monetization strategies, and scaling bots to thousands of users. Use when: telegram bot, bot api, telegram automation, chat bot telegram, tg bot.

106130

mcp-integration

anthropics

This skill should be used when the user asks to "add MCP server", "integrate MCP", "configure MCP in plugin", "use .mcp.json", "set up Model Context Protocol", "connect external service", mentions "${CLAUDE_PLUGIN_ROOT} with MCP", or discusses MCP server types (SSE, stdio, HTTP, WebSocket). Provides comprehensive guidance for integrating Model Context Protocol servers into Claude Code plugins for external tool and service integration.

21123

n8n-workflow-patterns

czlonkowski

Proven workflow architectural patterns from real n8n workflows. Use when building new workflows, designing workflow structure, choosing workflow patterns, planning workflow architecture, or asking about webhook processing, HTTP API integration, database operations, AI agent workflows, or scheduled tasks.

16115

n8n-code-javascript

czlonkowski

Write JavaScript code in n8n Code nodes. Use when writing JavaScript in n8n, using $input/$json/$node syntax, making HTTP requests with $helpers, working with dates using DateTime, troubleshooting Code node errors, or choosing between Code node modes.

7122

n8n-expression-syntax

czlonkowski

Validate n8n expression syntax and fix common errors. Use when writing n8n expressions, using {{}} syntax, accessing $json/$node variables, troubleshooting expression errors, or working with webhook data in workflows.

6111

n8n-node-configuration

czlonkowski

Operation-aware node configuration guidance. Use when configuring nodes, understanding property dependencies, determining required fields, choosing between get_node_essentials and get_node_info, or learning common configuration patterns by node type.

7108

Search skills

Search the agent skills registry