Changelog
What changed in the parts of Prickles you copy or download: the agent rules, the review-paste text, the config snippets, the lint configs and the download packs. Changes to the reading on each page are not listed here.
The canon gains a fifty-first tenet, P8 Architecture Decision Records, in the Process pillar. It asks for each architecturally significant decision to be recorded as the next numbered file in docs/adr/, in the pull request that makes the change. An accepted record is superseded, never rewritten. Every pack holds the new rule. Its rule line goes in each always-loaded entry and review file. The rest sits with the other Process tenets. No pack gains or loses a file. To upgrade from 3.0.0, copy the new pack's agent files over the old ones. In the lint configs only the banners change, so there is nothing to install again.
A new tenet: P8 Architecture Decision Records
- P8's rule line, the one every entry and review file loads, reads: “Record each architecturally significant decision as the next numbered file in
docs/adr/, in the same pull request as the change. Before changing code, read the accepted records that govern it. Never rewrite or delete an accepted record: supersede it.” - The rest of the rule says which decisions count and how a record is written: a
NNNN-title-with-dashes.mdname, a title line, aDate:line, then Status, Context, Decision and Consequences, with the options weighed in Context. A record stays Proposed until a person on the team accepts it, never the agent that drafted it. When a new record supersedes an old one, only the old record's status changes. - No pack adds a template, because each pack holds only the files its agent reads. The record's format is in the rule text instead. The rule also tells the agent to use a decision folder the repository already has, such as adr-tools'
doc/adror MADR'sdocs/decisions. - The tenet page cites 25 sources. Five of its studies rest on one sample: the 921 public GitHub repositories that held an ADR at the end of 2020. The page states that limit.
- The worked example, in all five languages, moves rescue alerts onto a queue. The Avoid pane leaves record 5 still saying to call the vet directly. The Prefer pane adds record 8, which supersedes it.
- Each language's enforcement table checks the records' headings, with markdownlint, PyMarkdown, JUnit or PHPUnit. The tables also catch a deleted record and put
docs/adr/under CODEOWNERS. In TypeScript and JavaScript a Danger rule fails a pull request that adds a dependency but neither adds nor cites a record. The packs do not run these checks.
Every pack
- The entry's title reads “the 51 tenets” and its Process heading reads “Process (P1–P8)”, with P8's rule line under it. P8's other paragraphs go in the Process skill or, in the Strict layout, the Process rule or whole-canon file.
REVIEW.mdand.cursor/BUGBOT.mdgain P8's rule line and stay under 10,000 characters.- P8 adds text to files every 3.0.0 pack already has. Every path is the same.
- OpenAI Codex, Strict layout: P8 joins the always-loaded core in
AGENTS.md. F4 and F5 move from that core toprickles/codex-canon-part-2.md, and T2, TS5 and TA1 move from part 2 toprickles/codex-canon-part-3.md. The pack still has four files, and its session-start hook is unchanged. Its setup guide now gives the roomAGENTS.mdleaves for your own lines as about 5 KB, up from about 4 KB. - Windsurf and Devin, Strict layout: P8 joins P3 to P7 in
.devin/rules/prickles-05-process.md.AGENTS.mdkeeps the same 14 tenets. - Other AGENTS.md agents, Strict layout: the whole canon in
AGENTS.mdis now about 38 KB, up from about 37 KB. - Every lint config's banner gives the new version. The five main configs count 51 tenets and list P8 among the Process gates. The TypeScript banner said it enforced 20 tenets but listed 19. It now says 19 of 51.
- To upgrade a file you merged the canon into, such as
AGENTS.md, replace the canon's text inside it. From 2.x, follow the setup guide's upgrade step, which names every file to delete first.
Tenets that point to P8
- F5, TS1, AI2 and A7 now list P8 as a related tenet. F5 and TS1 also link to it where each reply mentions an ADR.
- TS1 no longer calls an ADR signed, since no source describes one that way. The line now reads “numbered, dated and superseded rather than edited”.
- AI2's reply no longer calls the brief the only place where a team decides once. The brief holds the team's conventions. P8's records hold its decisions.
- These four tenets show as revised on 23 October 2026. None of their agent rules, review-paste text or config snippets changed, so each keeps its version. The other 46 tenets keep their revision date of 13 October 2026.
Every pack now loads a short entry with every tenet's rule and leaves the rest of each pillar to load when the work needs it: by file pattern where the agent supports one, and as a skill where it doesn't. Nothing is removed, and the Strict layout keeps 2.0's whole canon in every session. Eighteen rule lines now say what to do, every pack checks magic numbers and the setup guides are corrected against each agent's documentation. Every pack also fails on any comment but a tool directive. To upgrade, delete the files the new setup guide lists, copy in the new pack and run the install command again.
A short entry, and the rest when the work needs it
- Every pack's default layout, Recommended, gives the agent an entry of about 11 KB that it always loads: each tenet's ID, name and rule, under nine pillar headings. Each heading names the file that holds the rest of that pillar and says when to read it, as a plain path, never an
@import, which some agents would load at once. - Foundations, Architecture, Style, Types & Schema, Testing and Patterns load by file pattern wherever the agent supports one, with patterns for your language. Testing loads on test files only. Process, AI Collaboration and Tooling are Agent Skills, which the agent reads when the task needs them, and an agent with no file patterns gets every pillar as a skill.
- Nothing is removed. The entry and the pillar files together hold every word of every tenet's rule, and a test rebuilds each rule from them byte for byte, for every agent, language and layout. Other tests check that every frontmatter block parses, that each entry stays under 12,000 bytes and 150 lines, that every path the entry names is in the pack and that only the entry loads in every session.
- A skill is the same file in every pack that writes it, so a second pack replaces it rather than adding a copy.
- The Strict layout keeps 2.0's packs, with the whole canon loaded in every session. Pick it in step 3 of the download: its link adds
?layout=strictand its file name ends in-strict. The download link for the default layout is unchanged. - The rules preview on the implementation page shows the layout and language you pick.
Each agent's pack
- Claude Code:
.claude/rules/prickles-canon.mdis the entry, the six code pillars are.claude/rulesfiles withpaths:and the other three are skills in.claude/skills. Use Claude Code 2.1.293 or later. - Cursor: the entry is
.cursor/rules/prickles.mdcwithalwaysApply: true, the code pillars are.mdcrules with globs and the others are skills in.agents/skills. - GitHub Copilot: the entry is
.github/copilot-instructions.md, the code pillars are.github/instructionsfiles withapplyToand the others are skills in.github/skills. - OpenAI Codex:
AGENTS.md, with Code Review Rules, is the entry and every pillar is a skill in.agents/skills. The session-start hook leaves the default pack, so Codex no longer needs you to trust a hook. The Strict layout keeps it. - Gemini CLI and Code Assist:
GEMINI.mdand nine skills in.agents/skills. - Google Antigravity: an always-on entry in
.agents/rules, glob rules for the code pillars and skills for the rest. - Windsurf and Devin:
AGENTS.mdis the entry, under 12,000 characters, the code pillars are glob rules in.devin/rulesand the rest are skills. - Cline:
.clinerules/prickles.mdand nine skills, because Cline's code does not act on thepaths:conditions its documentation describes. - JetBrains Junie:
.junie/rules/prickles.mdand nine skills. AI Assistant's chat gets its own entry and pillar rules in.aiassistant/rules. - Aider:
.aider.conf.ymllists only the entry,prickles/canon.md. The pillars are skills that Aider offers to add when the model asks for one. - Other AGENTS.md agents:
AGENTS.mdand nine skills in.agents/skills. Kiro reads skills only from.kiro/skills, so the pack puts the same skills there, and no other agent it serves reads that folder. - An optional
REVIEW.mdgives Claude Code Review every tenet's rule, and an optional.cursor/BUGBOT.mddoes the same for Cursor's Bugbot, in both layouts. Neither reviewer reads the rule files. Keep the file if you use the reviewer and delete it if you don't.
Rule lines that say what to do
- The first paragraph of an agent rule is now the line every entry always loads, so in eighteen tenets it opens with what to do: A1, A3, A4, A5, A6, F3, F4, P3, P7, T4, TS3, TS4, TS7, TA1, AI2, AI4, AI5 and AI6. The rest of each rule is unchanged.
- AI4 Verifiable Specs and AI5 Verify the API now state a rule. AI4 asks for specs written as executable contracts the agent can run and grade itself against, and AI5 for a check of the current docs or source before any call to a framework, library or SDK.
- Every tenet's version moves up one and shows as revised on 13 October 2026.
Setup guides
- Each guide describes both layouts and how to switch. Its check has two parts: ask the agent to quote a rule without reading a file, then ask for a test and see the detail file or skill open.
- Facts that changed since September are corrected against each agent's documentation of 11 October 2026. Claude Code needs 2.1.293 or later for path-scoped rules to load on every edit and file read, and its managed-only setting leaves them on, where 2.0's guide said it switched them off. Codex's documentation moved to learn.chatgpt.com, and its code review reports only P0 and P1 findings. Copilot's coding agent is now the cloud agent, and Eclipse's setting is now called Enable workspace instructions. Antigravity allows 24,000 bytes a rule, Devin cloud reads the first 16 KiB of
AGENTS.mdand Cline also reads.cline/rules. - The upgrade step names every file that 2.0 and both layouts of 3.0.0 write, so nothing from an older pack stays behind, and it keeps any file you merged your own text into.
- Each guide ends with what was checked. Its facts follow the agent's documentation, and nothing about the Recommended layout has been measured in that agent: Prickles runs its adherence test on Claude Code only.
Magic numbers in every pack
- TypeScript runs
@typescript-eslint/no-magic-numberswith the base rule off, and JavaScript runsno-magic-numbers. Both let -1, 0 and 1, array indexes and default values through and ask for aconst. TypeScript also lets enums, numeric literal types, type indexes and readonly class properties through. - Python sets out Ruff's
PLR2004, which thePLRselection already ran. It checks the numbers in comparisons. - Java runs PMD's
AvoidLiteralsInIfConditionwith -1, 0 and 1 allowed, and names the same values for Checkstyle'sMagicNumber. - PHP adds phpmnd to the install and run commands. It ignores -1 as well as the 0 and 1 it always ignores, and skips default parameters and arrays.
No comments in code
- Every pack fails on any comment, because F5 asks the code to explain itself. Tool directives still pass, because they instruct a tool rather than explain the code:
eslint-disableandeslint-enable,@ts-expect-errorwith its description,prettier-ignore, triple-slash references and the#!line in TypeScript and JavaScript;# type: ignore,# noqaand# pylint: disableorenablein Python;// NOPMDandCHECKSTYLE:OFForONin Java; andphpcs:ignore,disableandenable,@phpstan-ignore,@psalm-suppressand PHPMD's@SuppressWarningsin PHP. - Every pack also lets through SPDX licence lines,
SPDX-License-Identifier:andSPDX-FileCopyrightText:, and generated-file banners,@generatedorCode generated … DO NOT EDITas Go and protoc write them, because F5 counts them as metadata rather than comments. - The TypeScript and JavaScript configs carry a short rule,
prickles/no-comments, because ESLint has none built in. The JavaScript pack lets through JSDoc blocks that hold type tags alone, such as/** @param {string} name */, whileallowTypeDocBlocksis on. The TypeScript pack, whose types live in the code, fails them. So that such a block can pass, the JavaScript pack dropsmultiline-comment-style, whose starred blocks contradicted unicorn'sno-asterisk-prefix-in-documentation-comments, and sets unicorn'ssingle-line-block-comment-styleto single-line, so a one-tag block stays on one line. - In Python, a docstring counts as a comment. The pack ships
prickles_no_comments.py, a Pylint checker thatpyproject.tomlloads, so keep it besidepyproject.tomland run Pylint from that folder, as the run command does. - Java runs PMD's
CommentContent, which fails every comment, Javadoc included. - The PHP pack ships
phpcs/Prickles/Sniffs/Commenting/NoCommentsSniff.php, whichphpcs.xmlloads. Docblocks of type tags alone, such as/** @param list<int> $ids */, pass whileallowTypeDocBlocksis on, because Psalm and PHPStan read generics from them. - The Java ruleset's TA1 note asks for a suppression's reason in the directive itself, as in
// NOPMD - reason, and treats one without a reason as a defect. - The worked examples on every tenet page follow the same rule. A pane's Before or After line now sits in a caption above the code, and a pane that spans several files gives each file its own heading, with any note beside it. Given, When and Then comments became test names, a feature file or a test beside the code, and the steps that narrated a function went. Every Prefer pane passes its pack's comment rule, holding nothing but tool directives with their reasons and, in JavaScript and PHP, type-only docblocks. The Avoid panes keep the comments they hold up as the problem.
- The rules that asked for a comment are gone: PMD's
UncommentedEmptyMethodBodyand PHP_CodeSniffer'sSquiz.Commenting.LongConditionClosingComment.
Lint configs
- The Java ruleset lets a method take 3 parameters. PMD reports at or above the value it is given, so
ExcessiveParameterListmoves from 3 to 4. - Pylint caps a class at 7 public methods. 2.0.1 set the 7 only for Ruff, whose check for it runs only in preview, so Pylint silently kept its default of 20.
- The Java ruleset gives the canon's values for the Checkstyle checks it pairs with, where 2.0.1 left Checkstyle's defaults of 7 parameters, 150 lines and 30 statements.
- The duplication check ignores Nuxt's
.nuxtand.output. - The TypeScript pack reports an
ifwith noelsewhose only statement is areturnfollowed by anotherreturn, as unicorn 77'sprefer-ternarydoes in the JavaScript pack. Twono-restricted-syntaxselectors sit beside the TypeScript pack's unicorn 65, the last version that supports ESLint 9. The two versions still differ elsewhere: 77 also reports aletthat anifthen reassigns, and 65 also reports anifandelsethat each throw. - Pylint no longer reports a class with fewer than two public methods,
too-few-public-methods(R0903), so a value object or a class with one public method passes. - Pylint no longer asks for a docstring on a module, class or function (C0114, C0115 and C0116). F5 asks the code to explain itself, so the pack does not ask for comments.
- PHP_CodeSniffer no longer asks for an underscore at the start of a private property or method name. It reports one on any property or method, as PSR-12 asks, and reports it as an error, so
phpcs -n, which hides warnings, still shows it. Squiz's naming checks, such as camelCase, still run without theirPrivateNoUnderscorecodes. - PHPMD leaves out
StaticAccess, so a call such asAssert::assertSame()passes, andMissingImportignores classes in the global namespace, such asDateTimeImmutable. A namespaced class still needs ausestatement. - The Java pack's setup pins PMD 7.28.0, the version the pack is tested against. maven-pmd-plugin 3.28.0 runs PMD 7.17.0 unless told otherwise, so the Maven step gives the plugin
pmd-core,pmd-java,pmd-javascriptandpmd-jspat 7.28.0, and the Gradle step setstoolVersion.
Setup steps for frameworks
- typescript-eslint 8 works with TypeScript up to 6.0, so in a project with TypeScript 7, or none, the guide installs
typescript@~6.0first. - In an Angular workspace with no ESLint yet, add angular-eslint at your Angular version, such as
ng add angular-eslint@21. - In a Nuxt project, keep the import of
withNuxtand add...(await withNuxt())to the pack'sdefineConfigarray. - When you merge into SvelteKit's config, import each name once.
Config snippets on each tenet page
- Every snippet matches the downloads, including sonarjs's cognitive complexity cap of 15, and a test now holds every threshold a page shows to the download's.
- S2's caps of 6 become 3, or 4 for PMD, which reports a method at the level it is given. Its worked examples show v(G) 4 and 11 lines, or 7 in Python.
- S3's PHPMD setting is now
maximum3. - The ESLint snippets report errors, not warnings.
- S2's and AI4's worked examples return a ternary where they returned from an
if, in all five languages, and T3's JavaScript, Python and PHP type guards return one boolean, so the TypeScript and JavaScript examples pass the packs'prefer-ternary. - F5's rule lists and config snippets show each pack's comment ban, in place of rules that asked for docstrings, Javadoc and doc comments. P2's Java snippet no longer asks for a comment on every class, and S3 keeps a parameter-list justification in the lint suppression rather than a code comment.
The TypeScript pack lets npm keep ESLint 9 where your lint setup needs it, as Next.js's does, and the JavaScript pack installs ESLint 10 in projects whose lint setup holds ESLint at 9, where 2.0's could not. Both work beside the ESLint config your framework set up, check the code in Vue, Svelte and Astro component files, and pass the checks they ask you to run. The duplication check fails on any clone, a new phpmd.xml holds PHP to the canon's size limits, and the Python and PHP guides say which config file each tool reads, so the pack's file is not ignored, and does not replace yours, without a word. To upgrade from 2.0, copy in the new lint configs, run the install command again and use the new run command, which the setup guide now gives.
ESLint versions
- The TypeScript install command accepts ESLint 9.38 or later as well as 10, so npm can keep ESLint 9 where the project's lint packages need it, as in a Next.js project. Otherwise it installs ESLint 10, even over an ESLint 9 the project already has. 2.0 always installed ESLint 10, which clashes with lint setups that stop at ESLint 9: eslint-plugin-react, eslint-plugin-import and eslint-plugin-jsx-a11y declare ESLint 9 at most, and Next.js's
eslint-config-nextand Expo'seslint-config-expodepend on them. - The TypeScript pack pins eslint-plugin-unicorn to 65, the last version that supports ESLint 9, and its config uses that version's name for the
for…ofrule,unicorn/no-array-for-each. Unicorn 76, which 2.0 installed, only hasunicorn/no-for-each, so run the install command again when you copy in the new config. - The JavaScript pack installs ESLint 10 and eslint-plugin-unicorn 77, whose recommended set has 338 rules, where 76's had 315. It keeps
@eslint/jsat 9: version 10 stops npm installing anything in a project whose lint setup holds ESLint at 9, so 2.0's JavaScript install command failed in a Next.js project. There, npm now warns that eslint-plugin-react, eslint-plugin-import and eslint-plugin-jsx-a11y expect ESLint 9, and their rules still run on ESLint 10.@eslint/js9's recommended set lacks three rules that 10 adds:no-unassigned-vars,no-useless-assignmentandpreserve-caught-error.
Lint configs beside a framework's own
- The setup guide has a step to keep one ESLint config, and the implementation page says the same. ESLint reads only the first of
eslint.config.js,.mjs,.cjs,.ts,.mtsand.ctsthat it finds, so in 2.0 the pack'seslint.config.mjswent unread beside theeslint.config.jsthat Angular and SvelteKit set up, and took the place of theeslint.config.tsthat Vue sets up. - The configs set their parser and presets for
.jsand.tsfiles and the extensions that go with them, such as.tsxand.mjs, so a framework's own parser keeps the files it reads. In 2.0 the TypeScript config set its parser for every file, which broke the.vuefiles Vue lints and the.htmltemplates Angular lints. - The canon's rules also check the code in
.vue,.svelteand.astrofiles, scripts included, wherever your framework's ESLint plugin reads them, and leave them alone where nothing does. A new step in the setup guide asks you to keep that plugin, or add it. Component files may be named in PascalCase, as Vue, Svelte and Astro name them. The 150-line file cap does not apply to them, because it would count markup and styles. Prettier checks their formatting throughnpx prettier --check ., which uses your Prettier plugins, rather than through ESLint. - The TypeScript, JavaScript and Python guides have a step for a subfolder with its own config, as monorepo packages often have. ESLint 10 and Ruff check each file against the config nearest to it, so in 2.0 such a folder skipped the canon. The step says how to bring the canon into that config.
- Both configs ignore whatever your
.gitignoreignores, through@eslint/compat, so the files a framework generates, such as.next,.nuxt,.svelte-kitor.angular, are not linted. They also ignoredist,buildandcoverage, as the TypeScript config already did.
The config files themselves
- The A2 folder rule follows the tenet's wording:
lib/genericimports only fromlib/generic, andlib/productonly fromlib/genericandlib/product. In 2.0 it only stopped imports fromsrc/componentsandsrc/app, so it missed app code kept in folders such assrc/routesorsrc/pages. - The JavaScript config wraps its entries in
defineConfig, as the TypeScript config does, so rules that flag an anonymous default export, such as eslint-plugin-import's, accept it. - The canon's rules skip files named
*.config.*, such aseslint.config.mjsandvite.config.ts, and both configs come formatted as Prettier formats them by default. In 2.0,eslint.config.mjsfailed thenpx eslint .andnpx prettier --check .it asked you to run. - A new step formats the config with your project's own Prettier settings,
npx prettier --write "eslint.config.*", for projects whose framework sets them, as Angular and Vue do. - The JavaScript config declares the browser and Node.js globals, through the
globalspackage the install command now adds. In 2.0, a project with no ESLint config of its own sawconsole,processandwindowreported as undefined. - The Java ruleset lets a method reach the canon's caps of 3, as the other packs do: a cyclomatic complexity of 3 and three nested
ifstatements. PMD reports a method at the level it is given, so it now gets 4 forCyclomaticComplexityandAvoidDeeplyNestedIfStmts. With 2.0's 3, both rules failed a method at 3.
The run commands
- The setup guide in every download gives the run command, after the install steps. In 2.0 it was only on the implementation page.
- The duplication check in the TypeScript, JavaScript and Python run commands fails on any clone, as TA2 asks. In 2.0, jscpd listed the clones it found and still passed.
- The TypeScript and JavaScript duplication check reads script and component files across the repository, and skips
node_modules,dist,buildandcoverage, along with whatever.gitignoreignores in a git repository. 2.0 checked onlysrc, and stopped with an error in a project with nosrcfolder, such as a Nuxt project, which keeps its code inapp. - The Python duplication check reads only Python files, and skips
node_modules,.venvandvenv. 2.0's read every file in the repository,node_modulesincluded. - The TypeScript, JavaScript and Python install commands ask for jscpd 5. Every jscpd 4 release, which 2.0's TypeScript and JavaScript commands installed, depends on a package with a high-severity security advisory and no fixed version, so
npm auditreported it in any project that installed it. 2.0's Python command named no version. - Pylint checks the Python files git does not track yet, as well as the ones it does. 2.0 gave it only committed files, so it skipped new ones, and in a repository with no committed Python files it stopped with "No files to lint".
Python and PHP packs
- The Python guide has a step to keep one Ruff config and another to keep one Pylint config. Ruff reads only the first of
.ruff.toml,ruff.tomlandpyproject.tomlthat it finds, so the pack'spyproject.tomlwent unread beside aruff.toml. Pylint reads its settings from one file only, and looks atpylintrcand.pylintrcbeforepyproject.toml, and atsetup.cfgandtox.iniafter it. So the pack went unread beside a.pylintrc, and took the place of Pylint settings kept insetup.cfgortox.ini. - The PHP guide has a step to keep one PHP_CodeSniffer config. PHP_CodeSniffer reads only the first of
.phpcs.xml,phpcs.xml,.phpcs.xml.distandphpcs.xml.distthat it finds, so the pack'sphpcs.xmlwent unread beside a.phpcs.xml, and took the place of aphpcs.xml.dist, the file Symfony's recipe sets up. - The PHP pack ships
phpmd.xml, with the canon's limits of 15 lines a method, 150 lines a class and 3 parameters. 2.0's run command left PHPMD at its own limits of 100 lines, 1,000 lines and 10 parameters, and passed it arguments that PHPMD 3 warns about on every run. The run command now uses PHPMD 3'svendor/bin/phpmd analyze, which readsphpmd.xml, and the install command asks for PHPMD 3. A step keeps one PHPMD config, as PHPMD reads only the first of fifteen file names that it finds, starting withphpmd.yml. - A step in the PHP guide names your own folders when your code is not all in
src. 2.0 assumedsrc, so PHP_CodeSniffer and PHPMD stopped with an error in a Laravel project, which keeps its code inapp, and checked onlysrcin a project that also haslib. - The PHP install command no longer runs
vendor/bin/psalm --init. It stopped with an error where apsalm.xmlexisted, and beside apsalm.xml.distit wrote apsalm.xmlthat Psalm reads instead. A separate step, for a repository with no Psalm config, runsvendor/bin/psalm --init src 1, which sets error level 1, asphpcs.xmlsays. In 2.0, Psalm chose a level from your code.
Config snippets on each tenet page
- A2's TypeScript and JavaScript example uses the same folder rule as the lint configs, and no longer stops
src/componentsimportingsrc/app, which the tenet does not ask for. - A8's TypeScript row names
cacheComponents, which turns on Partial Prerendering in Next.js 16, where 2.0 namedexperimental.ppr, which Next.js 16 removed. - S4's Java example sets PMD's
problemDepthto 4, so three nestedifstatements pass, as the tenet allows. PMD reports anifat the depth it is given, so 2.0's 3 reported three levels. - A2, A8 and S4 move up to version 1.2 and show as revised on 11 October 2026.
The download gives each agent exactly the files it reads, the lint configs install and run on ESLint 10, and three rules ask for something different. If you installed 1.0, delete its files and install 2.0.
Rules that now ask for something different
- F3 Don't Repeat Yourself now says to extract duplicated knowledge on the second occurrence inside one bounded context, instead of waiting for the third. It also cites Bounded Contexts as A6, where 1.0 said A8.
- TS3 Parameterised Scenarios makes the second near-duplicate test the trigger to parameterise, where 1.0 waited for the third.
- S3 Parameter Object no longer exempts keyword arguments from the three-parameter cap, because Ruff's
PLR0913counts keyword-only arguments. Object destructuring counts as one parameter.
Other changes to the rules
- F4 and F6 are headed by their canon titles, Simplicity and Encapsulation.
- T1 no longer opens with a Canon link line, and A6 and T4 no longer contain the HTML entity
'. - Every tenet's version moves up one and shows as revised on 24 September 2026.
The download
- Choose from eleven agents. Each pack holds the lint config for your language, only the rule files that agent reads, and
PRICKLES-SETUP.mdwith its install steps, what to merge, how to keep exactly one copy and how to check the rules loaded. PRICKLES-SETUP.mdreplaces theREADME.mdof 1.0, which overwrote your own README when you unzipped the pack.- Claude Code:
.claude/rules/prickles-<pillar>.md, one per pillar. - Cursor:
.cursor/rules/prickles-<pillar>.mdcopening withalwaysApply: true. In 1.0 the frontmatter sat inside the file and switched the rules off. - GitHub Copilot: the whole canon in
.github/copilot-instructions.md. 1.0 wrote files to.github/instructionsthat Copilot never reads. - OpenAI Codex:
AGENTS.mdwith the 36 highest-ranked tenets under Code Review Rules, inside Codex's 32 KiB limit, two part files with the rest, and a session-start hook in.codex/hooks.jsonthat loads them. - Gemini CLI and Code Assist: the whole canon in
GEMINI.md. - Google Antigravity: one always-on rule per pillar in
.agents/rules. - Windsurf and Devin:
AGENTS.mdwith the 14 highest-ranked tenets, inside Cascade's 12,000-character limit, and always-on rules in.devin/rulesfor the rest. - Cline:
.clinerules/prickles-0N-<pillar>.md. 1.0 wrote a file whose name was an instruction,.clinerules (append ### Prickles · …). - JetBrains Junie:
.junie/rules/prickles.md, and.aiassistant/rules/prickles.mdfor AI Assistant's chat. - Aider:
prickles/canon.mdand a.aider.conf.ymlthat lists it. - Other AGENTS.md agents: the whole canon in
AGENTS.md. 1.0 wrote a file namedAGENTS.md (append ## Prickles · …). - The agents with a size limit read the tenets in one ranked order: the AI Collaboration tenets first, then the tenets no lint rule can check, and last the caps the lint config enforces.
- The rule files no longer carry an HTML comment above each tenet.
Agent rules on each tenet page
- The Cursor rule opens with
alwaysApply: true. In 1.0 its frontmatter was not valid YAML and setalwaysApply: false. - The Copilot rule goes in
.github/copilot-instructions.md, and the Cline rule in.clinerules/<tenet>.md. - Each agent has its own tab, so each shows its own file path.
Lint configs
- The TypeScript and JavaScript configs run on ESLint 10. eslint-plugin-import and eslint-plugin-jsx-a11y, which do not support it, are replaced by eslint-plugin-import-x and eslint-plugin-jsx-a11y-x, so their rules are now
import-x/…andjsx-a11y-x/…. The install commands install every package the configs import and pin each major version. - The TypeScript config no longer assumes Next.js or React. It follows
.jsimport specifiers and tsconfigpaths, soimport-x/no-cyclefinds cycles through them. import-x/no-restricted-pathsenforces the canon's A2 tiers, where 1.0 set it with no zones and it reported nothing. The emptyno-restricted-importsis gone, and A6 is listed as the one your project must configure.- The JavaScript config parses JSX.
- Java: the PMD ruleset loads in PMD 7. 1.0 held a comment PMD rejects.
- PHP: phpcs reports errors, not warnings, for complexity and nesting. Duplication runs through PMD CPD, because phpcpd is archived. The run command uses PHPMD's built-in rule sets, and the install step creates Psalm's config.
- Every comment names its tenet by the canon title.
Config snippets on each tenet page
- Every ESLint and pyproject snippet now loads in its tool.
- Rules renamed upstream carry their new names: PMD's
NcssCount,UnnecessaryImportandClassNamingConventions, and eslint-plugin-unicorn'sno-for-each. - Two rows cited rules that do not exist. S4's PHP row now names
Generic.Metrics.NestingLevel, and a Ruff row namesPT003. - The PHPUnit snippets target PHPUnit 13.
The first release of the canon.
What it held
- Fifty tenets in nine pillars, each with an agent rule and review-paste text.
- Lint config snippets for TypeScript, JavaScript, Python, Java and PHP on each tenet.
- A download of combined lint configs and rule files for five agent surfaces.