Know the risk of merging, and where it lives.
Agents write the code and agents review it. The last call is still a person's. farol tells that person how risky the merge is, which files carry the risk and what they reach, so the riskiest changes get the most attention instead of the same skim as everything else.
npx @winninjs/farol routesor on every pull request: uses: winnin/farol/action@main
Every claim in the report comes with the chain of calls behind it. Explore a real one →
Review effort should follow risk.
Agents now write much of the code and review it too, so the human approval is the scarce part. Spread evenly over every pull request it turns into a skim, and a skim is how a one-line change to a shared hook breaks forty pages.
farol makes the risk explicit before anyone approves: a verdict that says how much review the merge needs, and the files that carry the risk, ranked. Low-risk pull requests can go fast; risky ones get read line by line, starting where it matters. The Claude Code team describes the same principle in how they do code review: “The change sets the tier, not the author.”
The riskiest files, first
A forty-file pull request usually has two or three files that can hurt. farol ranks them by reach, diff coverage and findings, so they get the closest read.
Reach, not file names
A declaration graph built with the real compilers: a change to formatPrice lists the pages that render it.
Contracts before clients
Removed response fields, new required parameters and changed types, per endpoint, in GraphQL, FastAPI, Go handlers and gRPC.
Fails closed
When part of a change cannot be read, farol says unknown and asks for a careful review. It never calls something safe by default.
After the AI review, before the human approval.
farol does not replace your review agent. Let the agent comment on the lines; when it is done, farol gives the person who approves what the agent cannot reliably give: the risk of accepting the change, and where it lives.
An agent writes the change
Fast, and often larger than a person would write it.
An agent reviews the lines
Bugs, style and local mistakes, comment by comment.
farol measures the risk
What the change reaches, broken contracts, untested lines and findings, turned into a verdict and a ranked list of files.
A person decides
A quick look when the risk is low; a careful, file-by-file read of the risky parts when it is high.
What each one is good at:
Your AI reviewer
- Read the diff, and whatever context fits in the prompt
- Tell you what may be wrong in these lines
- Answer differently on every run
- May sound confident when unsure
farol
- Reads the whole program at the base and the head, with the compilers
- Tells you how risky the merge is, which files carry the risk and what they reach
- Same pull request, same report, with the call chain behind each claim
- Says
unknownand asks for a careful review
A review plan, not a wall of warnings.
One comment on the pull request and a single-file HTML report, built for the person reviewing it.
Also in the report: suggested reviewers from git history, findings from your linters and audits, production traffic and errors from Datadog (optional), pages behind a feature flag, and a copyable record of the review.
Open a real report.
The reports farol wrote in CI for a pull request on the FastAPI full-stack template. Mark files as reviewed, flag a page, open the diffs. Nothing to install.
Backend · FastAPI
⚠ 72/100- A breaking change:
GET /items/no longer returnscount - SQL built with an f-string, flagged as high severity
- A model change that reaches 23 endpoints
Frontend · React + TanStack Router
⚠ 77/100- A new page, and four existing pages reached through the sidebar
- A shared component with no test
- A test plan that follows your review
The pull request was written for the demo: see it on GitHub, with farol's comments.
A CLI and a GitHub Action. Nothing to sign up for.
farol is MIT-licensed and free to use, on any repository. There is no account, no hosted service and no telemetry: it runs on your machine or in your CI runner.
On your machine
Run it with npx on any branch; it writes a JSON result and a single-file HTML report.
npx @winninjs/farol analyze --base origin/main --head HEAD --out farol.json npx @winninjs/farol html --in farol.json --out farol.html
On every pull request
Use the GitHub Action after your tests: a comment on each push, with a link that opens the report in the browser.
# .github/workflows/farol.yml (excerpt) - uses: winnin/farol/action@main with: command: analyze base: ${{ github.event.pull_request.base.sha }} head: ${{ github.event.pull_request.head.sha }} out: farol.json
Reads the frameworks you already use.
Entry points come from your routes, operations and jobs. Diff coverage, lint and vulnerabilities come from the reports your CI already produces.
TypeScript & React
Pages and layouts, read with the TypeScript type checker, declaration by declaration.
Go
Routes, RPC methods and binaries, read with go/types, offline. Interface calls reach their implementations.
Python
Routes, tools, tasks and workflows, read with Python's own parser. Nothing is imported.
Static analysis, end to end.
No model in the loop and nothing executed: the same pull request always gives the same report.
Diff
The merge-base against the head, with renames; whitespace-only lines are ignored.
Read both trees
The TypeScript compiler, go/types or Python's ast build a graph of which declaration uses which.
Reach
From each changed declaration to every entry point that runs it, keeping the shortest chain.
Plan
Class, risk score, verdict, files to start with and a test plan, in the PR comment and the HTML report.
One config line, then run it.
You need Node.js 22+ and git (plus Go or Python 3.11+ for those projects). Describe the project once, check what farol sees, then analyze a branch.
- Add your coverage, lint and audit reports to sharpen the score
- Copy a ready workflow to get a comment on every pull request
- Optional: production traffic and errors from Datadog
# 1. describe the project echo '{ "routes": { "file": "src/routes.tsx" } }' > farol.config.json # 2. check the pages and endpoints farol sees npx @winninjs/farol routes # 3. analyze your branch and open the report npx @winninjs/farol analyze --base origin/main --head HEAD --out farol.json npx @winninjs/farol html --in farol.json --out farol.html
Your code stays yours.
Never runs your code
Go and Python are read by small helpers that only parse, from the standard library. Your tests run in your own CI job.
Never sends it anywhere
Analysis is local or in your runner. Only the PR comment (GitHub) and the optional Datadog read use the network.
Shadow mode
farol informs. It never approves, requests changes or fails a check: reviewers decide.
Built in the open.
farol is free and MIT-licensed. If it helps your reviews, a star helps other teams find it. Issues, ideas and pull requests are welcome, especially new frameworks and languages.