AGENTS.md
AGENTS.mdAGENTS.mdroot
Quality
96/100
Scores the file, not the repository.Length
2,383 words
26 headings · 4 code blocksRepository
199k
— · pushed 0 days agoLast changed
3 days ago
First indexed 3 days ago.1# AGENTS.md23This file provides guidance on how to work with the n8n repository.45## Project Overview67n8n is a workflow automation platform written in TypeScript, using a monorepo8structure managed by pnpm workspaces. It consists of a Node.js backend, Vue.js9frontend, and extensible node-based workflow engine.1011## General Guidelines1213- Always use pnpm14- **Secrets on the command line:** if a developer opted into anonymous dev15 metrics (`scripts/dev-metrics`), pnpm command arguments are recorded. Arguments16 of secret-carrying words (`config`, `login`, `publish`, `token`) — whether a17 subcommand or baked into a flag — are dropped, and the home dir is stripped from18 paths, but other args are sent as-is — so never put secrets in a command. Pass19 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 and22 relevant to the surrounding code, not just to the current task23- We use Linear as a ticket tracking system24- We use Posthog for feature flags25- To find registered telemetry events (names, descriptions, properties), run26 `pnpm --filter @n8n/telemetry catalog` (`--json` for structured output). The27 registry is being adopted incrementally, so search call sites if the catalog28 has no match. The `n8n:telemetry` skill covers adding or changing events29- When starting to work on a new ticket – create a new branch from fresh30 master with the name specified in Linear ticket31- When creating a new branch for a ticket in Linear - use the branch name32 suggested by Linear, **unless it is a security fix** (see Security Fix33 Hygiene below)34- Use mermaid diagrams in MD files when you need to visualise something35- **Developing v3 features:** land normal feature work on `master` behind an36 opt-in flag; introduce breaking changes only on the `3.x` branch. See37 [.github/DEVELOPING_V3.md](.github/DEVELOPING_V3.md).3839## Agent Skills and Claude Code Plugin4041n8n shared skills live in `.agents/skills/`. Claude Code consumes them through42symlinks in `.claude/plugins/n8n/skills/`; OpenCode reads `.agents/skills/`43directly. Harness-specific overrides remain real directories in the harness44path, such as `.opencode/skills/setup-mcps/`. See45[skills README](.agents/skills/AGENTS.md) for editing and sync guidance.4647n8n-specific Claude Code commands and agents live in `.claude/plugins/n8n/` and48are namespaced under `n8n:`. Use `n8n:` prefix when invoking them (e.g.49`/n8n:create-pr`, `/n8n:plan`, `n8n:developer` agent). See50[plugin README](.claude/plugins/n8n/README.md) for structure and details.5152## Essential Commands5354### Fresh checkout / agent setup5556For a fresh checkout (cat-bot, a new hire, any agent verifying the repo57builds), prefer `pnpm agent:setup` over running install + build + tests by58hand. It chains them in one process, caps per-process memory and turbo59concurrency so a 6GB box doesn't OOM, streams all output to60`.agent-setup/<step>.log` (gitignored), and surfaces only a one-line summary61per step plus the tail of the failing log. A machine-readable62`.agent-setup/summary.json` is always written so a backgrounded run is63readable in a single shot — no polling, no scrolling logs.6465```bash66pnpm agent:setup # install → build → test (full suite)67pnpm agent:setup install # one step at a time68pnpm agent:setup --json # JSON summary on stdout (for scripts/agents)69```7071### Building72Use `pnpm build` to build all packages. ALWAYS redirect the output of the73build command to a file:7475```bash76pnpm build > build.log 2>&177```7879You can inspect the last few lines of the build log file to check for errors:80```bash81tail -n 20 build.log82```8384If build outputs or the turbo cache are stale (e.g. after switching branches85or worktrees) but dependencies haven't changed, use `pnpm reset` (lightweight86by default) for a fast recovery: it cleans build outputs and force-rebuilds87(keeping `node_modules` and untracked files). If that doesn't fix your issue,88use `pnpm reset --full`, which also wipes untracked files and reinstalls89dependencies.9091### Testing92- `pnpm test` - Run all tests93- `pnpm test:affected` - Runs tests based on what has changed since the last94 commit9596Running a particular test file requires going to the directory of that test97and running: `pnpm test <test-file>`.9899When changing directories, use `pushd` to navigate into the directory and100`popd` to return to the previous directory. When in doubt, use `pwd` to check101your current directory.102103### Code Quality104- `pnpm lint` - Lint code105- `pnpm typecheck` - Run type checks106107Always run lint and typecheck before committing code to ensure quality.108Execute these commands from within the specific package directory you're109working on (e.g., `cd packages/cli && pnpm lint`). Run the full repository110check only when preparing the final PR. When your changes affect type111definitions, interfaces in `@n8n/api-types`, or cross-package dependencies,112build the system before running lint and typecheck.113114## Architecture Overview115116**Monorepo Structure:** pnpm workspaces with Turbo build orchestration117118### Package Structure119120The monorepo is organized into these key packages:121122- **`packages/@n8n/api-types`**: Shared TypeScript interfaces between frontend and backend123- **`packages/workflow`**: Core workflow interfaces and types124- **`packages/core`**: Workflow execution engine125- **`packages/cli`**: Express server, REST API, and CLI commands126- **`packages/editor-ui`**: Vue 3 frontend application127- **`packages/@n8n/i18n`**: Internationalization for UI text128- **`packages/nodes-base`**: Built-in nodes for integrations129- **`packages/@n8n/nodes-langchain`**: AI/LangChain nodes130- **`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 consistency132- **`@n8n/config`**: Centralized configuration management133134## Technology Stack135136- **Frontend:** Vue 3 + TypeScript + Vite + Pinia + Storybook UI Library137- **Backend:** Node.js + TypeScript + Express + TypeORM138- **Testing:** Vitest (unit) + Playwright (E2E)139- **Database:** TypeORM with SQLite/PostgreSQL support140- **Code Quality:** Biome (for formatting) + ESLint + lefthook git hooks141142### Key Architectural Patterns1431441. **Dependency Injection**: Uses `@n8n/di` for IoC container1452. **Controller-Service-Repository**: Backend follows MVC-like pattern1463. **Event-Driven**: Internal event bus for decoupled communication1474. **Context-Based Execution**: Different contexts for different node types1485. **State Management**: Frontend uses Pinia stores1496. **Design System**: Reusable components and design tokens are centralized in150 `@n8n/design-system`, where all pure Vue components should be placed to151 ensure consistency and reusability152153## Key Development Patterns154155- Each package has isolated build configuration and can be developed independently156- Hot reload works across the full stack during development157- Node development uses dedicated `node-dev` CLI tool158- Workflow tests are JSON-based for integration testing159- AI features have dedicated development workflow (`pnpm dev:ai`)160161### Workflow Traversal Utilities162163The `n8n-workflow` package exports graph traversal utilities from164`packages/workflow/src/common/`. Use these instead of custom traversal logic.165166**Key concept:** `workflow.connections` is indexed by **source node**.167To find parent nodes, use `mapConnectionsByDestination()` to invert it first.168169```typescript170import { getParentNodes, getChildNodes, mapConnectionsByDestination } from 'n8n-workflow';171172// Finding parent nodes (predecessors) - requires inverted connections173const connectionsByDestination = mapConnectionsByDestination(workflow.connections);174const parents = getParentNodes(connectionsByDestination, 'NodeName', 'main', 1);175176// Finding child nodes (successors) - uses connections directly177const children = getChildNodes(workflow.connections, 'NodeName', 'main', 1);178```179180### TypeScript Best Practices181- **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 communication184- **Lazy-load heavy modules** — if a module is only used in a specific code185 path (not every request), use `await import()` at point of use instead of186 top-level `import`. Applies especially to native modules and large parsers.187188### Error Handling189- Don't use the deprecated `ApplicationError` class anywhere — it's a190 compatibility shim kept only so community nodes keep resolving. Use one of191 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 package199200### Persistence layer & the TypeORM boundary201202TypeORM (`@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 not205import from `@n8n/typeorm` (including `@n8n/typeorm/...` subpaths). In206`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.208209- **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 generic212 `find(options)` passthrough.213- **Transactions:** transaction orchestration belongs in the persistence layer.214 Don't reach for `.manager` / `.manager.transaction(...)` or215 `createQueryBuilder(...)` in business logic. Use the sanctioned primitive in216 `@n8n/db`: inject the abstract `TransactionRunner` and wrap the unit of work in217 `txRunner.run(ctx, async (ctx) => …)`. The callback receives an218 `OperationContext` carrying the active transaction; thread that `ctx` into the219 repository methods you call. `run` **requires** a context — pass an empty `{}`220 at the operation entry point, and reuse the one you were handed everywhere221 below it (a context that already carries a transaction is joined, not nested).222 Repositories extend `BaseRepository` and resolve the right `EntityManager` with223 `this.managerFor(ctx)`; the `Transaction` handle is opaque and never exposes a224 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 of227 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 rule230 (`@n8n/db` re-exports several operators/types, but this relabels the231 dependency rather than removing it).232 - Pushing `.manager` / `createQueryBuilder` into business logic to avoid an233 operator import — trades a visible leak for an invisible one.234235### Frontend Development236- Refer to `packages/frontend/AGENTS.md`237- **All UI text must use i18n** - add translations to `@n8n/i18n` package238- **Use CSS variables directly** - never hardcode spacing as px values239- **data-testid must be a single value** (no spaces or multiple values)240- Always use `design-system-rules` skill in reviews241242### Testing Guidelines243- **Always work from within the package directory** when running tests244- **Mock all external dependencies** in unit tests245- **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 tests247- **Typecheck is critical before committing** - always run `pnpm typecheck`248- **When modifying pinia stores**, check for unused computed properties249- **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`.250251What 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 mocking254- 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 containers258 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).261262### Common Development Tasks263264When implementing features:2651. Define API types in `packages/@n8n/api-types`2662. Implement backend logic in `packages/cli` module, follow267 `@packages/cli/scripts/backend-module/backend-module-guide.md`2683. Add API endpoints via controllers2694. Update frontend in `packages/editor-ui` with i18n support2705. Write tests with proper mocks2716. Run `pnpm typecheck` to verify types272273## Design Principles274275### Security Must Not Degrade the Building Experience276277Security improvements, whether driven by enterprise requirements or internal278standards, must NEVER add friction to the common-case building experience. When279designing security-related features (defaults, behaviors, flows, error280handling), apply these checks:281282- **No friction for the common case:** A community builder's workflow should283 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 security287 are not trade-offs. They're both required. If a design forces a choice288 between them, the design needs more work.289290### Security Fix Hygiene291292**This is a public repository.** When working on security fixes, never expose293the attack vector or vulnerability type in any public-facing artifact. Attackers294monitor open-source repos for signals like branch names, commit messages, PR295titles, test descriptions, and Linear URLs.296297**Rules for security fixes:**298299- **Branch names:** Do NOT use the Linear-suggested branch name if it reveals300 the vulnerability. Rename to describe the fix neutrally301 (e.g. `node-1234-improve-request-handling`, not302 `node-1234-fix-ddos-vulnerability`).303- **Commit messages:** Describe what the code now does, not the threat it304 prevents (e.g. `fix: add payload size validation`, not305 `fix: prevent denial of service`).306- **Test descriptions:** Use neutral, functional language307 (e.g. `'should sanitize query parameters'`, not308 `'should prevent SQL injection'`).309- **Code comments:** Do not describe the attack scenario in comments.310- **Linear references:** Never include the URL slug311 (e.g. `.../N8N-1234/fix-ssrf-vulnerability`).312313### Customer Confidentiality314315**This is a public repository.** Never mention customer names in any316public-facing artifact — not all customers have agreed to be named publicly,317and naming them can reveal security-relevant details about their setup.318319This applies to PR titles and descriptions, branch names, commit messages,320code, code comments, test names and test data, and fixtures. When implementing321a customer request, describe the use case neutrally (e.g. "a customer with a322large multi-main setup", not the company name) and use generic placeholder323names (e.g. `Acme Corp`) in tests and examples.324325## Github Guidelines326- When creating a PR, use the conventions in327 `.github/pull_request_template.md` and328 `.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 PR331 description using `https://linear.app/n8n/issue/[TICKET-ID]`. Do not332 create a Linear ticket on your own — ask first.333- always link to the github issue if mentioned in the linear ticket.334
Also in n8n-io/n8n
Diff this repo’s formatsOne repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| n8n-io/n8n.agents/skills/AGENTS.md · 199k | AGENTS.md | setuparchagent-behaviour | 58/100 | 3 days ago | |
| n8n-io/n8n.github/CLAUDE.md · 199k | CLAUDE.md | styleagent-behaviour | 48/100 | 3 days ago | |
| n8n-io/n8npackages/@n8n/ai-workflow-builder.ee/AGENTS.md · 199k | AGENTS.md | agent-behaviour | 53/100 | 3 days ago | |
| n8n-io/n8npackages/@n8n/db/AGENTS.md · 199k | AGENTS.md | database | 39/100 | 3 days ago | |
| n8n-io/n8npackages/@n8n/engine/AGENTS.md · 199k | AGENTS.md | archdo-not | 59/100 | 3 days ago | |
| n8n-io/n8npackages/@n8n/instance-ai/CLAUDE.md · 199k | CLAUDE.md | buildteststyletesting-strategy+1 | 89/100 | 3 days ago | |
| n8n-io/n8npackages/cli/AGENTS.md · 199k | AGENTS.md | lint-format | 55/100 | 3 days ago | |
| n8n-io/n8npackages/cli/src/modules/n8n-packages/CLAUDE.md · 199k | CLAUDE.md | stylearchdependenciesmonorepo+2 | 69/100 | 3 days ago | |
| n8n-io/n8npackages/frontend/AGENTS.md · 199k | AGENTS.md | style | 40/100 | 3 days ago | |
| n8n-io/n8npackages/frontend/editor-ui/src/app/stores/workflowDocument/CLAUDE.md · 199k | CLAUDE.md | styleagent-behaviour | 58/100 | 3 days ago | |
| n8n-io/n8npackages/nodes-base/AGENTS.md · 199k | AGENTS.md | teststylearchtypes+5 | 89/100 | 3 days ago | |
| n8n-io/n8npackages/testing/playwright/AGENTS.md · 199k | AGENTS.md | setupbuildtestlint-format+8 | 96/100 | 3 days ago | |
| n8n-io/n8npackages/@n8n/agents/AGENTS.md · 199k | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| n8n-io/n8nscripts/instance-seeding/AGENTS.md · 199k | AGENTS.md | setupstyledo-not | 65/100 | 3 days ago |
Diff against .agents/skills/AGENTS.md Diff against .github/CLAUDE.md Diff against packages/@n8n/ai-workflow-builder.ee/AGENTS.md Diff against packages/@n8n/db/AGENTS.md Diff against packages/@n8n/engine/AGENTS.md Diff against packages/@n8n/instance-ai/CLAUDE.md Diff against packages/cli/AGENTS.md Diff against packages/cli/src/modules/n8n-packages/CLAUDE.md Diff against packages/frontend/AGENTS.md Diff against packages/frontend/editor-ui/src/app/stores/workflowDocument/CLAUDE.md Diff against packages/nodes-base/AGENTS.md Diff against packages/testing/playwright/AGENTS.md Diff against packages/@n8n/agents/AGENTS.md Diff against scripts/instance-seeding/AGENTS.md
Similar configs
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| TryGhost/Ghoste2e/AGENTS.md · 55k | AGENTS.md | setupteststylearch+2 | 100/100 | 3 days ago | |
| elastic/elasticsearchx-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/AGENTS.md · 78k | AGENTS.md | buildtestlint-formatstyle+2 | 100/100 | 3 days ago | |
| mui/material-uiAGENTS.md · 99k | AGENTS.md | setupbuildtestlint-format+9 | 100/100 | 3 days ago | |
| aaif-goose/gooseAGENTS.md · 52k | AGENTS.md | setupbuildtestlint-format+6 | 100/100 | 3 days ago | |
| code-yeongyu/oh-my-openagentpackages/web/AGENTS.md · 67k | AGENTS.md | setupbuildtestlint-format+6 | 100/100 | 2 days ago | |
| n8n-io/n8npackages/@n8n/agents/AGENTS.md · 199k | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70 | AGENTS.md | buildteststylearch+3 | 100/100 | 3 days ago | |
| elastic/elasticsearchx-pack/plugin/inference/AGENTS.md · 78k | AGENTS.md | buildtestlint-formatstyle+3 | 100/100 | 3 days ago |
