Make the canon enforce itself.
Download the canon as a lint config in your project's language plus a set of rule files for your AI coding agent. Pick both below.
Pick your language
Pick the language of your project. The choice also sets the language used in every code sample and enforcement table on the rest of the site.
Enforcement
One config file per language, and two for PHP. Every rule has an inline comment naming the tenet it enforces and a link to the canon entry. Drop the files in your repo, install the dependencies and the rules run.
TypeScript · primary toolchain: ESLint (flat config)
Config file: eslint.config.mjs
// ============================================================================= // Prickles canon — TypeScript flat config (eslint.config.mjs) · v4.0.0 // Source of truth: https://prickles.org/implementation // // What this file enforces (19 of 51 tenets): // F1 F2 F3 F4 F5 F6 · Foundations // A1 A2 A3 A11 · Architecture (folder + import discipline) // S2 S3 S4 S5 · Style (caps, params, guards, inline-first) // T2 · Types (no escape hatches) // P5 · Shift-Left Quality (a11y safety in JSX) // TA1 TA2 · Tooling (linter as law, detect duplication) // TS5 · Testing (locate by structure — a11y roles) // // What this file CANNOT enforce — the canon carries these on other surfaces: …
Install steps
- Install the dependencies:
npm i -D "eslint@^9.38 || ^10" @eslint/compat@2 typescript-eslint@8 eslint-config-prettier@10 eslint-plugin-prettier@5 eslint-plugin-import-x@4 eslint-plugin-jsx-a11y-x@0.2 eslint-plugin-sonarjs@4 eslint-plugin-unicorn@65 jscpd@5 prettier@3
- Drop the config above into
eslint.config.mjsat your repo root. If the repo already has its own ESLint config, merge the two into one file: ESLint reads only one. If your framework has an ESLint plugin, keep it in that file or add it: the canon checks .vue, .svelte and .astro files through the plugin's parser. typescript-eslint 8 works with TypeScript up to 6.0, not 7. If your project has no TypeScript yet, or has TypeScript 7, install 6.0 before the lint tools: npm i -D typescript@~6.0 In an Angular workspace with no ESLint yet, add angular-eslint at your Angular major version before you merge, such as ng add angular-eslint@21 for Angular 21. Without the version, ng add installs the newest angular-eslint, which refuses an older workspace. In a Nuxt project, the eslint.config.mjs Nuxt sets up exports withNuxt(), which returns a promise of Nuxt's config rather than an array. Keep its import of withNuxt and add ...(await withNuxt()) to this pack's defineConfig array. When you merge, import each name once. SvelteKit's config, for one, imports defineConfig and includeIgnoreFile from eslint/config and prettier from eslint-config-prettier, as this pack's does: delete its copies of those imports and its own includeIgnoreFile(...) entry, since this pack's config already ignores what .gitignore ignores. If a subfolder has its own ESLint config, as monorepo packages often do, ESLint 10 checks that folder's files against that config alone, and so does ESLint 9 when you run it from the folder. Import this pack's eslint.config.mjs into that config and spread it into the array it exports. Then format it with your project's own Prettier settings:npx prettier --write "eslint.config.*" - Run the gate:
npx eslint . && npx jscpd . --ignore "**/node_modules/**,**/dist/**,**/build/**,**/coverage/**,**/.nuxt/**,**/.output/**" --format "typescript,tsx,javascript,jsx,vue,svelte,astro" --threshold 0 && npx prettier --check .
- Wire the gate into CI: a
qualityscript (or its build-tool equivalent) that fails the build on any rule violation.
AI rules
The rule files each agent reads, in the form that agent loads them. In the Recommended layout a short entry holds every tenet's rule and is always loaded, and the rest of each pillar loads when the work needs it. In the Strict layout the whole canon is always loaded. Together, the files hold every word of each tenet's entry on the canon.
The entry: every tenet's rule
Always loaded. Each tenet's ID, name and rule under its pillar's heading, which names the file that holds the rest of the pillar and says when to read it.
# Prickles canon v4.0.0: the 51 tenets Every tenet below binds any code you write, change, test or review in this repository. Each line is the tenet's rule. The file named in each heading holds the rest of that pillar's tenets and binds you exactly as this file does. Claude Code also loads the Foundations, Architecture, Style, Types & Schema, Testing and Patterns files by itself when you read or edit a file they match. IMPORTANT: reading a pillar's file is a precondition. Read it with your file-read tool before your first edit of the kind its heading names, and again after your context is compacted. ## Foundations (F1–F6). Before you write or change source code, read `.claude/rules/prickles-foundations.md`. - **F1 Single Responsibility Principle.** One obvious job per function, class, or module. When a second concern shows up in the same unit, peel it out so each piece has its own reason to change. - **F2 Intention-Revealing Names.** Use names that answer why this exists and what it does in the domain vocabulary. If the signature does not hold the meaning, rename. - **F3 Don't Repeat Yourself.** Give every fact, rule and decision in the system one home. If you find yourself typing the same logic, the same literal or the same shape twice, the second copy is a bug looking for a deadline. - **F4 Simplicity.** Build for the requirement at hand, not the speculative future. No line of code is cheaper than the one you didn't write, and speculative generality is debt with no creditor. - **F5 Self-Documenting Code.** Do not add comments that explain what the code does. If a reader needs help, improve names, extract functions, add types, or add tests until the code tells the story. - **F6 Encapsulation.** Hide the inside of your code. Callers should only call methods: never read or change fields directly. The method names are the contract. The body of the code is private and free to change. …
Foundations pillar
Loads by itself when Claude Code reads or edits a file that matches its paths.
--- paths: - "**/*.ts" - "**/*.tsx" - "**/*.mts" - "**/*.cts" - "**/*.vue" - "**/*.svelte" - "**/*.astro" --- Contents: F1 Single Responsibility Principle, F2 Intention-Revealing Names, F3 Don't Repeat Yourself, F4 Simplicity, F5 Self-Documenting Code, F6 Encapsulation. The rest of the Foundations tenets of the Prickles canon, v4.0.0. Each tenet's first paragraph is its rule, in the always-loaded Prickles entry. What follows binds you exactly as that rule does. …
Architecture pillar
Loads by itself when Claude Code reads or edits a file that matches its paths.
--- paths: - "**/*.ts" - "**/*.tsx" - "**/*.mts" - "**/*.cts" - "**/*.vue" - "**/*.svelte" - "**/*.astro" --- Contents: A1 Screaming Architecture, A2 Three-Tier Hoisting, A3 Stable Dependencies Principle, A4 Common Closure Principle, A5 Thin Handlers, A6 Bounded Contexts, A7 Coupling First, A8 Push to the Source of Truth, A9 Liskov Substitution Principle, A10 Interface Segregation Principle, A11 Dependency Inversion Principle. The rest of the Architecture tenets of the Prickles canon, v4.0.0. Each tenet's first paragraph is its rule, in the always-loaded Prickles entry. What follows binds you exactly as that rule does. …
Style pillar
Loads by itself when Claude Code reads or edits a file that matches its paths.
--- paths: - "**/*.ts" - "**/*.tsx" - "**/*.mts" - "**/*.cts" - "**/*.vue" - "**/*.svelte" - "**/*.astro" --- Contents: S2 Cyclomatic Caps, S3 Parameter Object, S4 Guard Clauses, S5 Inline-First. The rest of the Style tenets of the Prickles canon, v4.0.0. Each tenet's first paragraph is its rule, in the always-loaded Prickles entry. What follows binds you exactly as that rule does. …
Types & Schema pillar
Loads by itself when Claude Code reads or edits a file that matches its paths.
--- paths: - "**/*.ts" - "**/*.tsx" - "**/*.mts" - "**/*.cts" - "**/*.vue" - "**/*.svelte" - "**/*.astro" - "**/*.schema.json" - "**/*.sql" - "**/*.prisma" - "**/*.graphql" - "**/*.proto" …
Process pillar
A skill: the agent sees its description and reads the rest when the task needs it.
--- name: prickles-process description: "Use at the start of every task in this repository, and before declaring it done, committing or opening a pull request. Holds the rest of the Prickles Process tenets, P1 Test-First Development, P2 Spec-First Execution, P3 Definition of Done, P4 Continuous Quality Feedback, P5 Shift-Left Quality, P6 Leave it Better Than You Found it, P7 Short-Lived Branches with AI+Human Review, P8 Architecture Decision Records, which bind you exactly as the always-loaded Prickles entry does." --- Contents: P1 Test-First Development, P2 Spec-First Execution, P3 Definition of Done, P4 Continuous Quality Feedback, P5 Shift-Left Quality, P6 Leave it Better Than You Found it, P7 Short-Lived Branches with AI+Human Review, P8 Architecture Decision Records. The rest of the Process tenets of the Prickles canon, v4.0.0. Each tenet's first paragraph is its rule, in the always-loaded Prickles entry. What follows binds you exactly as that rule does. ## Prickles P1: Test-First Development In typed languages, the type is the first test. Define the signature, leave the body as a hole, let the compiler reject the inconsistencies the unit test would have caught, then write the test for the residue. Test the public contract rather than the internals. The unit's contract is the test's contract. Mock cascades through private collaborators are the smell, not the rule. …
Testing pillar
Loads by itself when Claude Code reads or edits a file that matches its paths.
--- paths: - "**/*.test.ts" - "**/*.test.tsx" - "**/*.spec.ts" - "**/*.spec.tsx" - "**/__tests__/**" - "**/*.feature" --- Contents: TS1 Living Documentation, TS2 Specification by Example, TS3 Parameterised Scenarios, TS4 Real-Dependency E2E, TS5 Structural Assertions, TS6 Behaviour Testing, TS7 Test Isolation, TS8 One Concept Per Test. The rest of the Testing tenets of the Prickles canon, v4.0.0. Each tenet's first paragraph is its rule, in the always-loaded Prickles entry. What follows binds you exactly as that rule does. …
AI Collaboration pillar
A skill: the agent sees its description and reads the rest when the task needs it.
--- name: prickles-ai description: "Use at the start of every task in this repository, before relying on an API, library or version you have not checked, and before declaring the work done. Holds the rest of the Prickles AI Collaboration tenets, AI1 The Intern Pattern, AI2 Persistent Brief, AI3 Working Context, AI4 Verifiable Specs, AI5 Verify the API, AI6 Self-Review Pass, which bind you exactly as the always-loaded Prickles entry does." --- Contents: AI1 The Intern Pattern, AI2 Persistent Brief, AI3 Working Context, AI4 Verifiable Specs, AI5 Verify the API, AI6 Self-Review Pass. The rest of the AI Collaboration tenets of the Prickles canon, v4.0.0. Each tenet's first paragraph is its rule, in the always-loaded Prickles entry. What follows binds you exactly as that rule does. ## Prickles AI1: The Intern Pattern Plan before you type. Use Plan Mode (Claude Code), spec-first prompts (Cursor), or a written outline checked into the PR description. The plan names files, decisions and the verification step. Approve in writing. The plan is a contract. Approval is the gate. No edits until a human (or the orchestrator agent) signs off. …
Tooling pillar
A skill: the agent sees its description and reads the rest when the task needs it.
--- name: prickles-tooling description: "Use before configuring or changing a linter, formatter, type checker, duplication check or CI gate in this repository, and whenever one of them fails. Holds the rest of the Prickles Tooling tenets, TA1 Linter as Law, TA2 Duplication Detection, which bind you exactly as the always-loaded Prickles entry does." --- Contents: TA1 Linter as Law, TA2 Duplication Detection. The rest of the Tooling tenets of the Prickles canon, v4.0.0. Each tenet's first paragraph is its rule, in the always-loaded Prickles entry. What follows binds you exactly as that rule does. ## Prickles TA1: Linter as Law Encode the limit before the violation. Line count, complexity, parameter count, file size, equality, return annotations, type-file naming, barrel files, import direction: all in `eslint.config.mjs` or its language equivalent. When the linter trips, fix the code. Never disable the rule inline. The disable comment is the bug. The rule is doing its job. …
Patterns pillar
Loads by itself when Claude Code reads or edits a file that matches its paths.
--- paths: - "**/*.ts" - "**/*.tsx" - "**/*.mts" - "**/*.cts" - "**/*.vue" - "**/*.svelte" - "**/*.astro" --- Contents: PT1 Patterns Are Vocabulary, PT3 Every Pattern Has a Failure Mode. The rest of the Patterns tenets of the Prickles canon, v4.0.0. Each tenet's first paragraph is its rule, in the always-loaded Prickles entry. What follows binds you exactly as that rule does. …
Review rules for Claude Code Review
Optional. Every tenet's rule, for Claude Code Review, which reads this file and not the rule files above.
# Prickles canon v4.0.0: review rules Report a change that breaks any tenet below as a review finding, and name the tenet's ID. Each line is that tenet's rule: the first paragraph of its entry in the Prickles canon. ## Foundations (F1–F6) - **F1 Single Responsibility Principle.** One obvious job per function, class, or module. When a second concern shows up in the same unit, peel it out so each piece has its own reason to change. - **F2 Intention-Revealing Names.** Use names that answer why this exists and what it does in the domain vocabulary. If the signature does not hold the meaning, rename. - **F3 Don't Repeat Yourself.** Give every fact, rule and decision in the system one home. If you find yourself typing the same logic, the same literal or the same shape twice, the second copy is a bug looking for a deadline. - **F4 Simplicity.** Build for the requirement at hand, not the speculative future. No line of code is cheaper than the one you didn't write, and speculative generality is debt with no creditor. - **F5 Self-Documenting Code.** Do not add comments that explain what the code does. If a reader needs help, improve names, extract functions, add types, or add tests until the code tells the story. - **F6 Encapsulation.** Hide the inside of your code. Callers should only call methods: never read or change fields directly. The method names are the contract. The body of the code is private and free to change. ## Architecture (A1–A11) …
Download
Pick a language, an agent and a layout. The pack holds the lint config for that language, the rule files that agent reads, and PRICKLES-SETUP.md with the install steps for that agent. This is version 4.0.0: see what changed in the changelog.
Step 1. Pick the language
Step 2. Pick your agent
Step 3. Pick the layout
Part of this pack is hidden
This pack includes .claude. Many file managers hide a file or folder whose name starts with a dot, so the unzipped pack can look as if something is missing. It is all there. To see it:
- Windows: in File Explorer, choose View → Show → Hidden items.
- macOS: in Finder, press Command + Shift + . (full stop).
- Linux: in most file managers, press Ctrl + H.