Skip to content

Rules

Rules (opens in a new tab) are short Markdown files Claude loads into its context. A rule’s frontmatter paths: field decides when it loads: when Claude reads or edits a file matching one of those file patterns, the rule loads. A rule with no paths: field loads at the start of every session.

Rules are guidance Claude reads; nothing forces Claude to follow them. Anything that must always hold, whatever Claude decides, is enforced by hooks, the commit hooks, and the merge audit.

GAIA ships rules in two places:

  • .claude/rules/ at the root: rules for the whole repository. Their file patterns are relative to the repository root.
  • frontend/.claude/rules/: rules for the React app. They load when the work is under frontend/, and their file patterns are relative to frontend/.
RuleWhat it enforces
coding-guidelinesKebab-case files and folders. Keep code simple: no handling for situations that cannot happen, but real failures are handled with limits. Change only what the task needs. Use TDD. Leave formatting and auto-fixable lint to pnpm lint. React file layout lives in coding-guidelines-react.
context-disciplineKeep the main session’s context small by handing reading-heavy work to sub-agents. Choose models from GAIA’s model table. Research goes in .notebook/research/<date>-<topic>/. Long work resumes from one STATE.md file.
fenced-copy-paste-blocksAnything meant for you to paste goes, whole, in its own plain three-backtick fence, never in prose or a blockquote, so Claude Code shows it with a copy button. A handoff prompt carries its own context instead of pointing back at the session.
issue-claimBefore work that closes a GitHub issue, check for the in-progress label and add it. Release it when Claude closes the pull request unmerged or you drop the work. Follow the work lifecycle. Claim tech-debt issues only through /gaia-debt.
pr-mergeBefore any gh pr merge, run the audit and post GAIA-Audit as the last step. The audit loop runs on its own until it reaches the branch checkpoint, which only you can answer.
quality-gateRun the Quality Gate before any commit that touches source, unless nothing in the gate’s scope is staged.
shell-cwdNo cd in Bash calls; use absolute paths. Each hook finds its script from the checkout the shell is in, so a cd into another checkout can switch the guards off without any warning. See Hooks.
subagent-dispatchClaude re-runs a sub-agent that returned nothing, instead of reading silence as “found nothing”.
RuleWhat it enforcesLoads on
ambient-context-resolutionApplies when Claude writes shell scripts or GitHub workflows: a script gets the repository root, base branch, and commit from its input, not from the current folder or HEAD. The last two patterns match files a GAIA project does not ship (TypeScript under .gaia/ and bats test suites), so they apply only if you add such files..gaia/scripts/**/*.sh, .claude/hooks/**/*.sh, .github/workflows/**/*.yml, .gaia/**/*.ts, **/*.bats
code-commentsA comment says something the code itself does not; the merge audit checks comments by the same standard.app, test, Playwright (opens in a new tab), and Storybook (opens in a new tab) source under frontend/, .gaia/**/*.ts and .sh, .claude/hooks/**/*.sh, .github/**/*.sh, and **/*.bats
file-placementNew hooks go at the root of .claude/hooks/, and how to register one so it keeps working. Project scripts go outside .gaia/, never in .gaia/scripts/..claude/hooks/**, .gaia/scripts/**
generated-filesNames the source to change for a file GAIA or pnpm generates. For frontend/.claude/settings.json: the root .claude/settings.json or the frontend overlay, then regenerate. For pnpm-lock.yaml: pnpm commands, never a hand edit.frontend/.claude/settings.json, pnpm-lock.yaml
guards-must-failA guard and its tests must be seen failing before anyone trusts them.hooks, scripts, workflows, and Playwright specs
no-abbreviationsDescriptive names in every language, alongside the naming-conventions skill.code files in any language
user-questionsAsk a choice as an AskUserQuestion menu: recommended option first, at most four options, one question per decision. A list of review findings, each with its own recommendation, is one decision: every finding prints as text, then one question asks Accept all as recommended or Revise.skills, commands, and agents (root and frontend/), plus a few wiki pages about the merge workflow and the Quality Gate
wiki-stylePresent-tense prose; no historical phrasing or roadmap stated as current; no SPEC, PR, or commit references in body prose.wiki/**/*.md and the Markdown files for skills, commands, agents, and rules
working-doc-idsNo SPEC, plan, or audit IDs, no paths to one machine’s notebook or .gaia/local/ entries, and none of your own issue or PR numbers, in code or prose. Hooks also enforce most of this (gate).app, test, and harness source
RuleWhat it enforcesLoads on
accessibilityKeyboard reachability, alt text, focus management, semantic HTML over ARIA roles, color never the only indicator.app/components/**, app/pages/**
api-servicePoints Claude to the API Service Pattern and the new-service skill.app/services/**, test/mocks/**
coding-guidelines-reactReact file and folder layout and naming: kebab-case folders, index.tsx, use-<name>.ts hooks, tests/ folders.app/**, test/**, .playwright/**, .storybook/**
design-baselineGAIA’s neutral styling is a placeholder, not a design system; confirm the design direction before extending tokens.app/styles/**, app/components/**, app/pages/**
i18nEvery user-facing string comes from t(); namespace and key-file conventions; which steps to follow to add a language or remove i18n.app/routes/**, app/pages/**, app/components/**, app/languages/**
playwrightSpec layout, semantic selectors, web-first assertions, the hydration helper, MSW (opens in a new tab) in dev..playwright/**, playwright.config.*
portsEach checkout owns its dev, Storybook, and Playwright ports. Claude reads them from GAIA’s ports script and never hardcodes 5173 or 6006.Test, Playwright, Storybook, and server config files, and package.json
react-router-docsRead the React Router (opens in a new tab) docs in node_modules/react-router/docs, which match the installed version, and check remix-utils before writing a basic utility from scratch.routes, pages, app/root.tsx, middleware
routesThin route files (loader, action, meta, one-line page render); UI in app/pages/.app/routes/**, app/pages/**
shadcn-uiThe ui components copied in from shadcn/ui (opens in a new tab) are not edited; add components with pnpm shadcn add.app/components/ui/**
state-patternContext lives in app/state/, with Provider, useX, and useMaybeX naming.app/state/**
storybookStory location and typing, titles, decorator order, layout, and Chromatic (opens in a new tab) light and dark modes.app/**/*.stories.tsx, .storybook/**
tailwindUse the role-based color tokens (named for their purpose, not their color), never raw palette classes or arbitrary colors. Tailwind (opens in a new tab) v4 config lives in CSS.app/**/*.tsx, app/**/*.css

Ask Claude to write the rule for you. Say what the rule should make Claude do, and which files it applies to, so Claude can scope it with a paths: pattern:

Add a Claude Code rule that <what Claude should always do>. It applies when working on <which files, for example frontend/app/services/**>. Scope it with a paths: pattern, and keep it short.

A rule for the whole repository goes under .claude/rules/. A rule that only applies to the app goes under frontend/.claude/rules/, with patterns relative to frontend/. Leave out paths: only when the rule truly needs to load in every session, because an always-loaded rule uses up context in every session.

/gaia-codify writes path-scoped rules from recurring audit findings, and /gaia-cleanse and /gaia-fitness keep rules lean.