dupelint Notify me

Proof-carrying deduplication · built for the AI era

It's just a little
duplicate code.
Until it's a full rewrite.

You'll fix it later. You won't. It compounds. Silent, harmless-looking. Until the refactor you keep dodging is a ground-up rewrite: a senior engineer, a lost year, a bill nobody budgeted for. And AI writes it faster than any team can catch.

dupelint is the only engine that proves duplication away instead of guessing. And the first with the math to catch Type-5 — subsumption — soundly, where every other tool approximates it or throws it away.

read-only · never modifies your files · operated by ROI PIPE LLC

result.json · CPython 3.12.3
{
"types": {
"1_exact": 33,
"2_renamed": 49,
"3_gapped": 17,
"4_semantic": 0,
"5_subsumption": 3,
"total": 102
},
"duplicates": [
{ "action": "remove", "unit": "class",
"remove": "SocketThread (…/test_ssl.py:1627)",
"use": "SocketThread (…/functional.py:158)" },
{ "action": "remove",
"remove": "_is_leap (Lib/_pydatetime.py:49)",
"use": "isleap (Lib/calendar.py:141)" },
{ "action": "reuse", Type-5
"inside": "iconcat (Lib/operator.py:349)",
"reuse": "iadd (Lib/operator.py:339)" }
… +99 more
]
}
SOUND 0 false positives · by construction

the actual output, not a mockup

Proven on CPython

Over-detect. Then prove down to certainty.

One pass across the CPython standard library and tooling. The net flags everything that could be a clone; the sound sieve discards everything it cannot prove. Nothing reaches a verdict without an unconditional proof.

candidates flagged
2,346,842
raw suspects across 5 clone types
sound duplicates
102
proven, with a ready consolidation
false-positive verdicts
0
by construction, not by tuning
63,186 functions 13,970 classes 1,996 files 8 skipped (unparseable) ~14.6 min single full-spectrum pass

What it solves

Speed up, slim down, stop the rewrite.

Duplicate code is the one debt that compounds on its own. And AI now writes it faster than any team can catch. Remove it, with proof, and the payoff lands in five places at once.

Speed
Time to market

Reuse what exists. AI stops re-deriving the primitives it already built. Less to write, review, and test.

Maintainability
Change once

One source of truth. Not the same fix in eight places, and the one you'd have missed.

Cost
Fewer tokens

Don't regenerate what exists or reload bloat into context. The savings compound on every run.

AI
No blind spots

AI has no memory of what it wrote. dupelint is the one it lacks: ask before it writes, sweep after it merges.

Trust
Safe to act on

Zero false positives, by proof. Consolidate with confidence, on a branch behind your tests.

The clone taxonomy

Five types, ordered by how hard they are to prove.

The standard taxonomy stops at four. The fifth — subsumption — others detect only to discard, or approximate and get wrong. The math to catch it soundly is ours.

01
Exact

Identical modulo whitespace and comments.

Discovered by J. Johnson · 1993

02
Renamed

Identical up to consistent renaming of identifiers.

Discovered by B. Baker · 1993-95

03
Gapped

Statements inserted or removed; the shared run still proven equivalent.

Discovered by Baxter et al. · 1998

04
Semantic

Same behavior, different code. No text overlap required.

Discovered by Komondoor & Horwitz · 2001

05
Subsumption SOUND

A fifth clone type beyond the standard four — the containment relation other tools approximate or throw away. We’re the first with the math to catch it soundly, zero false positives. The certainty is yours; the method is ours.

First sound detection by Ronald C. Smart · 2026-06-03

How it decides

Math first. The model only speaks where math can't.

Deterministic by design

The verdict step is compute, not a model. The same input gives the same answer, every time. A sound verdict is reserved for an unconditional proof, so it carries no false positives.

Two bases, never blurred

sound. An unconditional proof, safe to act on: apply on a branch, behind your tests. bounded. Proven only within a stated domain; flagged for you to verify. The two are never folded together.

Read-only & secret-safe

It reads code as structure and never modifies your files. Verdicts are proven statically, not by running your code. The only execution is a sandboxed check of pure-arithmetic functions, with no file, network, or import access, used only to rule out false matches. Secret-looking files are rejected on ingest, and the output is data: a verdict and a suggested rewrite you choose to apply.

The answer, not the recipe

A response says these are equivalent or inner  outer. It never carries how that was decided. You get the verdict; the derivation stays ours.

Safe by design

It reads. You decide. Your tests confirm.

dupelint never modifies your code. It returns a verdict and a suggested rewrite. Scanning an entire codebase changes nothing. Applying is yours, done the safe way.

Read-only

Never modifies your files. A scan reads your code and changes nothing on your side; verdicts come from static analysis, not from running it.

Decides, never does

The output is data: a verdict and a suggested rewrite. You apply it, on your terms.

Apply behind tests

Branch → apply → run your tests → review → merge. Never straight to production.

Unprovable → candidate

Anything the proof can't close is flagged for review. Never marked sound, never guessed.

Full terms of use → dupelint.com/terms

Privacy

We never store your code.

Your code is read in memory to compute the verdict, then dropped. It is never written to disk, and no copy is kept. Here's the full lifecycle of a scan, limits included.

In transit

Encrypted over TLS on every request. Your code never travels in the clear.

In memory

Held in RAM only, for the moment of the scan, read to compute the verdict. Never written to disk, and swap is off so it cannot leak there.

Dropped after

When the scan finishes, your code is released from memory. No stored copy, on disk or off.

In the EU

Processed in EU data centers, under GDPR. Never in US data centers.

Full transparency: we store nothing and never write your code to disk. We also won't overclaim. RAM holds the bytes only until they are overwritten, and we don't own the physical host, so we don't call it "unrecoverable." Hardware-encrypted memory (confidential computing) is on our roadmap to seal the in-scan window itself.

Transparency

Where it runs, and who else is involved.

You can find most of this out yourself. We'd rather state it up front.

Where it runs

Scans run on servers we operate at Hetzner Online GmbH, a German company, in their German data centers. Processing stays in the EU under GDPR. Hetzner is ISO 27001 certified and we hold an Article 28 data processing agreement with them. They provide the hardware and network — they hold no account on our machines and no access to scan contents.

No model sees your code

The verdict is computed, not inferred. Your code is never sent to a language model, an inference API, or any third party. There is no model provider in the processing chain, so there is nothing to opt out of and no training question to ask.

Who else is involved

Vendor Purpose Data Region
Hetzner Online GmbH Compute and hosting for scan execution Code held in memory during the scan, never written to disk Germany
Stripe, Inc. Billing and payment processing Billing identity, payment method United States

Your code goes to exactly one of these: the machines we run in Germany. Stripe sees billing details only and never touches code. Nothing in the scan path leaves the EU. Vendors used for account email and SMS are listed in our privacy policy — none of them sit in the scan path. We publish a changelog entry whenever this list changes.

Roadmap

Proven, not promised. One unit at a time.

Python is in development, and already proving itself: its functions and classes are proven today, matched across all five clone types, sound, with zero false positives. More units are landing one at a time, and every language ships the same way — proven, or not at all. Not a demo: see it run across the entire CPython standard library, the real output.

See the CPython scan ↗

A unit ships only when all five clone types are sound for it, and each language grows unit by unit. Expand a language to see what’s proven, what’s next, and what’s planned.

01Python
in development

Code units

  • Functions & methodsproven
  • Classesproven
  • Module-level codenext
  • Statement blocksplanned
  • Constants & data structuresplanned
  • Lambdas & comprehensionsplanned
  • Whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound.

02TypeScript / JavaScript
planned

Code units

  • Functions & methodsplanned
  • Classesplanned
  • Interfaces & type aliasesplanned
  • JSX components & hooksplanned
  • Arrow functions & closuresplanned
  • Constants & object literalsplanned
  • Modules & whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound.

03PHP
planned

Code units

  • Functions & methodsplanned
  • Classesplanned
  • Traits & interfacesplanned
  • Closures & arrow functionsplanned
  • Statement blocksplanned
  • Constants & arraysplanned
  • Whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound.

04Go
planned

Code units

  • Functions & methodsplanned
  • Structsplanned
  • Interfacesplanned
  • Func literals & closuresplanned
  • Statement blocksplanned
  • Constants & dataplanned
  • Packages & whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound. Go’s if err != nil is detected but never flagged for removal — mandatory duplication.

05Rust
planned

Code units

  • Functions & methodsplanned
  • Structs & enumsplanned
  • Traits & impl blocksplanned
  • Macrosplanned
  • Closuresplanned
  • Constants & dataplanned
  • Modules & whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound.

06Java
planned

Code units

  • Methodsplanned
  • Classesplanned
  • Interfacesplanned
  • Enums & recordsplanned
  • Lambdas & streamsplanned
  • Constants & fieldsplanned
  • Whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound. Getters/setters and POJO/DTO boilerplate are detected but never flagged for removal.

07C#
planned

Code units

  • Methodsplanned
  • Classes & structsplanned
  • Interfacesplanned
  • Propertiesplanned
  • LINQ & lambdasplanned
  • Constants & fieldsplanned
  • Whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound.

08Kotlin
planned

Code units

  • Functions & methodsplanned
  • Classes & data classesplanned
  • Interfacesplanned
  • Extension functionsplanned
  • Lambdasplanned
  • Objects & companionsplanned
  • Whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound.

09Swift
planned

Code units

  • Functions & methodsplanned
  • Classes & structsplanned
  • Protocols & extensionsplanned
  • Enumsplanned
  • Closuresplanned
  • Constants & dataplanned
  • Whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound.

10Dart
planned

Code units

  • Functions & methodsplanned
  • Classesplanned
  • Mixins & extensionsplanned
  • Closuresplanned
  • Statement blocksplanned
  • Constants & collectionsplanned
  • Whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound.

11Lua
planned

Code units

  • Functionsplanned
  • Tables & metatablesplanned
  • Closuresplanned
  • Statement blocksplanned
  • Constants & tablesplanned
  • Whole chunksplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound.

12Shell
planned

Code units

  • Functionsplanned
  • Pipelines & command blocksplanned
  • Here-docsplanned
  • Constants & variablesplanned
  • Whole scriptsplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound.

13C
planned

Code units

  • Functionsplanned
  • Structs & unionsplanned
  • Enums & typedefsplanned
  • Macros (#define)planned
  • Statement blocksplanned
  • Constants & dataplanned
  • Whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound. Header-vs-implementation declarations are detected but never flagged for removal.

14C++
planned

Code units

  • Functions & methodsplanned
  • Classes & structsplanned
  • Templatesplanned
  • Macrosplanned
  • Lambdasplanned
  • Constants & dataplanned
  • Namespaces & whole filesplanned

Every unit is matched across all five clone types — exact · renamed · gapped · semantic · subsumption — and nothing ships until it is proven sound.

·HTML · CSS · XML · YAML · Markdown
planned

Units

  • Rules & selectorsplanned
  • Components & templatesplanned
  • Config keys & valuesplanned
  • Whole documentsplanned

Parsed and canonicalized first (computed CSS, parsed YAML, canonical XML, rendered DOM), then matched — duplication proven on the meaning, not the text.

+ more languages — on request

For coding agents

Built for the agent loop.

Generation is fast and forgetful. It reinvents what it already wrote. dupelint is the primitive that catches it, with an answer solid enough to act on. On a branch, behind your tests.

before

Query before it writes

A worker checks whether the code it’s about to write — a function or a class — already exists before emitting it. Prevent the duplicate at the source.

during

Supervisor sweep

A coordinator scans merged output in parallel, catching cross-worker duplication no single worker can see.

after

Post-task refactor

When the task closes, batch-scan and consolidate. A typical repo clears in under a minute.

Stop shipping duplicate code.

Point dupelint at your codebase, or wire it into your agents. The verdict is sound, the proof is ours, and your code stays slim.

PSF Supporting Member

Built on Python

dupelint runs on CPython, and we proved it on CPython's own source. As a proud PSF Supporting Member, we back the Python Software Foundation, the nonprofit that stewards the language everything here is built on.