How React Doctor's Offline Mode Calculates Scores Without API Calls
React Doctor computes quality scores locally by analyzing diagnostic rules and applying penalty calculations, eliminating the need for network requests when the --offline flag is enabled.
React Doctor is a CLI tool that audits React applications for performance anti-patterns and dead code. When running in environments without internet access or when explicitly configured for isolation, the tool switches to a deterministic local scoring algorithm that processes diagnostic data entirely on your machine.
How the CLI Activates Offline Scoring
The offline workflow begins with option resolution in src/cli.ts. When you pass the --offline flag or when the tool detects a CI environment, the resolveCliScanOptions function (around line 176) merges CLI flags with user configuration to set ResolvedScanOptions.offline to true.
This boolean flows through the scan orchestration in src/scan.ts, where a conditional check at lines 817-819 selects the appropriate scoring path:
const scoreResult = options.offline
? calculateScoreLocally(diagnostics)
: await calculateScore(diagnostics);
When options.offline is true, the execution bypasses the async API call entirely and invokes the synchronous calculateScoreLocally function instead.
The Local Scoring Algorithm
The pure-JavaScript implementation in src/utils/calculate-score-locally.ts converts diagnostic findings into a numeric score without external dependencies. The function aggregates linting results and dead-code analysis into a final rating through three distinct phases.
Extracting Unique Rule Sets
First, the algorithm analyzes the collected Diagnostic objects using collectUniqueRuleSets to identify distinct error and warning categories. Rather than counting individual occurrences, it focuses on unique rule violations to determine the penalty scope.
Applying the Penalty Formula
The scoring calculation (lines 49-53) uses constants defined in src/constants.ts:
- PERFECT_SCORE: 100 (baseline)
- ERROR_RULE_PENALTY: Deducted for each unique error rule
- WARNING_RULE_PENALTY: Deducted for each unique warning rule
The formula subtracts the total penalty from the perfect score and clamps the result to a minimum of 0:
const score = Math.max(0, PERFECT_SCORE -
(uniqueErrors * ERROR_RULE_PENALTY) -
(uniqueWarnings * WARNING_RULE_PENALTY)
);
Mapping Scores to Labels
The numeric result maps to human-readable quality grades:
- Great: High scores indicating minimal issues
- Needs work: Moderate scores suggesting improvements required
- Critical: Low scores requiring immediate attention
Fallback Behavior When APIs Fail
Even when running in standard mode, React Doctor includes defensive logic in src/utils/calculate-score.ts. The calculateScore function attempts remote evaluation via tryScoreFromApi, but automatically falls back to calculateScoreLocally if the network request fails or times out.
This ensures that CI pipelines never fail due to network connectivity issues, always receiving a deterministic score derived from local diagnostics.
Implementation Examples
Trigger offline mode via command line:
# Scan without network requests, score calculated locally
npx react-doctor scan . --offline
Use offline scoring programmatically:
import { scan } from "react-doctor";
// Force local calculation regardless of network status
await scan("./my-app", { offline: true });
Access the raw scoring utility directly:
import { calculateScoreLocally } from "react-doctor/src/utils/calculate-score-locally";
import type { Diagnostic } from "react-doctor/src/types";
const diagnostics: Diagnostic[] = [
// Populate from lint/dead-code output
];
const { score, label } = calculateScoreLocally(diagnostics);
console.log(`Score: ${score} – ${label}`);
When offline mode is active, the CLI displays the banner defined by OFFLINE_MESSAGE in src/constants.ts: "Score calculated locally (offline mode)."
Summary
- Offline activation occurs through
--offlineflags or CI auto-detection insrc/cli.ts, stored inResolvedScanOptions.offline - Score calculation happens in
src/utils/calculate-score-locally.tsusing penalty-based mathematics without HTTP requests - Algorithm details: Subtracts
ERROR_RULE_PENALTYandWARNING_RULE_PENALTYmultipliers fromPERFECT_SCORE(100), clamps to ≥0 - Graceful degradation: The remote scoring function in
src/utils/calculate-score.tsautomatically falls back to local calculation when APIs are unreachable - Zero network traffic: No calls to
https://www.react.doctor/api/scoreoccur when offline mode is enabled
Frequently Asked Questions
How does the penalty calculation work in offline mode?
The algorithm counts unique error and warning rules found in your diagnostics, then applies the formula: score = 100 - (uniqueErrors × errorPenalty) - (uniqueWarnings × warningPenalty). The result is clamped to zero if penalties exceed 100, producing a score between 0 and 100.
What happens if I run offline mode but the API is actually available?
When options.offline is true, the code in src/scan.ts (lines 817-819) explicitly routes to calculateScoreLocally, completely skipping the tryScoreFromApi call. Even if the network is healthy, no HTTP requests are attempted, ensuring complete isolation as requested.
Are offline scores comparable to API-generated scores?
Offline scores use the same PERFECT_SCORE baseline of 100 but may differ slightly from API-generated scores because the remote algorithm might weight rules differently or include additional heuristics. However, the local calculation provides a consistent, deterministic baseline for CI/CD pipelines and air-gapped environments.
Can I customize the penalty constants for local scoring?
The penalty values (ERROR_RULE_PENALTY, WARNING_RULE_PENALTY) are defined as constants in src/constants.ts. Currently, these are hardcoded into the package build, but you can view these values to understand how rule severity impacts your final score calculation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →