farol farol
Free and open source · CLI and GitHub Action

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 routes

or on every pull request: uses: winnin/farol/action@main

Free, MIT licenseNo account, no serviceNever executes your codeNever blocks a merge
farol report · a single HTML file: review it, then paste the results in the PR
A farol report of an example pull request: careful review at 69/100, three items to check by hand (a breaking API change, a security finding, a lint error), the files by risk, and what makes up the score

Tick what you checked and the merge risk drops as you go. Review a real pull request →

Why farol

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.

Where it fits

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 unknown and asks for a careful review
The report

A review workbench, not a wall of warnings.

One comment on the pull request, and a single-file HTML report where the review happens. On the left, the risk that is left and what to read next; on the right, the file you are reading.

69
A merge risk that drops as you review0–100, with what makes it up. Tick a file once you read it and its share leaves the score. When the risk is low and nothing is left to check, the report says the merge is likely safe to approve.
!
Must checkBreaking API changes, security findings, lint errors and vulnerable dependencies, above every file. Reading the file does not clear them: you confirm each one.
≡
Files by risk: high, medium, skimEach with its diff, the lines no test ran marked in red, and a link to comment on any line in GitHub. Dependency bumps say what changed and how to check it; test files sit apart.
%
How much of the new code is testedDiff coverage per file and per line, with the files the coverage report never saw listed apart (types and constants are often excluded on purpose).
✓
What it can affectThe pages and endpoints that run the changed code, riskiest first, to try by hand. Mark the ones behind a feature flag and their files leave the score.
↗
Results for the pull requestWhat you checked, as Markdown for a PR comment: risk before and after, what is still open, your notes on each file.
A file in the farol report: a high-severity security finding to check, the share of the score, coverage of the changed lines and the diff with untested lines marked

Also in the report: suggested reviewers from git history, production traffic and errors from Datadog (optional), and a Details page with every route, its import graph and the raw signals. After a push, a second report covers only the new commits.

Free and open source

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

Complete workflows for TypeScript, Go and Python →

Stacks

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.

React RouterNext.jsTanStack RouterGraphQLFastify / Express
Vitest or Jest coverage · ESLint · npm/pnpm audit

Go

Routes, RPC methods and binaries, read with go/types, offline. Interface calls reach their implementations.

chiginechonet/httpgRPC
go test -coverprofile · golangci-lint + gosec · govulncheck

Python

Routes, tools, tasks and workflows, read with Python's own parser. Nothing is imported.

FastAPIFlaskDjangoCeleryTemporalPrefectMCP
pytest-cov · ruff (with bandit rules) · pip-audit
How it works

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.

Get started

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

Recipes per stack →  ·  Every option →

# 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
Built to be trusted

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.