RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Diff/n8n-io-n8n-agents ↔ n8n-io-n8n-packages-cli-agents

Comparison

A · AGENTS.md · n8n-io/n8nB · AGENTS.md · n8n-io/n8n
What each file covers, counted
DimensionSharedOnly in AOnly in BOverlap
Sections12524%
Commands12214%
Section tags11108%

What each file covers

Sections

1 shared · 25 only in A · 2 only in B
  • − Project Overview
  • − General Guidelines
  • − Agent Skills and Claude Code Plugin
  • − Essential Commands
  • − Fresh checkout / agent setup
  • − Building
  • − Testing
  • − Code Quality
  • − Architecture Overview
  • − Package Structure
  • − Technology Stack
  • − Key Architectural Patterns
  • − Key Development Patterns
  • − Workflow Traversal Utilities
  • − TypeScript Best Practices
  • − Error Handling
  • − Persistence layer & the TypeORM boundary
  • − Frontend Development
  • − Testing Guidelines
  • − Common Development Tasks
  • − Design Principles
  • − Security Must Not Degrade the Building Experience
  • − Security Fix Hygiene
  • − Customer Confidentiality
  • − Github Guidelines
  • + TypeORM boundary
  • + Transactions
  •   AGENTS.md

Commands

1 shared · 22 only in A · 1 only in B
  • − pnpm agent:setup
  • − pnpm agent:setup install
  • − pnpm agent:setup --json
  • − pnpm build > build.log 2>&1
  • − pnpm --filter @n8n/telemetry catalog
  • − pnpm build
  • − pnpm reset
  • − pnpm reset --full
  • − pnpm test
  • − pnpm test:affected
  • − pnpm test <test-file>
  • − pnpm lint
  • − pnpm typecheck
  • − node-dev
  • − pnpm dev:ai
  • − vitest
  • − pnpm --filter=n8n-playwright test:local
  • − pnpm dev
  • − pnpm --filter n8n-containers services --services postgres,redis,mailpit,proxy
  • − node-1234-improve-request-handling
  • − node-1234-fix-ddos-vulnerability
  • − gh pr create --draft
  • + eslint.config.mjs
  •   eslint-disable

Section tags

1 shared · 11 only in A · 0 only in B
  • − setup
  • − build
  • − test
  • − code-style
  • − architecture
  • − types
  • − testing-strategy
  • − git-pr
  • − security
  • − do-not
  • − agent-behaviour
  •   lint-format

Line diff

+49 added−318 removed16 unchanged4.8% identical
n8n-io/n8n · AGENTS.md
@@ −1 @@
1# AGENTS.md
2 
3This file provides guidance on how to work with the n8n repository.
 
4 
5## Project Overview
6 
7n8n is a workflow automation platform written in TypeScript, using a monorepo
8structure managed by pnpm workspaces. It consists of a Node.js backend, Vue.js
9frontend, and extensible node-based workflow engine.
10 
11## General Guidelines
 
12 
13- Always use pnpm
14- **Secrets on the command line:** if a developer opted into anonymous dev
15 metrics (`scripts/dev-metrics`), pnpm command arguments are recorded. Arguments
16 of secret-carrying words (`config`, `login`, `publish`, `token`) — whether a
17 subcommand or baked into a flag — are dropped, and the home dir is stripped from
18 paths, but other args are sent as-is — so never put secrets in a command. Pass
19 sensitive values via environment variables, which are never captured.
20- When adding comments, keep them concise and to the point - explain the "why"
21 in a line or two; don't be overly verbose. Comments should be scoped and
22 relevant to the surrounding code, not just to the current task
23- We use Linear as a ticket tracking system
24- We use Posthog for feature flags
25- To find registered telemetry events (names, descriptions, properties), run
26 `pnpm --filter @n8n/telemetry catalog` (`--json` for structured output). The
27 registry is being adopted incrementally, so search call sites if the catalog
28 has no match. The `n8n:telemetry` skill covers adding or changing events
29- When starting to work on a new ticket – create a new branch from fresh
30 master with the name specified in Linear ticket
31- When creating a new branch for a ticket in Linear - use the branch name
32 suggested by Linear, **unless it is a security fix** (see Security Fix
33 Hygiene below)
34- Use mermaid diagrams in MD files when you need to visualise something
35- **Developing v3 features:** land normal feature work on `master` behind an
36 opt-in flag; introduce breaking changes only on the `3.x` branch. See
37 [.github/DEVELOPING_V3.md](.github/DEVELOPING_V3.md).
38 
39## Agent Skills and Claude Code Plugin
 
 
40 
41n8n shared skills live in `.agents/skills/`. Claude Code consumes them through
42symlinks in `.claude/plugins/n8n/skills/`; OpenCode reads `.agents/skills/`
43directly. Harness-specific overrides remain real directories in the harness
44path, such as `.opencode/skills/setup-mcps/`. See
45[skills README](.agents/skills/AGENTS.md) for editing and sync guidance.
 
 
 
 
 
 
46 
47n8n-specific Claude Code commands and agents live in `.claude/plugins/n8n/` and
48are namespaced under `n8n:`. Use `n8n:` prefix when invoking them (e.g.
49`/n8n:create-pr`, `/n8n:plan`, `n8n:developer` agent). See
50[plugin README](.claude/plugins/n8n/README.md) for structure and details.
51 
52## Essential Commands
 
53 
54### Fresh checkout / agent setup
 
 
 
 
 
 
55 
56For a fresh checkout (cat-bot, a new hire, any agent verifying the repo
57builds), prefer `pnpm agent:setup` over running install + build + tests by
58hand. It chains them in one process, caps per-process memory and turbo
59concurrency so a 6GB box doesn't OOM, streams all output to
60`.agent-setup/<step>.log` (gitignored), and surfaces only a one-line summary
61per step plus the tail of the failing log. A machine-readable
62`.agent-setup/summary.json` is always written so a backgrounded run is
63readable in a single shot — no polling, no scrolling logs.
64 
65```bash
66pnpm agent:setup # install → build → test (full suite)
67pnpm agent:setup install # one step at a time
68pnpm agent:setup --json # JSON summary on stdout (for scripts/agents)
69```
70 
71### Building
72Use `pnpm build` to build all packages. ALWAYS redirect the output of the
73build command to a file:
 
 
 
 
74 
75```bash
76pnpm build > build.log 2>&1
77```
78 
79You can inspect the last few lines of the build log file to check for errors:
80```bash
81tail -n 20 build.log
82```
83 
84If build outputs or the turbo cache are stale (e.g. after switching branches
85or worktrees) but dependencies haven't changed, use `pnpm reset` (lightweight
86by default) for a fast recovery: it cleans build outputs and force-rebuilds
87(keeping `node_modules` and untracked files). If that doesn't fix your issue,
88use `pnpm reset --full`, which also wipes untracked files and reinstalls
89dependencies.
90 
91### Testing
92- `pnpm test` - Run all tests
93- `pnpm test:affected` - Runs tests based on what has changed since the last
94 commit
95 
96Running a particular test file requires going to the directory of that test
97and running: `pnpm test <test-file>`.
98 
99When changing directories, use `pushd` to navigate into the directory and
100`popd` to return to the previous directory. When in doubt, use `pwd` to check
101your current directory.
102 
103### Code Quality
104- `pnpm lint` - Lint code
105- `pnpm typecheck` - Run type checks
106 
107Always run lint and typecheck before committing code to ensure quality.
108Execute these commands from within the specific package directory you're
109working on (e.g., `cd packages/cli && pnpm lint`). Run the full repository
110check only when preparing the final PR. When your changes affect type
111definitions, interfaces in `@n8n/api-types`, or cross-package dependencies,
112build the system before running lint and typecheck.
113 
114## Architecture Overview
115 
116**Monorepo Structure:** pnpm workspaces with Turbo build orchestration
117 
118### Package Structure
119 
120The monorepo is organized into these key packages:
121 
122- **`packages/@n8n/api-types`**: Shared TypeScript interfaces between frontend and backend
123- **`packages/workflow`**: Core workflow interfaces and types
124- **`packages/core`**: Workflow execution engine
125- **`packages/cli`**: Express server, REST API, and CLI commands
126- **`packages/frontend/editor-ui`**: Vue 3 frontend application
127- **`packages/frontend/@n8n/i18n`**: Internationalization for UI text
128- **`packages/nodes-base`**: Built-in nodes for integrations
129- **`packages/@n8n/nodes-langchain`**: AI/LangChain nodes
130- **`packages/@n8n/instance-ai`**: "AI Assistant" in the UI, "Instance AI" in code — AI assistant backend. See its `CLAUDE.md` for architecture docs.
131- **`@n8n/design-system`**: Vue component library for UI consistency
132- **`@n8n/config`**: Centralized configuration management
133 
134## Technology Stack
135 
136- **Frontend:** Vue 3 + TypeScript + Vite + Pinia + Storybook UI Library
137- **Backend:** Node.js + TypeScript + Express + TypeORM
138- **Testing:** Vitest (unit) + Playwright (E2E)
139- **Database:** TypeORM with SQLite/PostgreSQL support
140- **Code Quality:** Biome (for formatting) + ESLint + lefthook git hooks
141 
142### Key Architectural Patterns
143 
1441. **Dependency Injection**: Uses `@n8n/di` for IoC container
1452. **Controller-Service-Repository**: Backend follows MVC-like pattern
1463. **Event-Driven**: Internal event bus for decoupled communication
1474. **Context-Based Execution**: Different contexts for different node types
1485. **State Management**: Frontend uses Pinia stores
1496. **Design System**: Reusable components and design tokens are centralized in
150 `@n8n/design-system`, where all pure Vue components should be placed to
151 ensure consistency and reusability
152 
153## Key Development Patterns
154 
155- Each package has isolated build configuration and can be developed independently
156- Hot reload works across the full stack during development
157- Node development uses dedicated `node-dev` CLI tool
158- Workflow tests are JSON-based for integration testing
159- AI features have dedicated development workflow (`pnpm dev:ai`)
160 
161### Workflow Traversal Utilities
162 
163The `n8n-workflow` package exports graph traversal utilities from
164`packages/workflow/src/common/`. Use these instead of custom traversal logic.
165 
166**Key concept:** `workflow.connections` is indexed by **source node**.
167To find parent nodes, use `mapConnectionsByDestination()` to invert it first.
168 
169```typescript
170import { getParentNodes, getChildNodes, mapConnectionsByDestination } from 'n8n-workflow';
171 
172// Finding parent nodes (predecessors) - requires inverted connections
173const connectionsByDestination = mapConnectionsByDestination(workflow.connections);
174const parents = getParentNodes(connectionsByDestination, 'NodeName', 'main', 1);
175 
176// Finding child nodes (successors) - uses connections directly
177const children = getChildNodes(workflow.connections, 'NodeName', 'main', 1);
178```
179 
180### TypeScript Best Practices
181- **NEVER use `any` type** - use proper types or `unknown`
182- **Avoid type casting with `as`** - use type guards or type predicates instead (except in test code where `as` is acceptable)
183- **Define shared interfaces in `@n8n/api-types`** package for FE/BE communication
184- **Lazy-load heavy modules** — if a module is only used in a specific code
185 path (not every request), use `await import()` at point of use instead of
186 top-level `import`. Applies especially to native modules and large parsers.
187 
188### Error Handling
189- Don't use the deprecated `ApplicationError` class anywhere — it's a
190 compatibility shim kept only so community nodes keep resolving. Use one of
191 these instead, picking by cause:
192 - `UserError` — the user caused it (invalid input, unauthorized action,
193 business-rule violation).
194 - `OperationalError` — a transient, expected issue (network request failing,
195 DB query timing out) that should be handled gracefully.
196 - `UnexpectedError` — a bug in the code (logic mistake, unhandled case,
197 failed assertion) that developers need to fix.
198- Import from appropriate error classes in each package
199 
200### Persistence layer & the TypeORM boundary
201 
202TypeORM (`@n8n/typeorm`) must stay in the **persistence layer** — the `@n8n/db`
203package or a backend module's own `database/` folder (entity/repository files).
204Business logic — services, controllers, handlers, commands, factories — must not
205import from `@n8n/typeorm` (including `@n8n/typeorm/...` subpaths). In
206`packages/cli` this is enforced by the `misplaced-n8n-typeorm-import` lint rule;
207a new import (or an inline `eslint-disable` of the rule) fails CI.
208 
209- **Pattern:** when a query needs operators (`In`, `IsNull`, `LessThan`,
210 `FindOptionsWhere`, …), put it behind a **use-case-named repository method**
211 that takes plain parameters and returns domain-shaped values — not a generic
212 `find(options)` passthrough.
213- **Transactions:** transaction orchestration belongs in the persistence layer.
214 Don't reach for `.manager` / `.manager.transaction(...)` or
215 `createQueryBuilder(...)` in business logic. Use the sanctioned primitive in
216 `@n8n/db`: inject the abstract `TransactionRunner` and wrap the unit of work in
217 `txRunner.run(ctx, async (ctx) => …)`. The callback receives an
218 `OperationContext` carrying the active transaction; thread that `ctx` into the
219 repository methods you call. `run` **requires** a context — pass an empty `{}`
220 at the operation entry point, and reuse the one you were handed everywhere
221 below it (a context that already carries a transaction is joined, not nested).
222 Repositories extend `BaseRepository` and resolve the right `EntityManager` with
223 `this.managerFor(ctx)`; the `Transaction` handle is opaque and never exposes a
224 driver type to business logic. See `oauth-token.service.ts` +
225 `oauth-*-token.repository.ts` for a worked example.
226- **Anti-patterns reviewers reject** — they hide the dependency instead of
227 removing it:
228 - String-matching TypeORM errors, e.g. `error.name === 'QueryFailedError'`.
229 - Relabeling the import from `@n8n/typeorm` to `@n8n/db` to silence the rule
230 (`@n8n/db` re-exports several operators/types, but this relabels the
231 dependency rather than removing it).
232 - Pushing `.manager` / `createQueryBuilder` into business logic to avoid an
233 operator import — trades a visible leak for an invisible one.
234 
235### Frontend Development
236- Refer to `packages/frontend/AGENTS.md`
237- **All UI text must use i18n** - add translations to `@n8n/i18n` package
238- **Use CSS variables directly** - never hardcode spacing as px values
239- **data-testid must be a single value** (no spaces or multiple values)
240- Always use `design-system-rules` skill in reviews
241 
242### Testing Guidelines
243- **Always work from within the package directory** when running tests
244- **Mock all external dependencies** in unit tests
245- **Prefer reusing hoisted shared `mock<T>(...)` fixtures** when a typed mock is immutable and used across tests. This rule exists to avoid massive test slowdowns from repeatedly creating nested proxy mocks while preserving the type contract. Avoid replacing these with `as unknown as T` helpers for entities like `User`.
246- **Confirm test cases with user** before writing unit tests
247- **Typecheck is critical before committing** - always run `pnpm typecheck`
248- **When modifying pinia stores**, check for unused computed properties
249- **For Vitest packages that use `@n8n/di` decorators**, use `createVitestConfigWithDecorators` from `@n8n/vitest-config/node-decorators`. It enables SWC `decoratorMetadata` (esbuild doesn't emit it) and externalizes workspace packages that register services (`@n8n/di`, `@n8n/config`, `@n8n/constants`, `n8n-workflow`) so a single DI `Container` instance is shared across the runtime. Loading them through Vitest's pipeline alongside their CJS dist produces two `Container`s and `Container.get(...)` returns `undefined`.
250 
251What we use for testing and writing tests:
252- For testing nodes and other backend components, we use Vitest for unit tests. Examples can be found in `packages/nodes-base/nodes/**/*test*`.
253- We use `nock` for server mocking
254- For frontend we use `vitest`
255- For E2E tests we use Playwright. Run with `pnpm --filter=n8n-playwright test:local`.
256 See `packages/testing/playwright/README.md` for details.
257- **To iterate on a feature without docker rebuilds**, boot service containers
258 and run `pnpm dev` locally — `pnpm --filter n8n-containers services --services postgres,redis,mailpit,proxy`
259 then `pnpm dev`. See [Develop against running containers](packages/testing/playwright/README.md#develop-against-running-containers-avoid-docker-rebuilds).
260- **For Playwright test maintenance/cleanup**, see `packages/testing/playwright/AGENTS.md` (includes janitor tool for static analysis, dead code removal, architecture enforcement, and TCR workflows).
261 
262### Common Development Tasks
263 
264When implementing features:
2651. Define API types in `packages/@n8n/api-types`
2662. Implement backend logic in `packages/cli` module, follow
267 `scripts/backend-module/backend-module-guide.md`
2683. Add API endpoints via controllers
2694. Update frontend in `packages/frontend/editor-ui` with i18n support
2705. Write tests with proper mocks
2716. Run `pnpm typecheck` to verify types
272 
273## Design Principles
274 
275### Security Must Not Degrade the Building Experience
276 
277Security improvements, whether driven by enterprise requirements or internal
278standards, must NEVER add friction to the common-case building experience. When
279designing security-related features (defaults, behaviors, flows, error
280handling), apply these checks:
281 
282- **No friction for the common case:** A community builder's workflow should
283 remain intuitive. Security should be invisible when it can be.
284- **Migration and upgrade paths:** Existing users must have a clear,
285 non-disruptive path forward when defaults or behaviors change.
286- **Security layers on top, not in competition:** Great UX and strong security
287 are not trade-offs. They're both required. If a design forces a choice
288 between them, the design needs more work.
289 
290### Security Fix Hygiene
291 
292**This is a public repository.** When working on security fixes, never expose
293the attack vector or vulnerability type in any public-facing artifact. Attackers
294monitor open-source repos for signals like branch names, commit messages, PR
295titles, test descriptions, and Linear URLs.
296 
297**Rules for security fixes:**
298 
299- **Branch names:** Do NOT use the Linear-suggested branch name if it reveals
300 the vulnerability. Rename to describe the fix neutrally
301 (e.g. `node-1234-improve-request-handling`, not
302 `node-1234-fix-ddos-vulnerability`).
303- **Commit messages:** Describe what the code now does, not the threat it
304 prevents (e.g. `fix: add payload size validation`, not
305 `fix: prevent denial of service`).
306- **Test descriptions:** Use neutral, functional language
307 (e.g. `'should sanitize query parameters'`, not
308 `'should prevent SQL injection'`).
309- **Code comments:** Do not describe the attack scenario in comments.
310- **Linear references:** Never include the URL slug
311 (e.g. `.../N8N-1234/fix-ssrf-vulnerability`).
312 
313### Customer Confidentiality
314 
315**This is a public repository.** Never mention customer names in any
316public-facing artifact — not all customers have agreed to be named publicly,
317and naming them can reveal security-relevant details about their setup.
318 
319This applies to PR titles and descriptions, branch names, commit messages,
320code, code comments, test names and test data, and fixtures. When implementing
321a customer request, describe the use case neutrally (e.g. "a customer with a
322large multi-main setup", not the company name) and use generic placeholder
323names (e.g. `Acme Corp`) in tests and examples.
324 
325## Github Guidelines
326- When creating a PR, use the conventions in
327 `.github/pull_request_template.md` and
328 `.github/pull_request_title_conventions.md`.
329- Use `gh pr create --draft` to create draft PRs.
330- If there is a corresponding Linear ticket, reference it in the PR
331 description using `https://linear.app/n8n/issue/[TICKET-ID]`. Do not
332 create a Linear ticket on your own — ask first.
333- always link to the github issue if mentioned in the linear ticket.
334 
n8n-io/n8n · packages/cli/AGENTS.md
@@ +1 @@
1# AGENTS.md
2 
3Guidance specific to the `cli` package. See the root [AGENTS.md](../../AGENTS.md)
4for repo-wide conventions.
5 
6## TypeORM boundary
7 
8TypeORM belongs in the **persistence layer**, not in business logic.
 
 
9 
10**Allowed to import `@n8n/typeorm`** — entity and repository files, including the
11ones co-located inside `src/modules/**`:
12 
13- `src/databases/**`
14- a module's `database/entities/**` and `database/repositories/**`
15- files named `*.entity.ts` or `*.repository.ts` (some modules keep these at the
16 module root)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17 
18These are exempted in `eslint.config.mjs` **by location**, so a genuine `@Entity`
19or repository class is never flagged — including the few entity files that lack
20the `.entity.ts` suffix (they live in a `database/entities/` folder).
21 
22**Not allowed** — business logic (services, controllers, public-api handlers,
23commands, factories) must not import `@n8n/typeorm` or `@n8n/typeorm/...`
24subpaths. The `misplaced-n8n-typeorm-import` lint rule enforces this; a new
25import — or an inline `eslint-disable` of the rule — fails CI. The same rule also
26catches the **relabel dodge**: importing a TypeORM operator/driver type (`In`,
27`Not`, `FindOptionsWhere`, `EntityManager`, …) from `@n8n/db`, which
28re-exports them from `@n8n/typeorm` — that silences the direct-import check
29without decoupling anything. Existing leaks of both kinds are tracked in two
30`files`-scoped allowlists in `eslint.config.mjs` (direct `@n8n/typeorm` imports,
31and `@n8n/db` relabels) that only ever shrink: never add to them, and never
32suppress the rule inline.
33 
34Distinct from that shrink-only ratchet, two files are **permanently** exempted in
35`eslint.config.mjs` for legitimate TypeORM use outside the persistence tree —
36these are sanctioned, not migration targets, so don't try to relocate them or
37suppress the rule:
38 
39- `src/commands/db/revert.ts` — `MigrationExecutor` (CLI migration tooling)
40- `src/security-audit/security-audit.repository.ts` — `PackagesRepository`
41 
42Need an operator query (`In`, `IsNull`, `FindOptionsWhere`, …)? Add a
43use-case-named repository method (plain parameters, domain-shaped return) rather
44than importing the operator into business logic. Relabeling the import to
45`@n8n/db` is lint-enforced against, not just convention (see above); likewise
46don't string-match `QueryFailedError` or push `.manager` / `createQueryBuilder`
47into business logic to dodge the rule. See the root "Persistence layer & the
48TypeORM boundary" section for the full rationale.
49 
50## Transactions
 
 
 
 
 
 
 
51 
52Three patterns coexist while the persistence layer is migrated — new code uses
53only the third:
 
 
 
54 
551. **`manager.transaction(...)`** — raw TypeORM, leaks the ORM into business
56 logic. Anti-pattern; being removed.
572. **`withTransaction(...)`** (`@n8n/db`) — deprecated helper that still hands an
58 `EntityManager` to its callback. Removed as call sites migrate.
593. **`TransactionRunner.run(ctx, fn)`** (`@n8n/db`) — the target. Inject the
60 `TransactionRunner` port and thread the `OperationContext`; the driver handle
61 never reaches business logic. Use this for new work.
62 
63See the root AGENTS.md "Transactions" bullet for the full API and a worked
64example.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65 
@@ −1 +1 @@
11 # AGENTS.md
22  
3−This file provides guidance on how to work with the n8n repository.
3+Guidance specific to the `cli` package. See the root [AGENTS.md](../../AGENTS.md)
4+for repo-wide conventions.
45  
5−## Project Overview
6+## TypeORM boundary
67  
7−n8n is a workflow automation platform written in TypeScript, using a monorepo
8−structure managed by pnpm workspaces. It consists of a Node.js backend, Vue.js
9−frontend, and extensible node-based workflow engine.
8+TypeORM belongs in the **persistence layer**, not in business logic.
109  
11−## General Guidelines
10+**Allowed to import `@n8n/typeorm`** — entity and repository files, including the
11+ones co-located inside `src/modules/**`:
1212  
13−- Always use pnpm
14−- **Secrets on the command line:** if a developer opted into anonymous dev
15− metrics (`scripts/dev-metrics`), pnpm command arguments are recorded. Arguments
16− of secret-carrying words (`config`, `login`, `publish`, `token`) — whether a
17− subcommand or baked into a flag — are dropped, and the home dir is stripped from
18− paths, but other args are sent as-is — so never put secrets in a command. Pass
19− sensitive values via environment variables, which are never captured.
20−- When adding comments, keep them concise and to the point - explain the "why"
21− in a line or two; don't be overly verbose. Comments should be scoped and
22− relevant to the surrounding code, not just to the current task
23−- We use Linear as a ticket tracking system
24−- We use Posthog for feature flags
25−- To find registered telemetry events (names, descriptions, properties), run
26− `pnpm --filter @n8n/telemetry catalog` (`--json` for structured output). The
27− registry is being adopted incrementally, so search call sites if the catalog
28− has no match. The `n8n:telemetry` skill covers adding or changing events
29−- When starting to work on a new ticket – create a new branch from fresh
30− master with the name specified in Linear ticket
31−- When creating a new branch for a ticket in Linear - use the branch name
32− suggested by Linear, **unless it is a security fix** (see Security Fix
33− Hygiene below)
34−- Use mermaid diagrams in MD files when you need to visualise something
35−- **Developing v3 features:** land normal feature work on `master` behind an
36− opt-in flag; introduce breaking changes only on the `3.x` branch. See
37− [.github/DEVELOPING_V3.md](.github/DEVELOPING_V3.md).
13+- `src/databases/**`
14+- a module's `database/entities/**` and `database/repositories/**`
15+- files named `*.entity.ts` or `*.repository.ts` (some modules keep these at the
16+ module root)
3817  
39−## Agent Skills and Claude Code Plugin
18+These are exempted in `eslint.config.mjs` **by location**, so a genuine `@Entity`
19+or repository class is never flagged — including the few entity files that lack
20+the `.entity.ts` suffix (they live in a `database/entities/` folder).
4021  
41−n8n shared skills live in `.agents/skills/`. Claude Code consumes them through
42−symlinks in `.claude/plugins/n8n/skills/`; OpenCode reads `.agents/skills/`
43−directly. Harness-specific overrides remain real directories in the harness
44−path, such as `.opencode/skills/setup-mcps/`. See
45−[skills README](.agents/skills/AGENTS.md) for editing and sync guidance.
22+**Not allowed** — business logic (services, controllers, public-api handlers,
23+commands, factories) must not import `@n8n/typeorm` or `@n8n/typeorm/...`
24+subpaths. The `misplaced-n8n-typeorm-import` lint rule enforces this; a new
25+import — or an inline `eslint-disable` of the rule — fails CI. The same rule also
26+catches the **relabel dodge**: importing a TypeORM operator/driver type (`In`,
27+`Not`, `FindOptionsWhere`, `EntityManager`, …) from `@n8n/db`, which
28+re-exports them from `@n8n/typeorm` — that silences the direct-import check
29+without decoupling anything. Existing leaks of both kinds are tracked in two
30+`files`-scoped allowlists in `eslint.config.mjs` (direct `@n8n/typeorm` imports,
31+and `@n8n/db` relabels) that only ever shrink: never add to them, and never
32+suppress the rule inline.
4633  
47−n8n-specific Claude Code commands and agents live in `.claude/plugins/n8n/` and
48−are namespaced under `n8n:`. Use `n8n:` prefix when invoking them (e.g.
49−`/n8n:create-pr`, `/n8n:plan`, `n8n:developer` agent). See
50−[plugin README](.claude/plugins/n8n/README.md) for structure and details.
34+Distinct from that shrink-only ratchet, two files are **permanently** exempted in
35+`eslint.config.mjs` for legitimate TypeORM use outside the persistence tree —
36+these are sanctioned, not migration targets, so don't try to relocate them or
37+suppress the rule:
5138  
52−## Essential Commands
39+- `src/commands/db/revert.ts` — `MigrationExecutor` (CLI migration tooling)
40+- `src/security-audit/security-audit.repository.ts` — `PackagesRepository`
5341  
54−### Fresh checkout / agent setup
42+Need an operator query (`In`, `IsNull`, `FindOptionsWhere`, …)? Add a
43+use-case-named repository method (plain parameters, domain-shaped return) rather
44+than importing the operator into business logic. Relabeling the import to
45+`@n8n/db` is lint-enforced against, not just convention (see above); likewise
46+don't string-match `QueryFailedError` or push `.manager` / `createQueryBuilder`
47+into business logic to dodge the rule. See the root "Persistence layer & the
48+TypeORM boundary" section for the full rationale.
5549  
56−For a fresh checkout (cat-bot, a new hire, any agent verifying the repo
57−builds), prefer `pnpm agent:setup` over running install + build + tests by
58−hand. It chains them in one process, caps per-process memory and turbo
59−concurrency so a 6GB box doesn't OOM, streams all output to
60−`.agent-setup/<step>.log` (gitignored), and surfaces only a one-line summary
61−per step plus the tail of the failing log. A machine-readable
62−`.agent-setup/summary.json` is always written so a backgrounded run is
63−readable in a single shot — no polling, no scrolling logs.
50+## Transactions
6451  
65−```bash
66−pnpm agent:setup # install → build → test (full suite)
67−pnpm agent:setup install # one step at a time
68−pnpm agent:setup --json # JSON summary on stdout (for scripts/agents)
69−```
52+Three patterns coexist while the persistence layer is migrated — new code uses
53+only the third:
7054  
71−### Building
72−Use `pnpm build` to build all packages. ALWAYS redirect the output of the
73−build command to a file:
55+1. **`manager.transaction(...)`** — raw TypeORM, leaks the ORM into business
56+ logic. Anti-pattern; being removed.
57+2. **`withTransaction(...)`** (`@n8n/db`) — deprecated helper that still hands an
58+ `EntityManager` to its callback. Removed as call sites migrate.
59+3. **`TransactionRunner.run(ctx, fn)`** (`@n8n/db`) — the target. Inject the
60+ `TransactionRunner` port and thread the `OperationContext`; the driver handle
61+ never reaches business logic. Use this for new work.
7462  
75−```bash
76−pnpm build > build.log 2>&1
77−```
78− 
79−You can inspect the last few lines of the build log file to check for errors:
80−```bash
81−tail -n 20 build.log
82−```
83− 
84−If build outputs or the turbo cache are stale (e.g. after switching branches
85−or worktrees) but dependencies haven't changed, use `pnpm reset` (lightweight
86−by default) for a fast recovery: it cleans build outputs and force-rebuilds
87−(keeping `node_modules` and untracked files). If that doesn't fix your issue,
88−use `pnpm reset --full`, which also wipes untracked files and reinstalls
89−dependencies.
90− 
91−### Testing
92−- `pnpm test` - Run all tests
93−- `pnpm test:affected` - Runs tests based on what has changed since the last
94− commit
95− 
96−Running a particular test file requires going to the directory of that test
97−and running: `pnpm test <test-file>`.
98− 
99−When changing directories, use `pushd` to navigate into the directory and
100−`popd` to return to the previous directory. When in doubt, use `pwd` to check
101−your current directory.
102− 
103−### Code Quality
104−- `pnpm lint` - Lint code
105−- `pnpm typecheck` - Run type checks
106− 
107−Always run lint and typecheck before committing code to ensure quality.
108−Execute these commands from within the specific package directory you're
109−working on (e.g., `cd packages/cli && pnpm lint`). Run the full repository
110−check only when preparing the final PR. When your changes affect type
111−definitions, interfaces in `@n8n/api-types`, or cross-package dependencies,
112−build the system before running lint and typecheck.
113− 
114−## Architecture Overview
115− 
116−**Monorepo Structure:** pnpm workspaces with Turbo build orchestration
117− 
118−### Package Structure
119− 
120−The monorepo is organized into these key packages:
121− 
122−- **`packages/@n8n/api-types`**: Shared TypeScript interfaces between frontend and backend
123−- **`packages/workflow`**: Core workflow interfaces and types
124−- **`packages/core`**: Workflow execution engine
125−- **`packages/cli`**: Express server, REST API, and CLI commands
126−- **`packages/frontend/editor-ui`**: Vue 3 frontend application
127−- **`packages/frontend/@n8n/i18n`**: Internationalization for UI text
128−- **`packages/nodes-base`**: Built-in nodes for integrations
129−- **`packages/@n8n/nodes-langchain`**: AI/LangChain nodes
130−- **`packages/@n8n/instance-ai`**: "AI Assistant" in the UI, "Instance AI" in code — AI assistant backend. See its `CLAUDE.md` for architecture docs.
131−- **`@n8n/design-system`**: Vue component library for UI consistency
132−- **`@n8n/config`**: Centralized configuration management
133− 
134−## Technology Stack
135− 
136−- **Frontend:** Vue 3 + TypeScript + Vite + Pinia + Storybook UI Library
137−- **Backend:** Node.js + TypeScript + Express + TypeORM
138−- **Testing:** Vitest (unit) + Playwright (E2E)
139−- **Database:** TypeORM with SQLite/PostgreSQL support
140−- **Code Quality:** Biome (for formatting) + ESLint + lefthook git hooks
141− 
142−### Key Architectural Patterns
143− 
144−1. **Dependency Injection**: Uses `@n8n/di` for IoC container
145−2. **Controller-Service-Repository**: Backend follows MVC-like pattern
146−3. **Event-Driven**: Internal event bus for decoupled communication
147−4. **Context-Based Execution**: Different contexts for different node types
148−5. **State Management**: Frontend uses Pinia stores
149−6. **Design System**: Reusable components and design tokens are centralized in
150− `@n8n/design-system`, where all pure Vue components should be placed to
151− ensure consistency and reusability
152− 
153−## Key Development Patterns
154− 
155−- Each package has isolated build configuration and can be developed independently
156−- Hot reload works across the full stack during development
157−- Node development uses dedicated `node-dev` CLI tool
158−- Workflow tests are JSON-based for integration testing
159−- AI features have dedicated development workflow (`pnpm dev:ai`)
160− 
161−### Workflow Traversal Utilities
162− 
163−The `n8n-workflow` package exports graph traversal utilities from
164−`packages/workflow/src/common/`. Use these instead of custom traversal logic.
165− 
166−**Key concept:** `workflow.connections` is indexed by **source node**.
167−To find parent nodes, use `mapConnectionsByDestination()` to invert it first.
168− 
169−```typescript
170−import { getParentNodes, getChildNodes, mapConnectionsByDestination } from 'n8n-workflow';
171− 
172−// Finding parent nodes (predecessors) - requires inverted connections
173−const connectionsByDestination = mapConnectionsByDestination(workflow.connections);
174−const parents = getParentNodes(connectionsByDestination, 'NodeName', 'main', 1);
175− 
176−// Finding child nodes (successors) - uses connections directly
177−const children = getChildNodes(workflow.connections, 'NodeName', 'main', 1);
178−```
179− 
180−### TypeScript Best Practices
181−- **NEVER use `any` type** - use proper types or `unknown`
182−- **Avoid type casting with `as`** - use type guards or type predicates instead (except in test code where `as` is acceptable)
183−- **Define shared interfaces in `@n8n/api-types`** package for FE/BE communication
184−- **Lazy-load heavy modules** — if a module is only used in a specific code
185− path (not every request), use `await import()` at point of use instead of
186− top-level `import`. Applies especially to native modules and large parsers.
187− 
188−### Error Handling
189−- Don't use the deprecated `ApplicationError` class anywhere — it's a
190− compatibility shim kept only so community nodes keep resolving. Use one of
191− these instead, picking by cause:
192− - `UserError` — the user caused it (invalid input, unauthorized action,
193− business-rule violation).
194− - `OperationalError` — a transient, expected issue (network request failing,
195− DB query timing out) that should be handled gracefully.
196− - `UnexpectedError` — a bug in the code (logic mistake, unhandled case,
197− failed assertion) that developers need to fix.
198−- Import from appropriate error classes in each package
199− 
200−### Persistence layer & the TypeORM boundary
201− 
202−TypeORM (`@n8n/typeorm`) must stay in the **persistence layer** — the `@n8n/db`
203−package or a backend module's own `database/` folder (entity/repository files).
204−Business logic — services, controllers, handlers, commands, factories — must not
205−import from `@n8n/typeorm` (including `@n8n/typeorm/...` subpaths). In
206−`packages/cli` this is enforced by the `misplaced-n8n-typeorm-import` lint rule;
207−a new import (or an inline `eslint-disable` of the rule) fails CI.
208− 
209−- **Pattern:** when a query needs operators (`In`, `IsNull`, `LessThan`,
210− `FindOptionsWhere`, …), put it behind a **use-case-named repository method**
211− that takes plain parameters and returns domain-shaped values — not a generic
212− `find(options)` passthrough.
213−- **Transactions:** transaction orchestration belongs in the persistence layer.
214− Don't reach for `.manager` / `.manager.transaction(...)` or
215− `createQueryBuilder(...)` in business logic. Use the sanctioned primitive in
216− `@n8n/db`: inject the abstract `TransactionRunner` and wrap the unit of work in
217− `txRunner.run(ctx, async (ctx) => …)`. The callback receives an
218− `OperationContext` carrying the active transaction; thread that `ctx` into the
219− repository methods you call. `run` **requires** a context — pass an empty `{}`
220− at the operation entry point, and reuse the one you were handed everywhere
221− below it (a context that already carries a transaction is joined, not nested).
222− Repositories extend `BaseRepository` and resolve the right `EntityManager` with
223− `this.managerFor(ctx)`; the `Transaction` handle is opaque and never exposes a
224− driver type to business logic. See `oauth-token.service.ts` +
225− `oauth-*-token.repository.ts` for a worked example.
226−- **Anti-patterns reviewers reject** — they hide the dependency instead of
227− removing it:
228− - String-matching TypeORM errors, e.g. `error.name === 'QueryFailedError'`.
229− - Relabeling the import from `@n8n/typeorm` to `@n8n/db` to silence the rule
230− (`@n8n/db` re-exports several operators/types, but this relabels the
231− dependency rather than removing it).
232− - Pushing `.manager` / `createQueryBuilder` into business logic to avoid an
233− operator import — trades a visible leak for an invisible one.
234− 
235−### Frontend Development
236−- Refer to `packages/frontend/AGENTS.md`
237−- **All UI text must use i18n** - add translations to `@n8n/i18n` package
238−- **Use CSS variables directly** - never hardcode spacing as px values
239−- **data-testid must be a single value** (no spaces or multiple values)
240−- Always use `design-system-rules` skill in reviews
241− 
242−### Testing Guidelines
243−- **Always work from within the package directory** when running tests
244−- **Mock all external dependencies** in unit tests
245−- **Prefer reusing hoisted shared `mock<T>(...)` fixtures** when a typed mock is immutable and used across tests. This rule exists to avoid massive test slowdowns from repeatedly creating nested proxy mocks while preserving the type contract. Avoid replacing these with `as unknown as T` helpers for entities like `User`.
246−- **Confirm test cases with user** before writing unit tests
247−- **Typecheck is critical before committing** - always run `pnpm typecheck`
248−- **When modifying pinia stores**, check for unused computed properties
249−- **For Vitest packages that use `@n8n/di` decorators**, use `createVitestConfigWithDecorators` from `@n8n/vitest-config/node-decorators`. It enables SWC `decoratorMetadata` (esbuild doesn't emit it) and externalizes workspace packages that register services (`@n8n/di`, `@n8n/config`, `@n8n/constants`, `n8n-workflow`) so a single DI `Container` instance is shared across the runtime. Loading them through Vitest's pipeline alongside their CJS dist produces two `Container`s and `Container.get(...)` returns `undefined`.
250− 
251−What we use for testing and writing tests:
252−- For testing nodes and other backend components, we use Vitest for unit tests. Examples can be found in `packages/nodes-base/nodes/**/*test*`.
253−- We use `nock` for server mocking
254−- For frontend we use `vitest`
255−- For E2E tests we use Playwright. Run with `pnpm --filter=n8n-playwright test:local`.
256− See `packages/testing/playwright/README.md` for details.
257−- **To iterate on a feature without docker rebuilds**, boot service containers
258− and run `pnpm dev` locally — `pnpm --filter n8n-containers services --services postgres,redis,mailpit,proxy`
259− then `pnpm dev`. See [Develop against running containers](packages/testing/playwright/README.md#develop-against-running-containers-avoid-docker-rebuilds).
260−- **For Playwright test maintenance/cleanup**, see `packages/testing/playwright/AGENTS.md` (includes janitor tool for static analysis, dead code removal, architecture enforcement, and TCR workflows).
261− 
262−### Common Development Tasks
263− 
264−When implementing features:
265−1. Define API types in `packages/@n8n/api-types`
266−2. Implement backend logic in `packages/cli` module, follow
267− `scripts/backend-module/backend-module-guide.md`
268−3. Add API endpoints via controllers
269−4. Update frontend in `packages/frontend/editor-ui` with i18n support
270−5. Write tests with proper mocks
271−6. Run `pnpm typecheck` to verify types
272− 
273−## Design Principles
274− 
275−### Security Must Not Degrade the Building Experience
276− 
277−Security improvements, whether driven by enterprise requirements or internal
278−standards, must NEVER add friction to the common-case building experience. When
279−designing security-related features (defaults, behaviors, flows, error
280−handling), apply these checks:
281− 
282−- **No friction for the common case:** A community builder's workflow should
283− remain intuitive. Security should be invisible when it can be.
284−- **Migration and upgrade paths:** Existing users must have a clear,
285− non-disruptive path forward when defaults or behaviors change.
286−- **Security layers on top, not in competition:** Great UX and strong security
287− are not trade-offs. They're both required. If a design forces a choice
288− between them, the design needs more work.
289− 
290−### Security Fix Hygiene
291− 
292−**This is a public repository.** When working on security fixes, never expose
293−the attack vector or vulnerability type in any public-facing artifact. Attackers
294−monitor open-source repos for signals like branch names, commit messages, PR
295−titles, test descriptions, and Linear URLs.
296− 
297−**Rules for security fixes:**
298− 
299−- **Branch names:** Do NOT use the Linear-suggested branch name if it reveals
300− the vulnerability. Rename to describe the fix neutrally
301− (e.g. `node-1234-improve-request-handling`, not
302− `node-1234-fix-ddos-vulnerability`).
303−- **Commit messages:** Describe what the code now does, not the threat it
304− prevents (e.g. `fix: add payload size validation`, not
305− `fix: prevent denial of service`).
306−- **Test descriptions:** Use neutral, functional language
307− (e.g. `'should sanitize query parameters'`, not
308− `'should prevent SQL injection'`).
309−- **Code comments:** Do not describe the attack scenario in comments.
310−- **Linear references:** Never include the URL slug
311− (e.g. `.../N8N-1234/fix-ssrf-vulnerability`).
312− 
313−### Customer Confidentiality
314− 
315−**This is a public repository.** Never mention customer names in any
316−public-facing artifact — not all customers have agreed to be named publicly,
317−and naming them can reveal security-relevant details about their setup.
318− 
319−This applies to PR titles and descriptions, branch names, commit messages,
320−code, code comments, test names and test data, and fixtures. When implementing
321−a customer request, describe the use case neutrally (e.g. "a customer with a
322−large multi-main setup", not the company name) and use generic placeholder
323−names (e.g. `Acme Corp`) in tests and examples.
324− 
325−## Github Guidelines
326−- When creating a PR, use the conventions in
327− `.github/pull_request_template.md` and
328− `.github/pull_request_title_conventions.md`.
329−- Use `gh pr create --draft` to create draft PRs.
330−- If there is a corresponding Linear ticket, reference it in the PR
331− description using `https://linear.app/n8n/issue/[TICKET-ID]`. Do not
332− create a Linear ticket on your own — ask first.
333−- always link to the github issue if mentioned in the linear ticket.
63+See the root AGENTS.md "Transactions" bullet for the full API and a worked
64+example.
33465  
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack