Repository checks
A repository check is a requirement you keep in your repository as a Markdown file. HeyDeer verifies it in every pull request that changes the files it covers.
Have checks written for you
On the dashboard, choose Set up repository checks under Getting started. HeyDeer reads the repository and its past pull requests, then opens a pull request that adds checks. It uses no credits.
To have your own coding agent write them, give it this prompt:
Add HeyDeer repository checks to this repository following the guide below, and open a pull request with them. If it needs no new check, explain why instead.
# Write repository checks
A check is a Markdown file in `.agents/checks/` that states a requirement. Each check adds a reviewer of its own to every pull request that changes the files it covers, on top of a general review that already looks for common bugs and security issues. Add one only for a requirement that is specific to this codebase, costly to miss and easy to overlook.
1. Learn what the team cares about: the code, AGENTS.md or CLAUDE.md, REVIEW.md, the checks already in `.agents/checks/`, and as much of the merged pull requests and their review discussions as you need to see what reviewers keep asking for and where bugs were fixed.
2. Choose the requirements, usually one or two, leaving out what existing checks cover. Give each check one requirement or a few closely related ones, and keep one requirement in one check.
3. Write each check as `.agents/checks/<name>.md`, its name starting with a letter or digit and using only letters, digits, `.`, `_` and `-`, excluding every case variant of `README.md`:
- Start with YAML frontmatter whose `files` lists glob patterns, relative to the repository root, for the files where the requirement can break. A pattern without a slash matches in any folder, a `!` prefix excludes, and the last matching pattern decides; exclusions need an including pattern. Compare the patterns with `git ls-files` so they match those files and little else. Add `skills` only to name repository skills the check needs.
```
---
files:
- "src/api/**/*.ts"
- "!**/*.test.ts"
---
```
- Below it, state the requirement as a condition on the code: what breaks it, what satisfies it and why it matters, with a short incorrect and correct example from this codebase. Most checks fit on a screen; a file can be up to 16000 bytes.
- Write it in the language of the repository's own Markdown, such as its README and AGENTS.md, even when you write the pull request in another language.
4. In the pull request, say what each check covers and why it is worth a reviewer. Link the discussions that led to a check when there are any.
Add a check
- Create a Markdown file in
.agents/checks/, such asapi-workspace-scope.md. - Start it with frontmatter that lists the files the check covers under
files. - Below the frontmatter, write the requirement: what breaks it, what satisfies it, and why it matters.
- Commit it in a pull request. HeyDeer reads checks from the pull request, so the new check applies to that pull request’s own review. See What a pull request can change.
.agents/checks/api-workspace-scope.md
---
files:
- "src/api/**/*.ts"
- "!**/*.test.ts"
---
# API handlers scope queries to the caller's workspace
Every query in an API handler that reads or writes a table with a
`workspace_id` column must filter on the workspace returned by
`requireWorkspace()`. Without that filter, one customer can read
or change another customer's data.
Fail when a handler queries such a table without that filter.
Pass when every such query filters on the workspace, or when the
handler only touches tables without a `workspace_id` column.
Incorrect:
```ts
const invoice = await db.query.invoices.findFirst({
where: eq(invoices.id, id),
});
```
Correct:
```ts
const { workspaceId } = await requireWorkspace(req);
const invoice = await db.query.invoices.findFirst({
where: and(eq(invoices.id, id), eq(invoices.workspaceId, workspaceId)),
});
```- Every
.mdfile directly in the folder whose frontmatter hasfilesis a check. HeyDeer ignores the folder’s other files, such asREADME.mdand checks written for other review tools. - File names start with a letter or digit and use only letters, digits,
.,_, and-.
Write an effective check
Each matching check gets a reviewer of its own, so a check is thorough but uses more credits. Keep checks for requirements that are costly to miss and easy to overlook, and put the rest in REVIEW.md or AGENTS.md.
- Write what is specific to your codebase. Every review already looks for common bugs and security issues, so a check such as “Queries must be secure” adds cost without catching more.
- Give each check one requirement, or a few closely related ones. A check that bundles unrelated requirements gets a shallower pass on each.
- Don’t split one requirement across several checks, and limit
filesto where the requirement can break, so the check runs only where it matters. - Write the requirement as a condition on the code: what breaks it, what satisfies it and why it matters, so HeyDeer can judge cases you didn’t anticipate. Add a short incorrect and correct example from your codebase.
- Most good checks fit on a screen. If several checks need the same background, move it into a skill.
- Test a new check on a pull request that breaks the requirement, and confirm a finding names your check.
| Less effective | More effective |
|---|---|
| Queries must be secure. | Every query in src/api/ on a table with a workspace_id column filters on the workspace from requireWorkspace(). |
| Don’t break the API. | A change to a response type in src/api/ keeps every existing field, so older clients keep working. |
How results appear
When code breaks a check, HeyDeer reports a finding that names the check’s file after Repository check:, on GitHub and in HeyDeer. A check with no findings adds nothing to the review.
These findings count like any other toward the HeyDeer Review check and automatic approval. The HeyDeer Review check’s summary also counts the repository checks that failed.
If HeyDeer cannot finish a check, the HeyDeer Review check shows Review incomplete and fails; request another review.
Frontmatter reference
Frontmatter is YAML between two --- lines, with the keys below.
| Key | Value | Effect |
|---|---|---|
files | A pattern or a list of patterns | Required; without it, HeyDeer ignores the file. The changed files the check covers. Prefix a pattern with ! to exclude files; exclusions need at least one including pattern. |
skills | A skill name or a list of names | Optional. The skills HeyDeer uses for this check. A missing skill doesn’t stop the review. |
HeyDeer ignores other keys, such as those other review tools read.
If a check is invalid, such as a pattern list with only exclusions, HeyDeer skips it and names it under Review notes. The review still runs, but HeyDeer doesn’t approve it automatically.
Which files a check covers
A check applies when at least one changed file matches it, and HeyDeer focuses it on those files.
- Use
files: ["**"]to cover every changed file. - Patterns are relative to the repository root and support
*,**, and{a,b}. A pattern without a slash, such as*.sql, matches in any folder. - Patterns apply in order, and the last one that matches a file decides, so a later pattern can include files an earlier exclusion removed.
- Generated files never match.
If a check seems ignored, see Troubleshooting.
Limits
A workspace can start up to 30 checks generation tasks in any 30 days, across all its repositories, including tasks that fail or are canceled.
A check file can be up to 16,000 bytes.
A review runs at most 10 matching checks, in file name order. HeyDeer lists the rest under Review notes, the HeyDeer Review check shows Review incomplete, and HeyDeer doesn’t approve that review automatically.
Narrow or combine checks so fewer match. To choose which run first, prefix their file names with numbers, such as 10-auth.md.
When a check is invalid
Files without frontmatter or a files key are ignored. Invalid YAML, oversized frontmatter, empty files patterns, and patterns with only exclusions are skipped and reported.
For checks that match changed files, HeyDeer also validates the file name, file size, and skill names. Invalid checks are skipped and listed under Review notes. The review continues, but HeyDeer doesn’t approve it automatically.
Fix the check in the pull request, then comment @heydeer review.