n8n-io/n8n:conventions
Quick reference for n8n patterns. Full docs /AGENTS.md
npx skills add https://github.com/n8n-io/n8n --skill n8n:conventions
📚 Full Documentation:
/AGENTS.md - Architecture, commands, workflows/packages/frontend/AGENTS.md - CSS variables, timingUse this skill when you need quick reminders on critical patterns.
TypeScript:
any → use unknownsatisfies over as (except tests)@n8n/api-typesError Handling:
import { UnexpectedError } from 'n8n-workflow';
throw new UnexpectedError('message', { extra: { context } });
// DON'T use deprecated ApplicationError
Frontend:
<script setup lang="ts">)/packages/frontend/AGENTS.md$t('key'))data-testid for E2E (single value, no spaces)Backend:
@n8n/di@n8n/configTesting:
pushd packages/cli && pnpm testDatabase:
GitHub Workflows:
permissions: block(usually contents: read); jobs needing more override at job level
Commands:
pnpm build > build.log 2>&1 # Always redirect
pnpm typecheck # Before commit
pnpm lint # Before commit
> Secrets: pnpm command lines may be recorded verbatim (opt-in dev metrics) —
> pass sensitive values via env vars, never inline on the command line.
| Package | Purpose |
|---------|---------|
| packages/cli | Backend API |
| packages/frontend/editor-ui | Vue 3 frontend |
| packages/@n8n/api-types | Shared types |
| packages/@n8n/db | TypeORM entities |
| packages/workflow | Core interfaces |
Pinia Store:
import { STORES } from '@n8n/stores';
export const useMyStore = defineStore(STORES.MY_STORE, () => {
const state = shallowRef([]);
return { state };
});
Vue Component:
<script setup lang="ts">
type Props = { title: string };
const props = defineProps<Props>();
</script>
Service:
import { Service } from '@n8n/di';
import { Config } from '@n8n/config';
@Service()
export class MyService {
constructor(private readonly config: Config) {}
}
📖 Need more details? Read /AGENTS.md and /packages/frontend/AGENTS.md
Take n8n-io/n8n:conventions from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.