TLDR overview
- Gitar Knowledge stores your team's review conventions as facts and applies them to later pull requests. When a finding relies on a fact, it links back to that fact.
- Facts come from Markdown files in
.gitar/review/and from pull request comments addressed to@gitar. In this walkthrough, a clock-module rule explained in one comment became a fact within minutes. On the next pull request, Gitar flagged a violation of that rule and linked to the fact, without anyone commenting. - The Knowledge library shows each fact's source, the paths it applies to, and which reviews received it. Admins can mark outdated facts stale.
- Knowledge is part of Gitar Enterprise.
Overview
By the end of this blueprint, you'll explain a convention to Gitar once in a pull request comment, and a finding on a later pull request will link back to it. Gitar is an AI code verification agent that reviews your pull requests. Knowledge is the part of Gitar Enterprise that stores your team's review guidance between reviews. The guidance comes from Markdown files in your repository and from pull request comments addressed to Gitar. The Gitar dashboard calls each stored piece of guidance a fact, and so does this blueprint.
In the sample service, route handlers must return errors through a sendError() helper, and code must read the time through a clock module so tests can freeze it. Neither rule is in a linter config, and until you write them down for Gitar, a reviewer who knows the codebase explains each one again on every pull request that breaks it. With Knowledge, you explain a rule once, and Gitar applies it to later pull requests. Gitar also reads agent instruction files such as AGENTS.md as context. A Knowledge fact carries its own scope, a link to its source, and a usage count in the dashboard, and a finding based on the fact links to it.
You'll write an API rule in a repository file and teach Gitar a clock rule in a pull request comment. The Knowledge library then lists three facts from the file and one from the comment. Last, you'll open a later pull request where a finding cites the comment's fact.
When to use this
Use this blueprint when reviewers keep leaving the same comment about a house convention, or when coding agents ignore rules your developers already know. Each fact carries a path scope, so a rule scoped to src/routes/ reaches reviews of pull requests that change route handlers.
What you'll achieve
- A guidance file in
.gitar/review/whose rules Gitar applies to changes undersrc/routes/. - A fact that Gitar stores from a pull request comment and applies to changes under
src/. - Three facts from the guidance file and one from the comment in the Knowledge library, each with its source and scope.
- A finding on a later pull request that links to the fact it is based on.
- A record of which reviews received each fact, and the steps to update a fact or mark it stale.
Architecture

Gitar turns files in .gitar/review/ and comments addressed to Gitar into facts in one Knowledge library. Before each review, Gitar looks up facts using the pull request's changed files, title, and description, checks that each one applies to the change, and gives the review the facts that do. A finding based on a fact links to that fact, and the dashboard records which reviews received each fact.
Prerequisites
- A Gitar organization on the Enterprise plan, which Knowledge requires (Gitar plans)
- Knowledge turned on for the organization, which the dashboard's Knowledge page shows as Knowledge enabled. Only an admin can change the setting.
- Membership in the Gitar organization, so you can open the dashboard's Knowledge page
- A GitHub repository with the Gitar app installed, and write access to it. To follow the walkthrough exactly, create your own copy of the sample repository with Use this template and Include all branches checked, then install Gitar on your copy. The sample's CI runs Node.js 24 with
node --test. Itsmainbranch holds the review guidance file, and the branchesfeat/cancel-orderandfeat/order-expirycontain the changes for the pull requests you open in Steps 1 and 4. - The GitHub CLI for the
ghcommands, or the GitHub web UI
Step 1. Add review guidance and open a pull request
Gitar reads the Markdown files in .gitar/review/ as review guidance. The sample repository ships .gitar/review/api-standards.md on main and on both feature branches:
# API standards (src/routes/)
Route handlers return errors with `sendError()` from `src/lib/http.ts`.
Don't call `res.status(...).json(...)` or `res.send(...)` directly for error responses.
Clients parse the `{ error: { code, message } }` envelope, and a bare
`{ message }` body breaks them. Success responses can still use `res.json()`.Write each file the way you'd brief a new teammate. Here the heading names the directory, the next two lines state the rule, and the last two give the reason and allow one exception for success responses.
If you created your copy from the template, main already has this file, so skip ahead to the pull request. To use a different repository, create the same file at .gitar/review/api-standards.md on the default branch, commit it, and push. Then branch new work from the default branch so every pull request branch contains the file.
Now open a pull request that breaks the rule. In the sample repository, open it from feat/cancel-order in the GitHub UI or from your clone:
gh pr create --base main --head feat/cancel-order \
--title "Add order cancellation endpoint" \
--body "Adds \`POST /orders/:id/cancel\`. Pending orders move to \`cancelled\` and record \`cancelledAt\`; shipped orders can't be cancelled."This is PR #1. Its new cancel route in src/routes/orders.ts returns errors with res.status(...).json(...) instead of sendError():
if (!order) {
res.status(404).json({ message: 'Order not found' });
return;
}
if (order.status === 'shipped') {
res.status(409).json({ message: 'Order already shipped' });
return;
}About two minutes after the pull request opens, Gitar posts a summary comment. The first line is the verdict, here Changes requested, followed by how many findings are closed out of the total. Each finding starts with a category, such as Bug or Quality, and a title. It then names the file and lines and explains the problem. Gitar also posts each finding as an inline review comment. Near the bottom, a collapsed Verification section records what Gitar checked. The excerpt below shows the verdict and the first of two findings, and "..." marks omitted text:
Code Review ⚠️ Changes requested 0 closed / 2 findings
...
⚠️ Bug: Cancel error responses skip sendError and break the error envelope
📄 src/routes/orders.ts:33-40
The new handler returns its 404 and 409 errors with `res.status(...).json({ message })`. Every other route uses `sendError()`, which returns `{ error: { code, message } }`. The README documents that envelope, and `.gitar/review/api-standards.md` says clients parse it and that a bare `{ message }` body breaks them. ...Step 2. Teach Gitar from a pull request comment
In the sample repository, no guidance file says that code under src/ must read the time through src/lib/clock.ts. The module's own comment explains only why the module exists:
// Single source of "now" for the service. It exists so tests can freeze time
// with setClock() and get deterministic timestamps.Gitar learns from two kinds of comment. The first is a top-level comment, which you post in the pull request's Conversation tab rather than on a line of code. It must start with gitar or @gitar or mention @gitar. The second is a reply under one of Gitar's findings, which needs no mention. Either way, the commenter needs write access to the repository.
Write a top-level comment that starts with @gitar and states the convention, why it exists, and which directory it covers. Post it on PR #1 in the GitHub UI, or from your clone, replacing 1 with your pull request's number:
gh pr comment 1 --body "@gitar in this repo, code under \`src/\` must never call \`new Date()\` or \`Date.now()\` directly. Use \`nowUtc()\` or \`nowIso()\` from \`src/lib/clock.ts\`. Our tests freeze time with \`setClock()\`, so a direct clock call makes time-dependent tests nondeterministic."About thirty seconds later, Gitar replies with a quote of your comment. The reply restates the rule in Gitar's words and says whether PR #1 breaks the rule:
Understood: code under `src/` must use `nowUtc()` or `nowIso()` from `src/lib/clock.ts` and never call `new Date()` or `Date.now()` directly, since tests freeze time with `setClock()`.
I checked this PR against that rule and found no violations. The only direct clock calls in `src/` are inside `src/lib/clock.ts`, which is the wrapper itself. The test's `new Date('2026-01-15T12:00:00.000Z')` passed to `setClock()` builds a fixed date and doesn't read the clock.
I haven't made any code changes.Gitar stores the rule as a Team feedback fact, which you'll find in the library in Step 3. To change the rule, post a new @gitar comment.

Step 3. Inspect what Gitar learned
Open Dashboard -> Knowledge in the Gitar web app and set the Repository filter to your repository. Within minutes of the comment, the library lists four facts.
Three facts come from api-standards.md. Gitar splits the file into separate facts and titles each one with the file's heading and the start of the rule, such as "API standards (src/routes/) / Route handlers return errors". That fact's content is the rule itself: "Route handlers return errors with sendError() from src/lib/http.ts." Each fact from the file has the source Repository instructions.
The fourth fact comes from the comment in Step 2. Gitar titled it "Use the injected clock in src", and its source is Team feedback, with the sub-label Review comment.
Gitar sets a fact's scope from the directory the guidance names, and the When it applies section shows the result. The file's heading names src/routes/, so each file fact reads "When a changed file matches src/routes/". The comment says "under src/", so the clock fact reads "When a changed file matches src/".

Gitar treats both kinds of fact the same way in a review. A file is versioned with your code and changes through pull request review. A comment captures a convention when a reviewer explains it, with no documentation pull request.
Click the clock fact to open its detail panel. The content is Gitar's rewrite of your comment, worded so that it makes sense without the original conversation:
Code under src/ must not call new Date() or Date.now() directly. Use nowUtc() or nowIso() from src/lib/clock.ts instead; tests freeze time with setClock(), and direct clock calls make time-dependent tests nondeterministic.
Under Where this comes from, the Open source link goes to your pull request comment.
Step 4. Watch a later review apply the fact
Open a pull request from feat/order-expiry:
gh pr create --base main --head feat/order-expiry \
--title "Expire pending orders after 30 minutes" \
--body "Adds \`isExpired()\` and \`POST /orders/expire\`, which moves pending orders older than 30 minutes to \`expired\`."This is PR #2. It adds src/lib/expiry.ts, which calls Date.now() instead of the clock module:
export function isExpired(order: Order): boolean {
if (order.status !== 'pending') return false;
return Date.now() - new Date(order.createdAt).getTime() > EXPIRY_MS;
} Nobody comments on PR #2. The changed file src/lib/expiry.ts matches the clock fact's scope, src/**, so the review receives the fact. About two minutes after the pull request opens, Gitar posts this finding:
⚠️ Quality: isExpired reads the wall clock instead of the injected clock
📄 src/lib/expiry.ts:1-9 📄 test/expiry.test.ts:7 📄 test/expiry.test.ts:16
`isExpired()` calls `Date.now()` directly to work out an order's age. The repo requires using the injected clock: code under `src/` should get the current time from `nowUtc()` in `src/lib/clock.ts`, and `src/routes/orders.ts` already sets `createdAt` with `nowIso()`. Because of this, a test that freezes time with `setClock()` has no effect on expiry. ...
Use the injected clock
import { nowUtc } from './clock.ts';
...
return nowUtc().getTime() - new Date(order.createdAt).getTime() > EXPIRY_MS;In the finding, the phrase "using the injected clock" links to the clock fact in the Knowledge library. That link is the citation, and the fact's Open source link opens the team's original comment. The suggested fix, titled "Use the injected clock", imports nowUtc() and replaces Date.now() with nowUtc().getTime().

Next, expand the Verification section in Gitar's summary comment on PR #2, then expand its Knowledge part:
Verification Knowledge ✅ 1 · 🔎 1 PRs 1 inspected
...
Knowledge ✅ 1 expectation met 🔎 1 informed a finding
🔎 Use the injected clock in src informed a finding, open -> isExpired reads the wall clock instead of the injected clock🔎 marks a fact that informed a finding, and its line links to that finding. ✅ marks a fact whose expectation the change met. Comment gitar display:verbose on the pull request to see the evidence behind each line.

Step 5. Track usage and keep guidance current
Back in the library, each fact card shows Times used, which counts the reviews that received the fact. The clock fact now shows 1. Its detail panel names that review: the Used section reads "1 review has received this knowledge" and lists PR #2 with the label Does not meet criteria, next to the title of the finding that cites the fact, "isExpired reads the wall clock instead of the injected clock".

The Review usage tab lists recent pull requests with the facts Gitar supplied to each, such as "PR #2 / 2 facts supplied" with the clock fact among them. A supplied fact is one the review received as context. A citation in a finding, or a 🔎 line in Verification, shows which fact informed that finding.
A fact's content comes from its source, so you change a rule by changing where it came from:
- For a file-based fact, edit or delete the rule in
.gitar/review/and merge the change to the default branch. Later reviews receive the updated facts, and a deleted rule's fact stops reaching reviews. An unmerged edit doesn't change the facts other reviews receive. - For a comment-based fact, ask an admin to click Mark as stale. A stale fact stops reaching future reviews and keeps its history. Then post a new
@gitarcomment with the corrected rule.
Filter by Status to see stale facts. The library sorts by Most used by default, so the facts that reach the most reviews appear first.
What to know
- Mention Gitar when you want a comment to become a fact. A comment between two developers that doesn't mention Gitar stays an ordinary comment.
- Name the directory the rule covers, because Gitar keeps the scope your comment states.
- To teach an exception, reply with why the finding is wrong and which files the exception covers. A bare "Done" or "fix this" gives Gitar nothing to learn from, and dismissing a finding without a reason doesn't make Gitar skip similar findings later.
- For a rule every repository should follow, use organization Custom Instructions (Settings -> Configuration -> Custom Instructions) or a configuration repository. Facts from
.gitar/review/and from comments apply only to the repository they came from. - Each explained comment works on the next review, and the library improves as your team uses it. Every new explanation adds a fact that Gitar ranks by relevance and source authority, and Gitar can also narrow a fact's scope when a review shows it was too broad.
Next steps
- The Knowledge page explains how Gitar selects facts for a review.
- The Code Review page covers citations in findings and every row of the Verification section.
- Share review guidance across repositories with a configuration repository.
- Repository customization lists every file Gitar reads, including
AGENTS.mdand.gitar/instructions/.
