Know the blast radius before you merge.

Serval is a local-first CLI that answers: if I change this file, what am I likely to affect? It reads your dependency graph, Git history, and CI configuration, and returns a deterministic, explainable risk score. Offline. No account, no cloud backend.

$ brew install AlbertoBarrago/tap/serval
Go offline-first JS/TS · Go · Python · Java · C CI-aware

What it reads

Four kinds of evidence, one score you can audit.

Dependency graph

Language-native resolution: tsconfig paths, go.mod, Python and Java packages. Every import becomes a graph edge; impact is the transitive closure of dependents.

Git history

Churn and co-change frequency over a bounded window: the files that historically break together with the one you are touching.

CI configuration

Path filters in GitHub Actions, GitLab CI, Azure Pipelines, and Jenkinsfiles: whether your change actually trips a workflow.

Explainable risk

No black box. Every point of the score maps to a documented rule, printed in the breakdown. Override the defaults per-repository with a config file.

One command

The report, straight to your terminal.

~/src/serval
$ serval inspect cmd/root.go

Target
  cmd/root.go

Direct impact
  main.go
  tools/gendocs/main.go

Indirect impact
  (none found)

CI
  .github/workflows/ci.yml
  .github/workflows/release.yml

Git history
  9 significant changes (last 90 days)

Risk
  MEDIUM: 38/100
  +4   2 downstream modules
  +14  high historical churn (9 changes)
  +12  91 frequently co-changed modules
  +8   2 CI workflows affected

How it works

Nothing leaves your machine.

  1. 1

    Scan. Serval walks the repository once, parses imports with per-language analyzers, and builds a deterministic dependency graph.

  2. 2

    Trace. For your target file it computes dependents via the graph, churn via Git history, and CI relevance from workflow path filters.

  3. 3

    Score. Each signal adds documented points; the total maps to low, medium, or high, with the breakdown printed next to it. Gate your pipeline with --fail-on high.