ThisCalculator

Everyday

Serval CLI: How It Estimates Code Change Impact

Updated · Standard formula, shown below

Average pace 5.00 min/km
Average speed
12.00 km/h
Result
Finish time
50 min
You entered
Distance
10 km
You entered

Serval CLI: How It Estimates Code Change Impact

Serval CLI is a command-line tool that estimates which parts of your codebase could be affected by a given code change. You provide it with a diff or a set of changed files, and it returns a ranked list of files, functions, or modules that are likely to be impacted. This article explains the estimation technique Serval uses, its limitations, and how to interpret its output.

Background: Why Impact Estimation Matters

When you modify code, you need to know what else might break. Manually tracing every call site, import, and configuration reference is tedious and error-prone, especially in large codebases. Serval CLI automates this by building a model of your project’s structure and then simulating the ripple effects of a change. This is similar to what IDEs do for refactoring, but Serval is designed to work in a terminal, on a whole repository, and without requiring a full build.

The tool is often used in continuous integration (CI) pipelines to suggest which tests to run, or by developers before committing to identify risky areas. It is not a static analysis tool that finds bugs; it is a dependency and impact analyzer.

How Serval Estimates Impact: The Core Mechanism

Serval’s estimation is based on static analysis of the code. It parses the source files (supporting languages like JavaScript, TypeScript, Python, Java, and Go) and builds a directed graph where nodes are symbols (functions, classes, variables, modules) and edges represent dependencies. For example, if file A imports a function from file B, there is an edge from B to A. When you change a file, Serval finds all nodes reachable from the changed symbols in this graph.

The process can be broken down into these steps:

  • Parse the diff: Serval reads the changed files and the specific lines that were added, removed, or modified.
  • Identify changed symbols: For each changed file, it determines which functions, classes, or exports are affected by the diff. A change to a function body affects that function; a change to a function signature affects everything that calls it.
  • Traverse the dependency graph: Starting from the changed symbols, Serval follows edges outward to find all dependent symbols. This is a breadth-first or depth-first search that collects all reachable nodes.
  • Rank by impact: The reachable nodes are ranked by the number of paths from the change (more paths = higher impact) or by the distance (fewer hops = higher impact).

Serval also considers “soft� dependencies like configuration files, environment variables, and database schemas if you provide them via a configuration file. It does not execute the code, so it cannot detect runtime-only dependencies (e.g., dynamic imports with variable paths).

How to Choose the Right Input for Serval

Serval accepts several ways to specify a change:

  • Git diff: The most common. Run serval diff HEAD~1 to analyze the last commit.
  • List of files: serval files src/foo.js src/bar.py treats the entire files as changed.
  • Branch comparison: serval diff main...feature compares two branches.

For precise results, ensure the codebase is clean and the language parser can handle all syntax. If you use a language with dynamic features (like Python’s eval or JavaScript’s require with variables), Serval may miss some dependencies. You can supplement with a serval.config file to manually add edges.

Choose the input that matches your workflow. For a quick pre-commit check, use a file list. For a CI pipeline, use a branch diff.

Common Problems and Misconceptions

Misconception: Serval predicts runtime behavior. It does not. It only finds static dependencies. If a change breaks a feature at runtime due to a data format change, Serval will not catch that unless the data schema is explicitly modeled.

Problem: False positives. Serval may flag files that are not actually affected because they import a changed module but only use a constant that didn’t change. This is conservative by design—better to run extra tests than miss a breakage.

Problem: False negatives with dynamic code. If your code uses reflection, dynamic imports, or plugin systems, Serval cannot see those edges. You must manually add them or accept the risk.

Problem: Large output. In a big monorepo, a change can produce hundreds of affected files. Use the --max-depth flag to limit the depth of traversal, or filter by test files to get a list of tests to run.

Comparing Serval to Other Tools

There are other impact analysis tools, but Serval’s key differentiator is its language-agnostic design and CLI-first approach. Tools like Impact (for Java) or madge (for JavaScript) are language-specific. Serval uses a unified AST representation, so you can analyze a mixed-language repo with one command.

Compared to IDE refactoring tools, Serval is faster and scriptable, but less precise because it doesn’t have type information. It also doesn’t require a build step, so it works on incomplete code.

If you need type-aware analysis, consider using a language server protocol (LSP) tool, but that requires a running language server and is often slower.

Costs and Performance Considerations

Serval is open-source and free to use. The main cost is computational: parsing a large codebase and building the dependency graph can take seconds to minutes. The tool caches the graph between runs, so subsequent analyses on the same codebase are faster. For a repository with 10,000 files, the initial parse might take 30 seconds, but incremental diffs take under a second.

Memory usage is proportional to the number of symbols. If you run out of memory, you can exclude directories with --ignore or increase the Node.js heap size (since Serval is built on Node).

Safety and Limitations

Serval is a static analyzer, so it is safe to run on any code without side effects. It does not modify files or execute code. However, its output is an estimate, not a guarantee. Always run your full test suite before deploying, especially for critical changes.

Known limitations:

  • Does not understand build-time code generation (e.g., protobuf, GraphQL codegen).
  • Does not track database migrations or external API contracts.
  • Cannot see through minified or obfuscated code.

To mitigate these, you can manually add dependencies in the config file or combine Serval with other checks like type checking and integration tests.

Alternatives to Serval

If Serval does not fit your needs, consider these alternatives:

  • IDE built-in refactoring preview: Good for small changes, but not scriptable.
  • Language-specific tools: e.g., pydeps for Python, dependency-cruiser for JavaScript.
  • Test impact analysis services: Some CI platforms (e.g., GitHub Actions with custom scripts) use a similar approach to select tests.
  • Manual review: For tiny changes, a careful code review is often sufficient.

Choose based on your language, budget, and need for automation.

Frequently Asked Questions

Does Serval require a build step?

No, Serval parses source files directly. It does not need to compile or link the code, which makes it fast and usable on incomplete codebases.

Can Serval analyze a monorepo with multiple languages?

Yes, Serval supports several languages and can analyze a mixed-language repository in one run. It treats each file according to its extension and builds a unified graph.

How accurate is Serval compared to running tests?

Serval is conservative—it often overestimates impact. It will rarely miss a static dependency, but it cannot catch runtime-only issues. Running tests is the only way to be sure.

Can I use Serval to decide which tests to run in CI?

Yes, that is a common use case. You can filter the output to test files and run only those. However, always run a minimal set of smoke tests as well, because Serval might miss dynamic dependencies.

Does Serval support TypeScript type dependencies?

Serval parses TypeScript and understands import/export statements, but it does not perform full type checking. It will not detect dependencies that only exist through type interfaces (e.g., structural typing). For type-aware analysis, use a tool that leverages the TypeScript compiler API.

Is Serval safe to run on untrusted code?

Serval only parses and analyzes code; it does not execute it. However, the parser itself could have vulnerabilities, so it is best to run it in a sandboxed environment if you are analyzing untrusted code.

Related

Formula used
in t | Finish time | min | 50 | 0
in d | Distance | km | 10 | 0
out pace | Average pace | min/km | t / d | 2
out speed | Average speed | km/h | d / (t / 60) | 2

Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.