A command-line tool for measuring code metrics with tree-sitter. It scans a project and reports high-risk files, functions, and React components so you can spot code that is worth refactoring. A programmatic API is also available.
# Run without installing
npx code-gauge path/to/project
# Or install globally
npm install -g code-gauge
code-gauge path/to/projectThe CLI scans JavaScript, JSX, TypeScript, TSX, Python, and Go files. By default it skips generated, vendor, test, and tool directories, prints a summary, and lists the highest-risk findings. TypeScript project metrics and React component classification turn on automatically when a tsconfig.json is found.
| Option | Description |
|---|---|
--config <path> |
Use this config file instead of the auto-detected code-gauge.config.json. |
--include-tests |
Include test files and test directories. |
--tsconfig <path> |
Use this tsconfig.json instead of the auto-detected one. |
--max-findings <n> |
Maximum number of findings to print (default: 20). |
--json |
Print machine-readable JSON. |
--fail-on-risk |
Exit with code 1 when any high-risk finding is reported. |
--fail-on-error |
Exit with code 1 when any file or directory cannot be scanned. |
--<metric>-threshold <n> |
Override a risk threshold (see below). |
A finding is reported when a measured value is greater than or equal to its threshold. Every threshold can be set on the command line (e.g. --file-loc-threshold 400) or in a config file; the command line wins over the config file, which wins over the defaults.
code-gauge looks for code-gauge.config.json by walking up from the target directory (override with --config). The following config reproduces every built-in default:
{
"thresholds": {
"fileLoc": 500,
"functionLoc": 120,
"componentLoc": 350,
"cognitive": 25,
"cyclomatic": 20,
"call": 50,
"import": 25,
"fanOut": 10,
"parameter": 8,
"duplicateBlock": 2,
"transitiveDependency": 25,
"structuralBreadth": 8,
"structuralCoordination": 300,
"stateMutation": 50,
"duplicateSymbolGroup": 5
},
"languageThresholds": {
"python": { "stateMutation": 90, "structuralCoordination": 350 },
"react": { "import": 30 }
},
"maxFindings": 20,
"includeTests": false,
"failOnRisk": false,
"failOnError": false
}| Threshold | CLI flag | Reports when a … |
|---|---|---|
fileLoc |
--file-loc-threshold |
file's code LOC is large. |
functionLoc |
--function-loc-threshold |
function's physical LOC span is large. |
componentLoc |
--component-loc-threshold |
React component's physical LOC span is large. |
cognitive |
--cognitive-threshold |
function's cognitive complexity is high. |
cyclomatic |
--cyclomatic-threshold |
function's cyclomatic complexity is high. |
call |
--call-threshold |
function makes many calls. |
import |
--import-threshold |
file has many unique import sources. |
fanOut |
--fan-out-threshold |
function calls many other in-file functions. |
parameter |
--parameter-threshold |
function declares many parameters. |
duplicateBlock |
--duplicate-block-threshold |
file contains copy-pasted code blocks. |
transitiveDependency |
--transitive-dependency-threshold |
file transitively reaches many local files. |
structuralBreadth |
--structural-breadth-threshold |
file coordinates many structural concerns. |
structuralCoordination |
--structural-coordination-threshold |
file's structural coordination score is high. |
stateMutation |
--state-mutation-threshold |
file mutates state heavily. |
duplicateSymbolGroup |
--duplicate-symbol-group-threshold |
file shares many duplicated symbols with others. |
Some metrics distribute very differently by language or file type, so a single global threshold either
over-flags one language or under-flags another. languageThresholds overrides individual thresholds for a
profile without repeating the whole set. Each file resolves its thresholds as base → its language profile →
the react profile (the last applies when the file contains a React component), so later profiles win.
Valid profile keys are javascript, jsx, typescript, tsx, python, go, and react. Built-in
overrides raise stateMutation and structuralCoordination for Python (every binding is an assignment, so
these run far higher than in TypeScript) and raise import for React files (which pull in many components).
Anything you specify is merged on top of the built-in overrides, so { "python": { "stateMutation": 8 } }
restores the global value for Python while keeping the other built-in adjustments.
{
"languageThresholds": {
"python": { "stateMutation": 120 },
"react": { "componentLoc": 400, "import": 35 }
}
}Command-line --<metric>-threshold flags set the global base only; use the config file for per-language tuning.
- Physical LOC, code lines, comment-only lines, and blank lines
- Function and class counts
- Cyclomatic and cognitive complexity (per function and maximum)
- Nesting depth
- Intra-file call graph metrics: call counts, fan-in/fan-out, recursion, call depth, and parameter counts
- Within-file structural duplication: copy-pasted code blocks (distinct from cross-file duplicate symbol names)
- File coupling (imports/exports) and cohesion (shared function identifiers)
- Architecture metrics: transitive local dependencies, structural coordination and breadth, state mutation, and cross-file duplicate symbols
- TypeScript type-shape metrics: annotations, aliases, interfaces, generics, unions, intersections, assertions, and conditional types
- Halstead metrics and the maintainability index
Built-in parsers cover JavaScript, JSX, TypeScript, TSX, Python, and Go. Additional tree-sitter grammars can be registered with TreeMeasurer.registerLanguage.
import { measureCode } from 'code-gauge';
const metrics = measureCode(
`
function score(value) {
if (value < 0 || value == null) {
return 0;
}
return value > 10 ? 10 : value;
}
`,
{ language: 'javascript' }
);
console.log(metrics.cyclomaticComplexity);