This file provides guidance to Claude Code (claude.ai/code) when working with code in the n8n repository.
n8n is a workflow automation platform written in TypeScript, using a monorepo structure managed by pnpm workspaces. It consists of a Node.js backend, Vue.js frontend, and extensible node-based workflow engine.
- Always use pnpm
- We use Linear as a ticket tracking system
- We use Posthog for feature flags
- When starting to work on a new ticket – create a new branch from fresh master with the name specified in Linear ticket
- When creating a new branch for a ticket in Linear - use the branch name suggested by linear
- Use mermaid diagrams in MD files when you need to visualise something
Use pnpm build to build all packages. ALWAYS redirect the output of the
build command to a file:
pnpm build > build.log 2>&1You can inspect the last few lines of the build log file to check for errors:
tail -n 20 build.logpnpm test- Run all testspnpm test:affected- Runs tests based on what has changed since the last commitpnpm dev:e2e- E2E tests in development mode
Running a particular test file requires going to the directory of that test
and running: pnpm test <test-file>.
When changing directories, use pushd to navigate into the directory and
popd to return to the previous directory. When in doubt, use pwd to check
your current directory.
pnpm lint- Lint codepnpm typecheck- Run type checks
Always run lint and typecheck before committing code to ensure quality.
Execute these commands from within the specific package directory you're
working on (e.g., cd packages/cli && pnpm lint). Run the full repository
check only when preparing the final PR. When your changes affect type
definitions, interfaces in @n8n/api-types, or cross-package dependencies,
build the system before running lint and typecheck.
Monorepo Structure: pnpm workspaces with Turbo build orchestration
The monorepo is organized into these key packages:
packages/@n8n/api-types: Shared TypeScript interfaces between frontend and backendpackages/workflow: Core workflow interfaces and typespackages/core: Workflow execution enginepackages/cli: Express server, REST API, and CLI commandspackages/editor-ui: Vue 3 frontend applicationpackages/@n8n/i18n: Internationalization for UI textpackages/nodes-base: Built-in nodes for integrationspackages/@n8n/nodes-langchain: AI/LangChain nodes@n8n/design-system: Vue component library for UI consistency@n8n/config: Centralized configuration management
- Frontend: Vue 3 + TypeScript + Vite + Pinia + Storybook UI Library
- Backend: Node.js + TypeScript + Express + TypeORM
- Testing: Jest (unit) + Playwright (E2E)
- Database: TypeORM with SQLite/PostgreSQL/MySQL support
- Code Quality: Biome (for formatting) + ESLint + lefthook git hooks
- Dependency Injection: Uses
@n8n/difor IoC container - Controller-Service-Repository: Backend follows MVC-like pattern
- Event-Driven: Internal event bus for decoupled communication
- Context-Based Execution: Different contexts for different node types
- State Management: Frontend uses Pinia stores
- Design System: Reusable components and design tokens are centralized in
@n8n/design-system, where all pure Vue components should be placed to ensure consistency and reusability
- Each package has isolated build configuration and can be developed independently
- Hot reload works across the full stack during development
- Node development uses dedicated
node-devCLI tool - Workflow tests are JSON-based for integration testing
- AI features have dedicated development workflow (
pnpm dev:ai)
- NEVER use
anytype - use proper types orunknown - Avoid type casting with
as- use type guards or type predicates instead - Define shared interfaces in
@n8n/api-typespackage for FE/BE communication
- Don't use
ApplicationErrorclass in CLI and nodes for throwing errors, because it's deprecated. UseUnexpectedError,OperationalErrororUserErrorinstead. - Import from appropriate error classes in each package
- All UI text must use i18n - add translations to
@n8n/i18npackage - Use CSS variables directly - never hardcode spacing as px values
- data-test-id must be a single value (no spaces or multiple values)
When implementing CSS, refer to @packages/frontend/CLAUDE.md for guidelines on CSS variables and styling conventions.
- Always work from within the package directory when running tests
- Mock all external dependencies in unit tests
- Confirm test cases with user before writing unit tests
- Typecheck is critical before committing - always run
pnpm typecheck - When modifying pinia stores, check for unused computed properties
What we use for testing and writing tests:
- For testing nodes and other backend components, we use Jest for unit tests. Examples can be found in
packages/nodes-base/nodes/**/*test*. - We use
nockfor server mocking - For frontend we use
vitest - For e2e tests we use
Playwrightandpnpm dev:e2e. The old Cypress tests are being migrated to Playwright, so please use Playwright for new tests.
When implementing features:
- Define API types in
packages/@n8n/api-types - Implement backend logic in
packages/climodule, follow@packages/cli/scripts/backend-module/backend-module.guide.md - Add API endpoints via controllers
- Update frontend in
packages/editor-uiwith i18n support - Write tests with proper mocks
- Run
pnpm typecheckto verify types
- When creating a PR, use the conventions in
.github/pull_request_template.mdand.github/pull_request_title_conventions.md. - Use
gh pr create --draftto create draft PRs. - Always reference the Linear ticket in the PR description,
use
https://linear.app/n8n/issue/[TICKET-ID] - always link to the github issue if mentioned in the linear ticket.