Duplifinder
The "Batteries Included" duplicate code detector. Detect and refactor duplicate Python classes, functions, and async defs—plus text and tokens across other languages—to keep your codebase lean and mean.
⚡ Quick Start (The "5-Minute Rule")
Prerequisites
- Python 3.12+
pip(oruv/poetry)
Installation
pip install duplifinder
Usage Example
Get instant feedback on your current directory:
# Standard scan (AST + Token)
duplifinder .
# Watch mode for live feedback (Best for dev loop)
duplifinder . --watch --preview
# Scan with parallel processing and detailed audit logs
duplifinder src/ --parallel --audit --verbose
Pre-commit Hook
Add to your .pre-commit-config.yaml to block duplicates before they merge:
- repo: https://github.com/dhruv13x/duplifinder
rev: v11.0.0 # Use latest version
hooks:
- id: duplifinder
args: ["--fail", "--dup-threshold=0.05"]
✨ Features (The "Why")
Core Capabilities
- AST-Powered Detection: Precision finding for
ClassDef,FunctionDef, andAsyncFunctionDef(Python). It sees through variable name changes. - Multi-Language Support: Token and text-based similarity checks for Python, JavaScript, TypeScript, and Java.
- Smart Watch Mode: "Live" scanning that updates results instantly as you modify files.
Performance & Security
- Parallel Processing: Blazing fast scans using multi-threading or multi-processing (GIL-aware) with
--paralleland--use-multiprocessing. - Smart Caching: Skips unchanged files to dramatically speed up re-scans.
- Audit Logging: Enterprise-grade JSONL trails for file access and scan operations.
Developer Experience
- Automated Refactoring Suggestions: "God Level" advice—tells you how to fix the duplication (e.g., "Extract to shared utility").
- Rich Reporting: Beautiful console tables, JSON output for CI/CD, and formatted previews.
🛠️ Configuration (The "How")
Customize behavior via CLI flags or a .duplifinder.yaml file.
CLI Reference
| Flag | Description | Default |
|---|---|---|
<root> |
Positional argument: Root directory to scan. | . |
--config |
Path to a YAML configuration file. | None |
--watch |
Live scanning on file changes. | False |
--parallel |
Enable parallel file scanning (threading). | False |
--use-multiprocessing |
Use CPU cores (true parallelism) instead of threads. | False |
--max-workers |
Limit the number of parallel workers. | Auto |
--fail |
Exit with code 1 if duplicates found (CI mode). | False |
--json |
Output results in JSON format. | False |
-p, --preview |
Show the actual code snippets in the output. | False |
--audit |
Enable audit logging to file. | False |
--audit-log |
Path for the audit log file. | .duplifinder_audit.jsonl |
--token-mode |
Enable token-based fuzzy matching. | False |
--similarity-threshold |
Sensitivity for token matching (0.0 - 1.0). | 0.8 |
--dup-threshold |
Alert if duplication rate exceeds this ratio. | 0.1 |
-f, --find |
Specific types to find (class, def, async_def). | All |
--exclude-patterns |
Glob patterns to exclude (e.g., */migrations/*). |
None |
--exclude-names |
Regex patterns for definition names to exclude. | None |
--no-gitignore |
Do NOT respect .gitignore files. | False |
--version |
Show version information. | - |
Configuration File (.duplifinder.yaml)
You can also use .duplifinder.yaml. The CLI args override these settings.
| Key | Description | Default |
|---|---|---|
root |
Root directory to scan | . |
ignore |
Comma-separated directory names to ignore | .git, venv, etc. |
exclude_patterns |
List of glob patterns to exclude | [] |
token_mode |
Enable token-based fuzzy matching | false |
similarity_threshold |
Sensitivity for token matching | 0.8 |
dup_threshold |
Duplication rate threshold for alerts | 0.1 |
audit |
Enable audit logging | false |
parallel |
Enable parallel scanning | false |
watch |
Enable watch mode | false |
Note: Environment variables are not currently supported for configuration to ensure reproducibility via code.
# Example .duplifinder.yaml
root: src
ignore: "tests,legacy"
exclude_patterns: "*/migrations/*"
token_mode: true
similarity_threshold: 0.85
audit: true
parallel: true
🏗️ Architecture
Duplifinder uses a Strategy pattern to dispatch scanners based on file type and mode.
Directory Tree
src/duplifinder/
├── application.py # Workflow orchestration
├── cli.py # Argument parsing
├── config.py # Pydantic configuration & validation
├── finder.py # Strategy Dispatcher
├── definition_finder.py # AST-based Logic (Python)
├── token_finder.py # Token-based Similarity (Multi-lang)
├── text_finder.py # Regex Pattern Matcher
├── refactoring.py # Refactoring Suggestion Engine
├── processors.py # File I/O & Parallel Processing
├── output.py # Rich Console & JSON Renderers
├── utils.py # File discovery & Audit logging
└── watcher.py # Watchdog event handling
Data Flow
- Discovery:
utils.pyrecursively finds files, respecting.gitignore. - Dispatch:
finder.pyselects the right strategy (AST, Token, or Text) based on file extension. - Analysis:
processors.pyruns in parallel to extract definitions or tokens. - Comparison: Hashes or token vectors are compared to find duplicates.
- Refactoring:
refactoring.pyanalyzes results to generate actionable fixes. - Reporting: Results are streamed to Console (using
Rich), JSON, or HTML.
🐞 Troubleshooting
| Issue | Likely Cause | Solution |
|---|---|---|
| No duplicates found | Thresholds too high or wrong path. | Lower --similarity-threshold (e.g., 0.6) or check <root>. |
| Scanning is slow | Large vendor directories. | Add folders to --ignore or .gitignore (e.g., node_modules, venv). |
| Memory usage high | Very large files or too many threads. | Reduce --max-workers or use --exclude-patterns for large generated files. |
| "Config validation failed" | Invalid .yaml or args. |
Check error message and compare with CLI Reference. |
Debug Mode: Run with --verbose to see detailed logs and performance metrics.
🤝 Contributing
We welcome contributions! Please see CONTRIBUTING.md for details on how to get started.
Dev Setup
- Clone the repo.
- Install dependencies:
pip install -e ".[dev]" - Run tests:
pytest - Linting:
ruff check .
🗺️ Roadmap
See ROADMAP.md for the full vision.
- ✅ Foundation: AST Detection, Parallelism, Rich Output.
- ✅ Standard: Watch Mode, Refactoring Suggestions, Multi-language.
- 🚧 Ecosystem (Next): IDE Plugins, GitHub Action, Webhooks.
- 🔮 Vision: AI-Powered Refactoring, Cross-Repo Analysis.
Built with 💙 by Dhruv & the Open Source Community.
Metadata
Release files for duplifinder 12.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| duplifinder-12.0.0.tar.gz | 49.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| duplifinder-12.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 87.7 kB
Release files / duplifinder-12.0.0.tar.gz
| Download URL | duplifinder-12.0.0.tar.gz |
|---|---|
| Size | 49.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
61c4802c598fb2c371b2173c0c6a1361c0f591fe8ff5ae381f0d8144cfdf31f6
|
|
BLAKE2b-256 checksum How to use checksums |
fd9a0227b99b8b06dd87e5079d7f5bc41c7ef163e54c8f0f9662b4cfa71f341e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 22, 2026.
Transparency logRelease files / duplifinder-12.0.0-py3-none-any.whl
| Download URL | duplifinder-12.0.0-py3-none-any.whl |
|---|---|
| Size | 38.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
57d469f68c33b71bcd11d93ad8102b337b39414410ac1493c4f2a4be88ceacaa
|
|
BLAKE2b-256 checksum How to use checksums |
bed8c76a28a968566728e55892e4afbb9a2bd30d82aba5c41b04a6716928e056
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 22, 2026.
Transparency log