Agent instruction files
groundrule sync writes your standards into the instruction files that coding agents read. This page shows which file each agent gets, what the generated section looks like, which rules go in and in what order, and how your own content in those files is kept.
Which files sync writes
Section titled “Which files sync writes”The targets list in .groundrule/config.yaml decides which agents get files. There are four targets:
| Target | Files it writes | How the file is written |
|---|---|---|
agents-md |
AGENTS.md |
A managed block inside the file. Everything else in the file is yours. |
claude-code |
CLAUDE.md |
A managed block. With agents-md also in targets, the block only imports AGENTS.md. Without it, the block holds the full rules. |
cursor |
.cursor/rules/groundrule.mdc, plus one .cursor/rules/groundrule-<scope>.mdc per group of path-scoped rules |
Whole files that Groundrule owns. |
copilot |
.github/copilot-instructions.md, plus one .github/instructions/groundrule-<scope>.instructions.md per group of path-scoped rules |
A managed block in copilot-instructions.md; the per-path files are owned by Groundrule. |
All paths are relative to the repository root.
Choosing targets
Section titled “Choosing targets”groundrule init picks targets for you:
agents-mdalways, because many agents readAGENTS.md.- Every agent it finds signs of in the repository:
claude-codeforCLAUDE.mdor a.claudefolder;cursorfor.cursoror.cursorrules;copilotfor.github/copilot-instructions.mdor.github/instructions.
- With
--org, the coding agents your workspace listed during onboarding (Claude Code, Cursor, Copilot). claude-code, when none of the above found anything.
To choose them yourself, pass --targets to init, or edit the list later:
targets: - agents-md - claude-code - cursor - copilotThen run npx @groundrule/cli sync again. If you leave targets out of the config entirely, the default is agents-md only. See Configuration.
What the generated section looks like
Section titled “What the generated section looks like”This is the managed block sync added to an existing AGENTS.md. The two lines above the block were already in the file and stay untouched:
# Checkout API
Run `pnpm test` before pushing.
<!-- groundrule:begin --><!-- Generated by Groundrule from `.groundrule/`. Edit the standards there, then run `groundrule sync`. -->
## Engineering standards
These are this repository's engineering ground rules. Follow them in every change.Before you finish a task, run `npx @groundrule/cli check` and fix what it reports.For the reasoning and examples behind a rule, run `npx @groundrule/cli explain <ID>`.
### Everywhere
- **SEC-001** No private keys in the repository · _blocker_ Never commit private keys. Load them at runtime from a secret manager or the environment.
- **SEC-002** No environment files in the repository · _blocker_ Do not commit .env files. Commit a .env.example with placeholder values instead. - Do: `.env.example with placeholder values` - Don't: `.env with real values`
…
- **TS-009** Import Node.js built-ins with the node: prefix · _info_ Import Node.js built-in modules with the node: prefix (node:fs, node:path, node:crypto, ...) in code that runs on Node.js 16 or later. (typescript, javascript) - Do: `import { readFile } from "node:fs/promises";` - Don't: `import { readFile } from "fs/promises";`
### `src/**` (except `src/payments/gateway.ts`)
- **ACME-004** Route all Stripe calls through the gateway · _blocker_ Never import stripe outside src/payments/gateway.ts. Call the gateway's functions, such as createPaymentIntent, instead. (typescript) - Do: `import { createPaymentIntent } from "../payments/gateway";` - Don't: `import Stripe from "stripe";` (Direct Stripe import)<!-- groundrule:end -->The structure is always the same:
- The begin marker, then a comment that says where the rules come from.
- An Engineering standards heading and a three-line preamble that tells the agent to follow the rules, to run
checkbefore finishing, and to useexplainfor the reasoning. - One subheading per scope group. Everywhere holds rules with no
paths. Each path-scoped group is headed by its paths, with any excluded paths in parentheses. - One entry per standard.
- The end marker.
How one standard is written
Section titled “How one standard is written”Each entry is short, because agents read every line on every task:
| Part | Where it comes from |
|---|---|
**ID** Title · _severity_ |
metadata.id, metadata.title and spec.severity. |
| The sentence below it | spec.agent.summary if the standard has one, otherwise spec.requirement. Line breaks are folded into spaces. |
(typescript, javascript) |
The standard’s scope.languages and scope.frameworks, when it has any. |
- Do: |
The first entry in spec.examples.approved. |
- Don't: |
The first entry in spec.examples.forbidden. |
Examples render in two ways:
- A one-line example is written inline:
- Do: `const url = process.env.SLACK_WEBHOOK_URL;`. An example’snotefollows in parentheses. - A multi-line example becomes a fenced code block, indented under the entry, with the example’s
languageon the fence. The note goes after the label:- Don't (Trusts a client-supplied role.):.
Only the first example of each kind is written. The others stay available through groundrule explain <ID>. To write rules that read well here, see The rule format.
Which rules go in, and in what order
Section titled “Which rules go in, and in what order”sync includes a standard when all of these are true:
- It is in effect: its status is
activeordeprecated, and no config override disables it. Drafts and retired standards are left out. - It applies to this repository. Its
scope.languages,scope.frameworks,scope.tagsandscope.repositoriesmust match what the CLI detects here. A React rule is left out of a repository without React. spec.agent.instructionis notfalse.- With a connected workspace: it is at Teach, Advise or Enforce. Rules at Observe, rules turned off, and drafts never reach agent files. See Rollout stages.
The order is fixed, so the files only change when the rules do:
- Rules are grouped by their
pathsandexcludelists. Rules with the same lists share a group. - Everywhere comes first. Path groups follow, sorted by their paths.
- Inside a group, rules are sorted by severity (blocker, warning, advisory, info), then by ID.
The sync headline counts the rules it delivered:
groundrule sync · 36 standards → agents-md, claude-code, cursor, copilotWith a connected workspace, a second line says where they came from, for example From Acme Payments on Groundrule (organization rules): rules at Teach, Advise, and Enforce.
Claude Code: CLAUDE.md
Section titled “Claude Code: CLAUDE.md”When agents-md is also a target, CLAUDE.md gets a block that imports AGENTS.md, so Claude Code doesn’t read the same rules twice:
<!-- groundrule:begin --><!-- Generated by Groundrule from `.groundrule/`. Edit the standards there, then run `groundrule sync`. -->
Engineering standards for this repository are in AGENTS.md:
@AGENTS.md<!-- groundrule:end -->When agents-md isn’t a target, the block in CLAUDE.md holds the full Engineering standards section instead.
Cursor: .cursor/rules
Section titled “Cursor: .cursor/rules”Cursor gets one rule file per scope group. Groundrule owns these files and rewrites them on every sync.
-
.cursor/rules/groundrule.mdcholds the Everywhere group and applies to every file:---description: Engineering standards for this repositoryglobs:alwaysApply: true---<!-- Generated by Groundrule from `.groundrule/`. Edit the standards there, then run `groundrule sync`. --># Engineering standards: Everywhere -
Each path group gets
.cursor/rules/groundrule-<slug>-<hash>.mdc, for examplegroundrule-src-1w14o.mdc. Itsglobsare the group’s paths, and it only applies when Cursor works on matching files:---description: Engineering standards for src/**globs: src/**alwaysApply: false---<!-- Generated by Groundrule from `.groundrule/`. Edit the standards there, then run `groundrule sync`. --># Engineering standards: `src/**` (except `src/payments/gateway.ts`)
The file name comes from the paths plus a short hash, so it stays the same between runs. Excluded paths appear in the heading but not in globs, because Cursor globs can’t exclude.
Other files in .cursor/rules/ are yours. sync only writes and removes files named groundrule.mdc or groundrule-*.mdc.
GitHub Copilot
Section titled “GitHub Copilot”-
.github/copilot-instructions.mdgets a managed block with the Everywhere rules. Your own instructions in the file stay. -
Each path group gets
.github/instructions/groundrule-<slug>-<hash>.instructions.md, with anapplyToheader:---applyTo: "src/**"---<!-- Generated by Groundrule from `.groundrule/`. Edit the standards there, then run `groundrule sync`. --># Engineering standards: `src/**` (except `src/payments/gateway.ts`)
Other files in .github/instructions/ are yours.
Your content is kept
Section titled “Your content is kept”In AGENTS.md, CLAUDE.md and .github/copilot-instructions.md, Groundrule owns only the lines from <!-- groundrule:begin --> to <!-- groundrule:end -->.
| The file… | What sync does |
|---|---|
| doesn’t exist, or is empty | Creates it with only the managed block. |
| has content but no markers | Adds a blank line and the managed block at the end. Nothing else changes. |
| has both markers | Replaces what is between them. Text above and below stays exactly as it was. |
Write your own instructions, such as build commands or architecture notes, above or below the block. Don’t edit inside it: the next sync overwrites those lines. To change a rule, change the standard (in .groundrule/standards/, or in the dashboard for a connected workspace) and sync again.
Owned files (.cursor/rules/groundrule*.mdc and .github/instructions/groundrule-*.instructions.md) are rewritten whole. When a path group disappears, for example because you changed a rule’s paths, sync removes its old file and prints it with − and removed. It only removes owned files of targets that are still in your config.
Keeping the files in sync
Section titled “Keeping the files in sync”Run sync whenever the rules change, and commit what it writes:
npx @groundrule/cli syncEach file is listed with what happened to it:
| Mark | Meaning |
|---|---|
+ created |
The file didn’t exist. |
~ updated |
The managed block or owned file changed. |
− removed |
An owned file is no longer needed. |
= unchanged |
Nothing to do. |
The last line reads ✓ Done. Commit these files so every agent gets the same rules., or ✓ Already up to date. when nothing changed.
Rules change in more than one place:
- a standard you edited in
.groundrule/standards/; - a pack update that arrives with a new CLI version;
- for a connected workspace, a change in the dashboard: a new standard, a rule moved to Teach, an edited wording.
The last one doesn’t touch your repository. Run sync after rulebook changes, or let CI tell you.
Check in CI that the files are current
Section titled “Check in CI that the files are current”sync --check writes nothing. It exits with 0 when every file is current and 1 when any file would change:
✕ Agent instructions are out of date: .cursor/rules/groundrule.mdc would be created Run groundrule sync and commit the result.When everything is current, it prints ✓ Agent instructions are up to date (36 standards).
Add it as a step before check:
- run: npx @groundrule/cli sync --check env: GROUNDRULE_TOKEN: ${{ secrets.GROUNDRULE_TOKEN }}With a connected workspace, sync --check fails as soon as someone changes the rulebook in a way that affects this repository. Someone then runs sync and commits the result. The full CI setup is in Run it in CI.
groundrule doctor runs the same comparison. It reports ✕ Agent instructions are out of date: .cursor/rules/groundrule.mdc, with the hint Run `groundrule sync`., and exits with 1.
Packs from GitHub
Section titled “Packs from GitHub”If your config extends a pack from GitHub pinned to a tag or commit, sync uses a cached copy. Run sync --refresh to fetch it again. Unpinned GitHub references are fetched on every run. See Environment and files.
Related
Section titled “Related”- The MCP server: agents can also ask for the rules, and propose new ones, while they work.
- The rule format:
agent.summary,agent.instructionand examples. - Command reference: every
syncoption.