GitHub Action v1.0.1 is live on the Marketplace

Detect
the invisible.

Debtlint finds duplicated and near-duplicate logic across your codebase, before AI-generated copy-paste quietly turns into technical debt. Fast, programmatic, language-agnostic.

See how it works
  • Open source · Apache 2.0
  • Written in Rust
  • No LLM, no API cost
src/pricing.py 3 duplicated copies
zsh · debtlint
Language-agnostic BPE + Winnowing Terminal & JSON reports GitHub Action AI agent skill
The problem

Technical debt now hides in plain sight.

Coding assistants are fast, and forgetful. Existing utilities get rewritten, business patterns get repeated, logic fragments across files. Nobody notices until the same bug has to be fixed in five places.

Duplicated code

The same logic copied across files, drifting apart one tweak at a time.

Bugs, replicated

One defect, many hiding places. Fixing it once is never enough.

Rising cost of change

Every feature touches more places than it should. Velocity quietly drops.

Harder maintenance

Onboarding slows, reviews get longer, refactors get riskier.

Our approach

Why not simply compare files?

The obvious answers don't hold up on a real codebase. Each one trades away precision, portability or speed.

1

Text comparison

Brittle. Rename a variable or reformat a line and the match disappears.

Too sensitive
2

Syntax analysis (AST)

Precise, but bound to one language and its parser. Every new language is a new project.

Language-locked
3

Compare every region

Pairwise comparison explodes as the repository grows. It simply doesn't scale.

Too expensive
The Debtlint way

Let the code teach us its own vocabulary.

Byte Pair Encoding learns the recurring patterns of your codebase, then Winnowing fingerprints the token stream. The result: tolerant to small edits, independent of any grammar, and fast enough for every pull request.

  • TolerantFinds near-duplicates, not just exact copies
  • AgnosticNo parser, no grammar, any text-based language
  • ScalableFingerprints instead of all-pairs comparison
How it works

Four steps from source to signal.

A compact pipeline, inspired by compression and plagiarism-detection research, tuned for source code.

debtlint.config.json
{
  "src": ".",
  "excludes": ["target", "node_modules", ".git"]
}
Byte Pair Encoding: frequent pairs become single tokens 128 vocabulary entries

Token 129 appears in n files, at n places, a recurring structure, found without understanding the language.

a.rs fn add(x, y) { return x + y; }
b.rs fn incr(x, y) { return x + y; }
fingerprint kept by the window shared fingerprint → candidate duplicate
debtlint --report-format json
[
  { "file": "src/pricing.py", "start_line": 34, "end_line": 42 },
  { "file": "src/pricing.py", "start_line": 42, "end_line": 50 },
  { "file": "src/pricing.py", "start_line": 50, "end_line": 58 }
]

Every duplicated block comes with its file and line range. A human-readable summary by default, JSON for CI and agents. Illustrative output.

Why teams pick it

Built to disappear into your workflow.

Automated

100% programmatic.

No LLM calls, no tokens to buy, no latency to wait on. Debtlint is deterministic, local and cost-efficient. Run it on every commit.

Agnostic

Any language.

No grammar to maintain. If it's text, it's in scope.

Tunable

Adjustable sensitivity.

Decide how small a duplicate has to be to matter with --shingle-size. Drag the slider.

--shingle-size50
3 / 6 duplicate blocks reported · illustration
Extensible

Yours to shape.

Save and reuse your vocabulary, export encoded sequences, tune every threshold, and build on an open Apache 2.0 core.

CI-ready

One YAML away.

Drop the GitHub Action into a workflow and every pull request gets a clear, actionable comment.

AI-native

A guardrail for your agents.

Ship an agent skill that reruns Debtlint after each generation and refactors until the report is clean.

Integrations

Where your code is written. Where it's reviewed.

GitHub Action

Analyze every pull request and get the report right where reviewers look.

.github/workflows/debtlint.yml
name: Check duplication

on:
  pull_request:
    branches: [main]

jobs:
  debtlint:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - name: Run debtlint
        uses: PoCInnovation/Debtlint@v1
        with:
          vocab-path: .debtlint-vocab.json

…and a comment reviewers can act on.

Duplicated copies, file and line range, right in the PR conversation.

github-actions Bot commented just now

Debtlint suggestion

3 duplicated copies

src/pricing.py · lines 34 to 42
def calculate_price_001(price, quantity):
    total = price * quantity
    tax = total * 0.20
    final_price = total + tax
    print(f"Total: {final_price}")
    return final_price
src/pricing.py · lines 42 to 50
def calculate_price_002(price, quantity):
    total = price * quantity
    tax = total * 0.20
    final_price = total + tax
    print(f"Total: {final_price}")
    return final_price
For AI agents

Extend Debtlint to your AI agents.

Generation becomes codebase-aware. The agent checks what already exists, removes what it just duplicated, and only stops when the report is clean, or after three iterations.

debtlint --report-format json
  1. 1Generate code
  2. 2Run Debtlint (JSON)
  3. 3Refactor the duplicates
  4. 4Re-run until clean
Debtlint & its rivals

Made for the way code is written today.

Classic clone detectors such as JSCPD are great tools. Debtlint takes a different path, one designed for AI-assisted codebases.

JSCPD Debtlint
DetectionToken matching with language-specific tokenizersBPE vocabulary learned from your code + Winnowing fingerprints
Language supportPer-format support, extended release by releaseLanguage-agnostic by design, no parser needed
SensitivityDetection modes and minimum thresholdsFine-grained: --shingle-size, --window-size, --min-tokens
Pull request feedbackReports via CI scriptingNative GitHub Action posting a PR comment
AI agentsIntegrate by handReady-to-use agent skill and JSON output
Installnpmcargo install debtlint · single native binary

Comparison based on default setups and public documentation at the time of writing.

Get started

From zero to report in under a minute.

1

Install

cargo install debtlint
2

Create debtlint.config.json

{
  "src": ".",
  "excludes": ["target", "node_modules", ".git"]
}
3

Train once, reuse everywhere (optional)

debtlint --save-vocab .debtlint-vocab.json
4

Run it

debtlint --load-vocab .debtlint-vocab.json

CLI reference

FlagDefaultDescription
--vocab-size1000Max vocabulary size (base + merges)
--min-frequency2Min pair frequency to create a merge
--load-vocabn/aLoad a vocabulary JSON, skip BPE training
--save-vocabn/aSave the trained vocabulary as JSON
--output-encodedn/aWrite encoded token sequences as JSON
--shingle-size50Shingle size in tokens (Winnowing)
--window-size3Sliding window size in shingles
--min-tokens20Minimum duplicated block length in tokens
--report-formattexttext or json

Clean code. Less debt.

Install Debtlint, add the Action to your next pull request, and make technical debt visible before it spreads.

Star on GitHub