Knip-backed rules — dependencies hygiene and dead code.
Knip (depcheck + ts-prune are archived as of 2025, both recommend knip) reports
unused/unlisted dependencies AND unused files/exports in one tool. We run it
with --no-exit-code so the process never fails on findings — the JSON is the
source of truth, and a genuine tool crash surfaces as a non-zero exit that the
base treats as an env-failure (knip exit 2 = exception, not findings).
Knip's JSON --reporter json shape (v5):
{"files": [...], "issues": [{"file": "...", "dependencies": [...],
"unlisted": [...], "exports": [...], "types": [...], ...}, ...]}
files is the list of unused files; each issues entry groups the other
issue kinds per source file.
NodeDeadCodeRule
Bases: _KnipRule
Score unused files + unused exports (knip).
Mirrors the Python DeadCodeRule (category lint): 100 - items*10.
Source code in packages/axm-audit/src/axm_audit/core/rules/node/knip.py
| Python |
|---|
| @register_rule("lint", framework=Framework.NODE)
class NodeDeadCodeRule(_KnipRule):
"""Score unused files + unused exports (knip).
Mirrors the Python ``DeadCodeRule`` (category ``lint``): ``100 - items*10``.
"""
@property
def rule_id(self) -> str:
"""Unique identifier (shared with the Python dead-code rule)."""
return "QUALITY_DEAD_CODE"
def score_output(self, parsed: object, project_path: Path) -> CheckResult:
"""Score by the count of unused files + unused exports/types."""
count = _count_unused_files(parsed) + _sum_issue_kinds(parsed, _DEAD_KINDS)
score = max(0, 100 - count * 10)
passed = score >= PASS_THRESHOLD
return CheckResult(
rule_id=self.rule_id,
passed=passed,
message=f"Dead code: {score}/100 ({count} unused)",
severity=Severity.WARNING if not passed else Severity.INFO,
score=score,
details={"unused_count": count},
fix_hint="Remove unused files / exports" if count else None,
)
|
rule_id
property
Unique identifier (shared with the Python dead-code rule).
score_output(parsed, project_path)
Score by the count of unused files + unused exports/types.
Source code in packages/axm-audit/src/axm_audit/core/rules/node/knip.py
| Python |
|---|
| def score_output(self, parsed: object, project_path: Path) -> CheckResult:
"""Score by the count of unused files + unused exports/types."""
count = _count_unused_files(parsed) + _sum_issue_kinds(parsed, _DEAD_KINDS)
score = max(0, 100 - count * 10)
passed = score >= PASS_THRESHOLD
return CheckResult(
rule_id=self.rule_id,
passed=passed,
message=f"Dead code: {score}/100 ({count} unused)",
severity=Severity.WARNING if not passed else Severity.INFO,
score=score,
details={"unused_count": count},
fix_hint="Remove unused files / exports" if count else None,
)
|
NodeDependencyRule
Bases: _KnipRule
Score unused + unlisted dependency hygiene (knip).
Mirrors the Python DependencyHygieneRule: 100 - issues * 10.
Source code in packages/axm-audit/src/axm_audit/core/rules/node/knip.py
| Python |
|---|
| @register_rule("deps", framework=Framework.NODE)
class NodeDependencyRule(_KnipRule):
"""Score unused + unlisted dependency hygiene (knip).
Mirrors the Python ``DependencyHygieneRule``: ``100 - issues * 10``.
"""
@property
def rule_id(self) -> str:
"""Unique identifier for this rule."""
return "DEPS_HYGIENE"
def score_output(self, parsed: object, project_path: Path) -> CheckResult:
"""Score by the count of unused/unlisted dependency issues."""
count = _sum_issue_kinds(parsed, _DEP_KINDS)
score = max(0, 100 - count * 10)
passed = score >= PASS_THRESHOLD
return CheckResult(
rule_id=self.rule_id,
passed=passed,
message=f"Dependency hygiene: {score}/100 ({count} issues)",
severity=Severity.WARNING if not passed else Severity.INFO,
score=score,
details={"issue_count": count},
fix_hint="Remove unused / declare unlisted deps" if count else None,
)
|
rule_id
property
Unique identifier for this rule.
score_output(parsed, project_path)
Score by the count of unused/unlisted dependency issues.
Source code in packages/axm-audit/src/axm_audit/core/rules/node/knip.py
| Python |
|---|
| def score_output(self, parsed: object, project_path: Path) -> CheckResult:
"""Score by the count of unused/unlisted dependency issues."""
count = _sum_issue_kinds(parsed, _DEP_KINDS)
score = max(0, 100 - count * 10)
passed = score >= PASS_THRESHOLD
return CheckResult(
rule_id=self.rule_id,
passed=passed,
message=f"Dependency hygiene: {score}/100 ({count} issues)",
severity=Severity.WARNING if not passed else Severity.INFO,
score=score,
details={"issue_count": count},
fix_hint="Remove unused / declare unlisted deps" if count else None,
)
|