Type to search the docs and updates.

Browse documentation

Rules

rules/ holds the conventions an agent follows without being asked, such as commit format or test style. Sync writes each rule in every tool's own format: Cursor .mdc files, Claude Code rules, AGENTS.md sections. Write short instructions. Put multi-step procedures in a skill.

Write one

agnostic-ai new rule conventional-commits creates rules/conventional-commits.md with globs: "**/*" and alwaysApply: true.

---
name: conventional-commits
description: Always use Conventional Commits format.
globs: "**/*"
alwaysApply: true
---

Use `feat:`, `fix:`, `docs:`, etc. Subject under 72 chars.

A rule that loads when the agent works on matching files:

---
name: react-components
description: Conventions for React components.
globs: "src/**/*.{ts,tsx}"
---

Write function components. Keep one exported component per file.

A rule for one directory. Create it with agnostic-ai new rule payments-context --scope services/payments, or place the file at rules/services/payments/payments-context.md:

---
name: payments-context
scope: services/payments
---

Use integer minor units for monetary values.

Claude Code gets a rule that applies only there. Codex gets services/payments/AGENTS.md. Cursor gets its own .mdc rule, unless a tool like Codex needs the shared AGENTS.md, which Cursor then reads too. Gemini gets services/payments/GEMINI.md. Directory-specific instructions lists every tool and the selector limits.

Headings in merged files

When several rules share a file, such as Codex's AGENTS.md or Gemini's GEMINI.md, each rule gets a ### <name> section, and sync moves the body's headings down together so its top heading is at least ####. A body with ### Doc versioning and #### Details becomes #### Doc versioning and ##### Details.

  • The outputs.claude.rules-file layout writes ## <name> sections, so there the top body heading is at least ###.
  • Headings already deep enough keep their levels. No heading goes past ######, so when a body's deepest heading is more than two levels below its top one (three in the Claude layout), the deepest levels merge at ######, and import cannot separate them again.
  • The section's source comment records the shift, as in <!-- source: .agnostic-ai/rules/content.md headings: +1 -->, and import moves the headings back.
Edge cases for heading shifts
  • Fenced code (including fences inside lists) and raw HTML blocks keep their headings as written.
  • Link reference definitions stay separate from underlined (Setext) headings.
  • List items followed by a thematic break remain lists.
  • Raw HTML blocks follow CommonMark. A line such as <b>Note:</b> read first is paragraph text, so a --- under it forms a heading that nests too.
  • A rule file written on its own, or a nested file with one rule and no section wrapper, keeps its heading levels.
  • An underlined (Setext) heading comes back from import as a # heading. Hard line breaks in its text become <br> tags.
  • Headings and source-comment examples inside fenced code and raw HTML stay in their rule body. They do not start another rule.
  • When a rule leaves a code or HTML block open, its source comment also records body-lines: <count>, which sync updates and import uses to find the next section.

Fields

FieldRequiredDefaultDescription
namenofilenameRule identifier.
descriptionnoemptyShort summary.
scopenoproject-wideA project-relative directory and everything under it. It wins over the rule's folder. A folder that names a project directory scopes a rule without scope; any other folder only groups rules. A scope inside node_modules is refused. See scoped context.
globsnodepends on the tool; new rule seeds **/*Project-relative patterns, as a comma-separated string ("*.go,*.mod") or a list. A comma inside a brace set does not separate patterns, so "src/**/*.{ts,tsx}" is one pattern. With scope, applies to the whole scope directory and every matching file. new rule --scope omits it.
pathsnounsetAnother name for globs, the form Claude Code writes. Every tool reads it as globs. Set only one of them; validate rejects a rule whose paths and globs name different patterns. See selector limits.
alwaysApplynofalse with globs, else depends on the tool; new rule seeds trueAsks the tool to always load the rule. Unset on a rule with globs, it is false in every tool that has an activation field, so the rule loads only on matching files; a catch-all such as **/* keeps it always-on. With scope, the rule stays within the scope plus patterns. new rule --scope omits it.

A rule with neither globs nor alwaysApply loads differently per tool; each target page says when. Set alwaysApply: true when a rule must load everywhere.