n8n código como archivos TypeScript con n8n-decanter
En pocas palabras: n8n-decanter, la herramienta open source con licencia MIT de Malte Buttjer, guarda cada Code node de n8n como archivo TypeScript en git, compila los módulos compartidos y las dependencias NPM con esbuild en cada push, y usa un proxy MCP para que los agentes de IA no editen el código.
Malte Buttjer publicó n8n-decanter en agosto de 2026, una herramienta open source con licencia MIT que guarda el código de n8n como archivos TypeScript en git: los módulos compartidos y las dependencias NPM se empaquetan solas en cada push, y los agentes de IA editan la estructura del workflow sin tocar el código.
n8n-decanter es una herramienta CLI gratuita que creó el desarrollador Malte Buttjer para versionar el código de los Code nodes de n8n en un repositorio git. Trabaja en dos frentes: un proxy MCP bloquea la escritura directa del campo de código desde agentes de IA, y un comando push compila los archivos TypeScript con esbuild para enviarlos a n8n como funciones autocontenidas.
En 30 segundos
- Código fuera del JSON: cada Code node pasa a ser un archivo TypeScript en git, con un puntero
@file:dentro del workflow. - Proxy selectivo: el guard rechaza una sola escritura, la del campo de código; crear nodos, conectar ramas y renombrar siguen habilitados para el agente.
- Compilación en el push: esbuild transforma TypeScript a JavaScript e incluye las dependencias NPM que optaste usar; cada nodo llega como función autocontenida.
- Borrador primero: los cambios caen en un draft y producción sigue corriendo la versión publicada hasta que hagas publish de forma consciente.
- Setup corto: unos cinco minutos sobre una instancia existente, cloud o self-hosted, según el anuncio de Buttjer.
¿Qué es n8n-decanter y cómo resuelve el versionado del código?
n8n-decanter parte de un problema concreto: en n8n, el código de un Code node es un string dentro de un objeto, dentro del documento JSON del workflow. La herramienta separa dos mundos que ahí conviven mal: la estructura del workflow sigue siendo cosa de n8n, y el código pasa a vivir en git, donde existen diffs, tipos, blame y pull requests.
Ponele que le pedís al agente que consolide dos feeds de marketplace escritos cada uno como un Code node gigante, con cientos de líneas de lógica de Shopify repetida. El agente cumple. ¿Y qué muestra el diff? Dos strings cambiados.
Ni un carácter más visible. Eso duele.
Eso le pasó a Buttjer con los feeds de Amazon y eBay de su negocio de tarjetas, y lo cuenta en su post: el agente reescribió unos cientos de líneas y el resultado quedó indistinguible de mover un nodo veinte píxeles. Su diagnóstico, en traducción adaptada: «El problema nunca fue que los agentes escriban mal código, es que escriben código, y rápido».
- Diffs ilegibles: un cambio de 40 líneas de lógica marca lo mismo que un ajuste cosmético.
- Cero tipos: nada te avisa que
$input.first().json.customerIddejó de coincidir con el helper que pegaste en cuatro nodos. - Sin reutilización: la lógica común se duplica nodo por nodo porque un módulo compartido no tiene dónde vivir.
- Revisión invisible: el cambio no se ve hasta que corre.
Las dos salidas obvias no zafan. Quitarle el MCP al agente descarta justo lo que funcionaba: agregar nodos, reconectar ramas o cablear el error path es tedioso a mano y el motor lo valida solo. Y espejar el JSON completo en git, la receta “n8n as code” de siempre, te regala un histórico lleno de ruido (posiciones de nodos, version ids, referencias de credenciales) y un push que pisa lo que se movió del otro lado. Sobre eso hablamos en sintaxis de las expresiones dentro de los nodos.
La observación de la que sale todo: estructura y código quieren dueños distintos. Guardar una función como string es una decisión correcta para un motor de workflows; el error fue dejar que ese string sea el único lugar donde vive el código.
¿Cómo guardar el código de n8n como archivos TypeScript en git?
Con una carpeta por workflow y un archivo por Code node. Cuando hacés pull, decanter vuelca cada nodo a su propio archivo y deja en el JSON un puntero en lugar del código inline, así la estructura diffea limpia y el código vive donde corresponde.
Así se ve un workflow convertido, con el ejemplo real del anuncio:
workflow.json: espejo de solo lectura de la estructura (nunca es la fuente de verdad)..decanter.json: mapa de node id a archivo, con hashes de sincronización por nodo.code-in-java-script4.js: el archivo de un nodo que nadie renombró (sí, ese nombre sale así).compat.ts: helpers importados por varios nodos, empaquetados en el push.types/shopify.d.ts: un solo set de tipos de Shopify para todos los nodos.
Donde antes había un string con toda la función, ahora hay algo como "//@file:code/amazon-feed.ts". Si el agente crea un Code node nuevo vía MCP, llega vacío y el primer push lo siembra. Simple.
¿Se puede usar TypeScript de verdad en los Code nodes de n8n?
Sí, con tipos reales en tu editor, aunque el camino tiene un detalle técnico: el código de un Code node no es un módulo, es el cuerpo de una función. Si lo typecheckeás tal cual está en disco, TypeScript lo rechaza con un TS1108, un return fuera de cuerpo de función.
Los archivos además tienen que quedar byte a byte idénticos a lo que n8n ejecuta, así que “arreglarlos” no es opción. La jugada de decanter: el typechecker envuelve cada archivo en un wrapper en memoria y mapea los diagnósticos de vuelta al original. En disco, el archivo intacto; en tu editor, autocompletado sobre $input y errores antes de pushear. Ya lo cubrimos antes en conectar tus flujos con Airtable.
Eso sí: TypeScript es one-way. n8n guarda el JavaScript compilado, así que el editor web te muestra el output, no la fuente (para leer código humano, volvé a tu repo).
¿Cómo funciona el push y qué pasa antes de llegar a producción?
El push compila cada archivo con esbuild, incluye los helpers y las dependencias NPM que hayas optado por usar, y le entrega a n8n cada nodo como una única función autocontenida. Nada de eso toca producción: los cambios aterrizan en el borrador del workflow.
Subís los archivos, esbuild los compila, el chequeo de cumplimiento valida la estructura, el control de drift compara hashes, todo cae en el borrador, vos leés el diff con calma, publicás cuando querés y producción ni se entera hasta ese momento.
Dos filtros independientes escoltan cada push:
- Chequeo de cumplimiento: las violaciones estructurales son errores duros, por ejemplo una llamada
$()que nombra un nodo que no existe. No tiene bypass: si fuera puenteable, lo puentearían. - Detección de drift: si el código remoto se movió del hash registrado en la última sincronización, el push aborta en vez de pisar a alguien. Este sí tiene bypass, porque “ya sé, hacelo igual” es una decisión legítima a veces.
Publicar es un acto aparte y deliberado: un agente que entendió mal la tarea genera un borrador equivocado y lo leés con calma antes de que llegue a tus clientes. Y going live vuelve a correr el chequeo de correctitud aunque el agente se lo saltee, fallando cerrado: si el borrador no se puede leer, no sale nada, y el error dice qué filtro murió. ¿Y mientras tanto producción? Corriendo la versión vieja, tranquila.
¿Qué escrituras bloquea el proxy de n8n-decanter?
Exactamente una: la escritura del campo de código de un Code node. Todo lo demás pasa. Tema relacionado: dominar el nodo HTTP Request.
El proxy se interpone entre el agente y n8n como un servidor MCP propio, reenvía toda la superficie de herramientas (crear, leer, actualizar, renombrar, conectar, publicar) e inspecciona los payloads antes de mandarlos. Cuando el agente intenta reescribir el código de un feed, la escritura vuelve rechazada con una dirección: el archivo que tiene que editar en el repo. Las ediciones estructurales siguen fluyendo por la API validada del motor, que es donde un agente rinde mejor.
¿Cómo se compara con las otras formas de versionar n8n?
Si venís de las dos recetas habituales, la diferencia se ve en frío:
| Criterio | Código inline (string en JSON) | Espejo completo del JSON | n8n-decanter |
|---|---|---|---|
| Diffs | Un string cambiado | Ruido: posiciones, version ids, credenciales | Un archivo por nodo |
| Tipos | Ninguno | Ninguno | TypeScript real en el editor |
| Lógica compartida | Copy-paste | Copy-paste | Módulos y tipos importados |
| Revisión | Invisible hasta ejecutar | Posible pero ruidosa | Pull request |
| Agente IA | Todo o nada | Todo o nada | Estructura sí, código no |

¿Qué ventajas tiene compartir módulos y tipos entre nodos?
Menos copy-paste y un solo lugar donde cambiar la lógica común. El caso original lo grafica: dos feeds, Amazon y eBay, cada uno recorriendo la GraphQL de Shopify a su manera; con decanter, los dos importan compat.ts y comparten types/shopify.d.ts.
Ojo con un matiz: cada nodo recibe su copia bundleada, porque n8n exige funciones autocontenidas. No hay sharing en runtime; lo que ganás es una única fuente para editar y revisar. Tocás el tipo en un lugar y el typechecker te marca todos los nodos que quedaron desalineados. Eso, para mí, es el golazo silencioso de todo el proyecto.
¿Cómo instalar y usar n8n-decanter en mi instancia?
Es un CLI con licencia MIT publicado en npm, y el setup toma unos cinco minutos contra una instancia existente, según documenta Buttjer. No requiere plugin ni fork: alcanza con cualquier n8n lo bastante nuevo como para incluir el servidor MCP integrado, sea cloud o self-hosted.
- Un proceso junto a tu repo: nada hosted en el medio, las credenciales quedan en tu máquina.
- Borrable sin drama: eliminás decanter mañana y tus workflows siguen corriendo; es un marco alrededor de un campo.
- Listo para agentes: la guía cubre el cableado del guard en Claude Code o cualquier cliente MCP.
- Self-hosted bienvenido: si corrés n8n self-hosted, decanter se conecta igual que en cloud.
El código está en GitHub si querés husmear antes de instalar.
Errores comunes al usar n8n-decanter
Decanter está en pre-1.0 y el modelo de datos puede moverse en versiones menores, así que tomalo con pinzas antes de meterlo en el camino crítico. Dicho esto, estos son los tropiezos que veo más probables:
- Tratar el guard como seguridad. Frena a un agente que coopera pasando por decanter; uno con tus credenciales crudas de n8n escribe lo que quiera. Contener a un agente hostil es otro problema.
- Pushear sin mirar tras un pull conflictivo. El pull rebaselinea incluso en conflicto y el próximo push sobrescribe el cambio remoto. Es diseño (los archivos son la fuente de verdad), pero te va a sorprender una vez.
- Esperarle poderes de deployment. No promueve workflows entre ambientes ni gestiona credenciales; para eso n8n tiene sus propias respuestas.
- Usarlo donde no hace falta. Workflows de puras integraciones con Code nodes de una línea no necesitan repo.
- Editar en el navegador mientras otro pushea. n8n toma un lock de escritor único y tu push falla hasta que el lock se libere. Comportamiento correcto, a veces molesto.
Preguntas Frecuentes
¿Qué es n8n-decanter y para qué sirve?
n8n-decanter es una herramienta CLI open source de Malte Buttjer que guarda el código de los Code nodes de n8n como archivos TypeScript en git. Sirve para tener diffs legibles, tipos, revisión en pull requests y módulos compartidos, manteniendo a los agentes IA lejos de la escritura directa del código. Más contexto en enviar alertas automáticas a Slack.
¿Cómo puedo guardar mis Code nodes de n8n en git?
Instalás el CLI desde npm, lo apuntás a tu instancia y hacés un pull inicial: decanter crea una carpeta por workflow con un archivo por Code node y un puntero @file: dentro del JSON. Desde ahí editás los archivos y enviás cambios con push.
¿Se puede usar TypeScript en los Code nodes de n8n?
Sí. Como el código de un Code node es el cuerpo de una función y no un módulo, decanter lo envuelve en un wrapper en memoria para typecheckear y mapea los errores al archivo original. En el push, esbuild lo compila y lo entrega como JavaScript autocontenido.
¿Cómo comparto módulos entre diferentes Code nodes?
Creás un archivo helper (por ejemplo compat.ts) y lo importás desde los nodos que lo necesiten; los tipos se centralizan en archivos .d.ts. En cada push, decanter empaqueta las importaciones dentro de cada nodo, que llega a n8n como función autocontenida.
¿Cuánto cuesta n8n-decanter?
Nada: es software libre con licencia MIT, descargable desde npm. Lo único que pagás es la instancia de n8n que ya tengas, sea la edición self-hosted o un plan cloud del propio n8n; decanter no agrega servicios ni costos intermedios.
Conclusión
Lo que cambió es fácil de enunciar: el código de tus automatizaciones puede vivir en git sin dejar de ejecutarse en n8n. Para equipos con Code nodes que dejaron de ser one-liners y agentes IA metidos en el flujo diario, decanter propone un reparto claro: estructura para el motor, código para el repo, revisión para personas.
Mi sugerencia: probalo en un workflow secundario, mirá los filtros en acción y recién ahí decidís si entra a tu repo principal. Que esté en pre-1.0 no lo hace menos interesante; lo hace joven.






