Node.js API
August 5, 2026 ยท View on GitHub
StopSlop ships a typed ESM API for tools that need findings and metrics in
memory instead of a CLI report. It requires Node.js ^20.19.0 || >=22.12.0.
Analyze with defaults
Resolve configuration before calling analyze:
import { analyze, resolveConfig } from 'stopslop';
const result = await analyze(process.cwd(), resolveConfig(undefined));
for (const finding of result.findings) {
console.log(finding.kind, finding.file, finding.line, finding.message);
}
console.log({
score: result.slop.score,
level: result.slop.level,
errors: result.errors,
notes: result.notes,
});
findings contains the issues that should fail the current gate. slop always
describes the complete analyzed repository. Check errors before trusting a
result; notes explains non-fatal skips by project-level engines.
Load stopslop.json
loadConfig reads stopslop.json from the analysis root and returns the
resolved defaults plus overrides:
import { analyze, loadConfig } from 'stopslop';
const root = process.cwd();
const result = await analyze(root, loadConfig(root));
To build configuration in code, pass the user-facing shape to resolveConfig:
import { analyze, resolveConfig, type StopSlopConfig } from 'stopslop';
const input: StopSlopConfig = {
cognitiveComplexity: 20,
duplicates: { minTokens: 100, minLines: 10 },
deadCode: { files: false },
};
const result = await analyze(process.cwd(), resolveConfig(input));
Unknown fields and invalid values throw instead of being ignored.
Compare with a Git revision
analyzeGitBase returns only findings absent from the selected revision while
retaining the current repository's complete score:
import { analyzeGitBase, loadConfig } from 'stopslop';
const root = process.cwd();
const result = await analyzeGitBase(root, 'origin/main', loadConfig(root));
if (result.errors.length > 0) process.exitCode = 2;
else if (result.findings.length > 0) process.exitCode = 1;
The ref must resolve in the local Git repository. StopSlop creates a temporary detached worktree; it does not switch the current branch or modify the index.
Extend the analyzer list
Pass a third argument to append a custom analyzer to the built-in set:
import {
analyze,
defaultAnalyzers,
resolveConfig,
type Analyzer,
} from 'stopslop';
const custom: Analyzer = {
name: 'project-policy',
analyzeFile(file) {
return file.source.includes('DO NOT SHIP')
? [{
kind: 'unused-file',
file: file.relPath,
symbol: 'DO NOT SHIP',
line: 1,
severity: 'warn',
message: 'Unresolved project marker',
}]
: [];
},
};
const result = await analyze(
process.cwd(),
resolveConfig(undefined),
[...defaultAnalyzers(), custom],
);
Custom analyzers currently return the published Finding union, so use an
existing finding kind for integrations. Treat that surface as pre-1.0; see the
compatibility policy.