Configuration
.diffy.yaml
Per-repository review settings: what to look for, what to leave alone, and which documents to read
Create the file
- Put a file named
.diffy.yaml(or.diffy.yml) at the root of the repository. If both exist,.diffy.yamlis used. - Start small. Every setting is optional, and an empty file is the same as no file. Add a setting when a review shows you need it.
- Merge it into the default branch. That is where diffy reads it from.
A wrong value never stops a review: the setting is reported and replaced by its default, and the others still apply. See Warnings.
Example
# The language of the summary, titles and explanations: en (default) or th.# Code, file paths and the "fix prompt for your coding agent" always stay English.language: en# assertive (default): also missing error handling, untested changes and maintainability problems.# chill: only what matters.profile: assertive# What the reviewers of this project care about. Up to 20,000 characters together with instructions_file.instructions: |We use Drizzle for all database access. Flag any raw SQL.Money is always stored in satang as an integer.# A file of the repository (on the default branch) with longer instructions. Added after `instructions`.instructions_file: docs/review-instructions.md# Instructions for part of the code. Only sent when the pull request changes a matching file.path_instructions:- path: "src/server/**"instructions: Every endpoint must check the signed-in user's permissions.- path: "**/*.sql"instructions: Migrations must be reversible.# More documents to read before every review (on the default branch, up to 10).context_files:- docs/ARCHITECTURE.md# Files that are never reviewed. Same pattern syntax as .gitattributes.ignore:- "public/**"- "**/*.svg"
Settings
| Setting | What it does | Default |
|---|---|---|
language | The language of the summary, titles and explanations: en or th. Code, file paths and the fix prompt stay in English. | en |
profile | assertive also reports missing error handling or input validation on new code, changed behavior with no test, and maintainability problems, as low or medium findings. chill reports only what matters. | assertive |
instructions | What the reviewers of the project care about, in plain words, like a note to a new reviewer. Up to 20,000 characters together with instructions_file. | none |
instructions_file | A file in the repository, on the default branch, with longer instructions. Its text comes after instructions. | none |
path_instructions | A list of path and instructions. Sent only when the pull request changes a file that matches the path. Up to 50 entries of 5,000 characters. | none |
context_files | More documents to read before every review, like architecture notes or a style guide. Up to 10. They are read before the files diffy finds by itself. | none |
ignore | Files that are never reviewed. Up to 100 patterns. | none |
Lockfiles, build output, migration snapshots and other generated files are skipped without any setting, and so is anything marked linguist-generated in .gitattributes. Instructions can add things to look for and tell diffy what to leave alone. They cannot change the format of the review or the rules for line numbers.
Pattern syntax
ignore and the path of each path instruction use the pattern syntax of .gitattributes, which is close to .gitignore but smaller.
| Pattern | Matches |
|---|---|
*.svg | An .svg file in any folder (a pattern with no slash matches by name, anywhere) |
public/** | Everything under public/ at the root of the repository |
**/*.sql | An .sql file in any folder, including the root |
docs/ | A folder named docs, at any depth, and everything in it (a trailing slash means the folder) |
/package-lock.json | Only that file, at the root (a leading slash anchors it) |
src/*.ts | .ts files directly in src/, not deeper (a slash in the middle anchors it to the root) |
file?.txt | file1.txt, fileA.txt: ? is one character that is not a slash |
*matches within one folder level,**across folders.- A pattern with a slash anywhere but the end is relative to the root of the repository.
- Not supported:
!to take a file back in,[abc]classes and{a,b}alternatives. A pattern that uses them is read literally, so write two patterns instead of*.{ts,tsx}. - The paths of
instructions_fileandcontext_filesare plain paths in the repository: no leading/, no.., no backslashes.
Writing instructions that work
- Say what to flag, and what is fine. "Flag raw SQL; we use Drizzle" works. "Write good code" does nothing.
- Give the reason when it is not obvious. "Money is an integer number of satang, so a float is a bug" lets the model judge a case you did not list.
- Keep it short and specific. Ten sentences about the rules that matter beat a page of everything. Put long reference material in a file and name it in
context_files. - Use path_instructions for rules that apply somewhere. They are sent only when a changed file matches, so they cost nothing on other pull requests.
- Do not repeat what your
AGENTS.md,CLAUDE.mdor README already say: diffy reads those on its own. - Do not ask for style comments. diffy leaves formatting and naming to your linters.
More examples
The smallest useful file:
instructions: |This is a billing service. A bug that charges a customer twice, or not at all, is always critical.ignore:- "**/*.snap"
A TypeScript monorepo:
language: enprofile: assertiveinstructions: |Follow AGENTS.md. Money is an integer number of satang, never a float.A change to a public API needs a test that would fail without it.path_instructions:- path: "apps/api/src/**"instructions: Every route needs an auth check. Another account's row must look like "not found".- path: "apps/api/prisma/migrations/**"instructions: Never edit a migration that is already merged. Flag anything that drops data.- path: "apps/web/src/**"instructions: Use the generated API client, never a hand-written fetch.context_files:- docs/ARCHITECTURE.mdignore:- "apps/api/openapi.json"- "**/*.generated.ts"
A documentation repository:
profile: chillinstructions: |Check facts, commands and links. Ignore wording preferences.ignore:- "static/**"
Check that it works
- Merge the file into the default branch, then open or update a pull request.
- At the bottom of the review, diffy lists the documents it read. If the file has a problem, a collapsed section "problem(s) with the diffy settings of this repository" lists each one.
- To see that an instruction is used, add one that is easy to spot, like "mention the word pineapple in the summary", open a pull request, and then remove it.
Warnings
Every message starts with the name of the file. Each setting is checked on its own, so one mistake does not cost you the rest.
| Message | What it means and what to do |
|---|---|
| The file is not valid YAML, so it was ignored | The whole file is skipped. Check indentation and quotes; a tab is not allowed. |
| The file must be a YAML mapping of settings, so it was ignored | The top level must be setting: value lines, not a list or a single value. |
| Unknown setting "x" was ignored | A misspelled setting. The known ones are language, profile, instructions, instructions_file, path_instructions, ignore, context_files. |
| language must be "en" or "th", not … | Fix the value. en is used. |
| profile must be "chill" or "assertive", not … | Fix the value. assertive is used. |
| instructions must be text. It was ignored | Use a string, or a | block. |
| instructions_file must be a path in the repository | Use a path like docs/review-instructions.md. |
| instructions_file "x" must be a path inside the repository | No leading /, no .., no backslashes. |
| instructions_file "x" was not found on the default branch | The file is not on the default branch yet. Merge it first, or fix the path. |
| the instructions are longer than 20000 characters. The rest was cut | instructions plus the file are over the limit. Shorten them. |
| path_instructions must be a list of { path, instructions } | Use a list of items that each have both fields. |
| path_instructions[N] needs a "path" and "instructions", both text | The item at position N (counting from 0) is missing one. It was skipped. |
| path_instructions[N] is longer than 5000 characters. It was cut | Shorten it. |
| Only the first 50 path_instructions are used | Merge entries that share a rule. |
| ignore must be a list of path patterns (text) | Use a list of strings. |
| Only the first 100 ignore patterns are used | Use broader patterns. |
| context_files must be a list of paths in the repository (text) | Use a list of strings. |
| context_files "x" must be a path inside the repository | No leading /, no .., no backslashes. |
| context_files "x" was not found on the default branch | The document is not on the default branch. |
| Only the first 10 context_files are used | Merge documents, or keep the ones that matter. |
| Could not read the repository's diffy settings (…). Defaults were used. | GitHub could not be asked. The review ran with the defaults. |
Limits
| What | Limit |
|---|---|
| instructions and instructions_file together | 20,000 characters |
| One path_instructions entry | 5,000 characters |
| path_instructions entries | 50 |
| ignore patterns | 100 |
| context_files | 10 |
| One document read by diffy | 10,000 characters |
| All documents together | 30,000 characters by default (a server setting) |
The documents diffy reads on its own, and how much of a change the model sees, are on What diffy reads.