Skip to content

Agent instructions in generated projects

ai-rulez is the opt-in single source for agent instructions, with the prose in shared macros

Id: e1545d12-ac20-426b-9cd5-519e80a56b5f Type: decision Status: superseded Superseded by: 249600a2-79c3-49b9-b4b5-277ccc245d1b Evidence: confirmed Source: ADR-035 (docs/adr/035-ai-rulez-as-the-agent-instruction-source.md), §1 and §5; issue #309 Revisit when: a host stops reading its generated file, ai-rulez leaves PyPI, or a sixth host is expected to open PRs See: repo-setup.md#a-resume-driven-repo-setup-skill-reads-check-blocks-from-the-setup-doc-no-separate-manifest — 68ac4665-dcde-456b-aef7-2faaf6fe51f4 — as of 2026-10-11 See: template-testing.md#collection-literals-are-rendered-through-one-shared-macro — 47b21a49-5fc4-46b8-b450-7d9f3225706c — as of 2026-10-11

include_ai_rulez (default off, full preset) with an ai_rulez_presets multiselect renders .ai-rulez/ sources from which ai-rulez generates each host's native instruction files and skill copies. With the toggle off, the hand-written AGENTS.md and the Claude-only skills render. The section prose lives once in _macros.jinja; both the hand-written file and the rule sources call the same macros. The pin lives in its own agents dependency group, exact, Renovate-tracked through the native uv manager.

Reason: the generated project's branch-name check already whitelists five agent prefixes, but only Claude received the repo-setup skill and only two hosts received instructions; hand-writing five formats is the duplication the template exists to remove; four of the five agents got nothing, not even .github/copilot-instructions.md, which GitHub's Copilot coding agent and PR review read server-side. ai-rulez (MIT, Go) authors rules, context, skills, agents and commands once and generates tool-native output for 20 hosts. It ships on PyPI (no Node) and has the cobo shape — sources in, committed output out, a check that proves they agree. A second hand-maintained copy of the paragraphs would recreate inside the template the drift it removes downstream. Its own group because dev includes style wholesale and only two callers invoke the tool; upstream's pre-commit hooks would add a second rev pin. The exact pin matters because the PyPI launcher downloads a Go binary and proceeds with a warning if the checksum file cannot be fetched.

Rejected alternative: hand-written per-host files — five dialects drifting.

Generated host files are build output; the template renders none of them

Id: e827d3fc-e3f6-4852-b2e3-d56180eac949 Type: decision Status: superseded Superseded by: 249600a2-79c3-49b9-b4b5-277ccc245d1b Evidence: confirmed Source: ADR-035 §2 and §8 (docs/adr/035-ai-rulez-as-the-agent-instruction-source.md) Revisit when: ai-rulez and copier produce identical bytes for the same content, or the template gains a post-render step See: agent-instructions.md#ai-rulez-is-the-opt-in-single-source-for-agent-instructions-with-the-prose-in-shared-macros — e1545d12-ac20-426b-9cd5-519e80a56b5f — as of 2026-10-11 See: template-updates.md#copieryml-defines-no-_tasks — 86130379-1660-4992-8aba-8b6cd7b4a9f7 — as of 2026-10-11

The template renders .ai-rulez/ and stops. AGENTS.md, the Copilot instructions and the per-host skill copies are written by the adopter's first ai-rulez generate and committed from then on. Turning the toggle on via update leaves a project with no instruction files until the generator runs (the after-update message names the two commands, uv lock then the generator; CI is red until the output is committed). On a fresh copy the generator is an explicit numbered step of the after-copy message, beside git init and uv sync. Turning it off requires running ai-rulez's clean command before the update, while the sources it reads still exist, because the host files are not copier-managed and would otherwise stay committed and stale. Clean reads .ai-rulez/.generated-manifest.json, which the generator writes into the source tree; it is committed, and the prek ^\.ai-rulez/ gate and the documentation labeler glob cover it. Clean is run with ai-rulez's keep-gitignore flag as belt-and-braces: gitignore = false leaves no ai-rulez block to remove and the .gitignore is cobo-sealed.

Reason: copier's renderer and ai-rulez's renderer produce different bytes for the same content (ai-rulez composes its own headings and stamps a provenance header with a content hash), so rendering both would diff on first generate and every copier update would re-render on top of generated files — churn on files the adopter never touched. As build output they sit outside the 3-way merge, which then covers only the small per-rule sources. Neither direction is automatic because the template has no tasks. Dropping the toggle from full was rejected: full means every toggle, and a preset that quietly omits one is a worse surprise than a loud one.

Rejected alternative: render the generated files as well — the churn above.

Rejected alternative: mark the generated host files linguist-generated in .gitattributes — the path set differs per host and is ai-rulez's contract, so re-encoding it would be a second copy that rots. The files carry their own DO-NOT-EDIT banner instead.

No builtin ai-rulez domains, and ai-rulez never touches .gitignore

Id: e9823c4a-891f-4344-8d64-029dd8d31138 Type: decision Type: constraint Status: superseded Superseded by: 249600a2-79c3-49b9-b4b5-277ccc245d1b Evidence: confirmed Source: ADR-035 §3–4 (docs/adr/035-ai-rulez-as-the-agent-instruction-source.md) Revisit when: a builtin domain stops contradicting a gate the project enforces, or the gitignore stops being cobo-sealed See: gitignore-generation.md#cobo-generates-the-gitignore-with-a-hash-sealed-fence-and-lockfiles — 3e3bc38e-bc1e-4e65-b74d-e91848262157 — as of 2026-10-11

builtins = false: the shipped rules are only the project's own. gitignore = false: the generated output is committed and ai-rulez does not rewrite the ignore file.

Reason: every one of the seven auto-included builtin domains (of 33 shipped) either restates a gate or contradicts it — complexity 20 versus ruff's 5, 120 columns versus 88, Google-style docstrings and 80% coverage versus ruff's pep257 and 99%, "use conventional commits" versus the blocking title check, "descriptive branch names" versus Conventional Branch and the blocking check-branch-name.yml. A rule an agent obeys and a gate that fails it must never be two separately maintained sentences, and per-domain exclusions would leave the next release free to add a contradiction to a domain opted into. Off entirely also keeps the generated file ~60 lines instead of ~270. ai-rulez's default gitignore rewrite would break the cobo-sealed fence and hide the very files GitHub must find in the repository.

Rejected alternative: per-domain ! exclusions — the next-release risk.

Two gates plus a convergence scenario over every host

Id: b23fd420-5b88-4075-93ad-5122b4f7622e Type: decision Type: incident Status: superseded Superseded by: 249600a2-79c3-49b9-b4b5-277ccc245d1b Evidence: confirmed Source: ADR-035 §6–7 (docs/adr/035-ai-rulez-as-the-agent-instruction-source.md) Revisit when: ai-rulez gains a check mode for preset output, or a host's generated output changes format See: template-testing.md#generated-files-must-be-formatter-canonical-not-merely-valid — 9b931598-7e52-4ff1-bb07-ef65c01d5369 — as of 2026-10-11 See: lint-orchestration.md#the-tox-style-env-is-the-sole-authoritative-lint-suite-prek-is-a-fast-gate-not-a-second-suite — 9b74fc8b-a808-4f2b-bdbd-9e4253c1b35a — as of 2026-10-11

prek runs the generator as a fixing hook; tox style runs ai-rulez validate; and ci.yml's hooks job additionally fails on any working-tree change including untracked files. A template-ci scenario renders the toggle on with every offered host, runs the generator, then the generated project's own fixing hooks, and gates on git diff; it also runs the checking hooks and gates on their exit codes. Checking hooks skip the paths a generator owns (.continue/prompts/ for trailing-whitespace, yamllint and the editorconfig checker; .mdc for the editorconfig checker), rendered only under the toggle.

Reason: there is no check mode for preset output, and a fixing hook only fails on a modified tracked file — a project that never committed its output would have it regenerated untracked and stay green, shipping instructions that exist on no branch. Two generators writing one tree that disagree on a byte leave a repository that never converges. The defaults emit markdown alone and converge; two hosts found only once the scenario covered every host do not — continue-dev's YAML header carries trailing-space comment lines the whitespace hook strips and the next generate restores, and cursor's .mdc rules fail the editorconfig checker because the \.md$ exclude does not reach the extra character. A checking hook rejecting generated output cannot be satisfied at all, so it gets the .copier-answers.yml answer: skip the generator-owned path.

Consequence: the width of the gate is the width of the output it sees; every offered host widens the scenario that must keep passing.

Consequence: MegaLinter's COPYPASTE_JSCPD reports the generated host files as clones of each other, which they are. It is left unexcluded on purpose: an exclusion would spell out ai-rulez's per-host output paths, the same second copy refused for .gitattributes, and MegaLinter runs with DISABLE_ERRORS: true, so the cost is a Security-tab finding, not a red job.

Consequence: ai_rulez_presets is the template's first list-valued answer, which surfaced a latent defect: copier writes block sequences unindented, so .copier-answers.yml fails the generated project's own yamllint indentation rule, and the file cannot be hand-edited. The yamllint hook now skips it, as the yamlfmt hook already did; any later list answer would have hit the same thing.

No CLAUDE.md by default; claude left the preset defaults; gemini is no longer offered

Id: 1a6849be-72d0-4990-abe2-7a0243cd5e67 Type: decision Status: needs-review Evidence: confirmed Source: ADR-035, 2026-10 amendment (docs/adr/035-ai-rulez-as-the-agent-instruction-source.md) Revisit when: Claude Code stops reading AGENTS.md natively, or the maintainers start using Gemini See: agent-instructions.md#ai-rulez-is-the-opt-in-single-source-for-agent-instructions-with-the-prose-in-shared-macros — e1545d12-ac20-426b-9cd5-519e80a56b5f — as of 2026-10-11

The default shape uses AGENTS.md alone, including for Claude Code. The former @AGENTS.md wrapper is neither rendered nor preserved on update any more, so an update deletes leftover copies (customized ones too). ai_rulez_presets defaults to codex and copilot; claude is still offered but not default; gemini was removed from the choices.

Reason: Claude Code reads AGENTS.md natively, removing the only reason the wrapper existed — and a leftover CLAUDE.md makes Claude Code's default mode skip AGENTS.md, the opposite of what the default shape wants. The codex host already writes AGENTS.md, so claude only added a duplicate wrapper and a .claude/ tree. The maintainers do not use Gemini and every offered host widens the convergence scenario.

Rejected alternative: keep excluding CLAUDE.md from updates to protect adopter guidance — kept a file that actively harmed the default; the README tells adopters to move unique guidance first, and git history keeps the old content.

Consequence: by default the per-host skills no longer reach Claude Code, which looks under .claude/skills/; adopters who want them select claude. Removing a choice has a sharp edge: a --defaults update (what Renovate runs) silently replaces a recorded selection containing a removed choice with the new defaults, so a project that selected gemini loses every other host too and keeps a stale GEMINI.md; such a project cleans before updating and re-selects.

ai-rulez is removed; the template ships one hand-written AGENTS.md and no per-host files

Id: 249600a2-79c3-49b9-b4b5-277ccc245d1b Type: decision Status: active Evidence: confirmed Source: issue #428 (maintainer decision), 2026-10-19 Revisit when: copier-skill-repo stops generating per-host agent and skill files, or an adopter needs per-host files this template must render itself See: agent-instructions.md#ai-rulez-is-the-opt-in-single-source-for-agent-instructions-with-the-prose-in-shared-macros — e1545d12-ac20-426b-9cd5-519e80a56b5f — as of 2026-10-19 See: repo-setup.md#the-repo-setup-skill-is-no-longer-shipped-the-setup-doc-is-read-directly — 4ff05ee1-3b53-423d-96cf-acb7681b6a97 — as of 2026-10-19

include_ai_rulez, ai_rulez_presets, the .ai-rulez/ sources, the agents dependency group, the prek hook, the tox ai-rulez validate command and the CI convergence scenario are gone. AGENTS.md is always rendered from the agent_*() macros in _macros.jinja. The adjacent entries on ai-rulez (build output, no builtins, the convergence gates) are superseded with the toggle; the rule that the template renders no CLAUDE.md still stands, but its mention of ai_rulez_presets is obsolete, so that entry is needs-review.

Reason: copier-skill-repo now generates agent and skill files per host, so keeping a second generator in this template duplicated it and carried the cost the earlier entries record (non-copier-managed output, two-way manual update steps, extra lint exclusions).

Rejected alternative: keep the toggle beside copier-skill-repo — two generators for the same files, and the update hazards stay.

Consequence: breaking change (refactor!). Adopters with include_ai_rulez=true must migrate: run ai-rulez clean --force --keep-gitignore before updating, then move any guidance from the .ai-rulez/ sources into AGENTS.md. Adopters with it off see only the removed question.