Skip to main content

codeecho 1.2.0

License: MIT Version Python PyPI

A developer tool that scans your codebase to detect and highlight echoes of duplicated or near-duplicated code, so you can refactor toward cleaner, more maintainable designs.

Prerequisites

  • Python >=3.14

Installation

pip install codeecho

Usage

python -m codeecho <path> [options]

Clone detection levels

Type Detection strategy Example
Type-1 Exact copy-paste — identical token sequences Two functions with the same code copied verbatim
Type-2 Structural clone — same structure, renamed identifiers / literals Same logic with different variable names
Type-3 Near-duplicate — high Jaccard similarity on token sets Nearly identical functions with a few extra lines

Supported languages

Language Extensions Grammar
Python .py tree-sitter-python
JavaScript .js, .mjs, .cjs tree-sitter-javascript
TypeScript .ts, .tsx tree-sitter-typescript
Java .java tree-sitter-java
Go .go tree-sitter-go
Gosu .gs, .gsx tree-sitter-gosu

Arguments

Argument Description
path Root directory to scan.

Options

Option Default Description
--types <types> all Clone types to detect: comma-separated (1, 2, 3) or all.
--threshold <float> 0.8 Jaccard similarity threshold for Type-3 detection (0.01.0).
--output <name> codeecho-output Base name (without extension) for output file(s).
--output-dir <dir> <cwd>/reports Directory where output file(s) will be written.
--db-dir <dir> ~/.codeecho Directory for the SQLite scratch database (codeecho.db). Session records are removed after the report is written.
--format <fmt> both Output format: json, html, or both.
--min-tokens <n> 10 Minimum token count for a code fragment to be included.
--exclude <pattern> (none) Glob pattern(s) to exclude from scanning (repeatable).
--target-list false Treat PATH as a single existing file listing target paths (files and/or directories), one per line, instead of individual PATH arguments. Blank lines and lines starting with # are skipped.
--basis <file> (none) File listing basis target paths, one per line — same format as --target-list. Absolute file/directory entries are merged into the scan automatically and matched exactly; relative entries (e.g. a bare filename like Foo.gs) are matched by filename/suffix against any file discovered in the scan. The report is filtered to only clone groups touching at least one basis file, and groups duplicated purely among basis files are flagged (basis_internal in JSON, a "Basis-to-Basis" badge in HTML).
--version Print the version and exit.
-h, --help Show help and exit.

Examples

Scan the current directory and write both JSON and HTML reports:

python -m codeecho .

Detect only Type-1 and Type-2 clones in a src/ tree:

python -m codeecho src --types 1,2

Scan with a custom output name and directory:

python -m codeecho . --output my-scan --output-dir audit/reports

Lower the Type-3 threshold to catch more near-duplicates:

python -m codeecho . --threshold 0.6

Exclude test and vendor directories:

python -m codeecho . --exclude "*/tests/*" --exclude "*/vendor/*"

Scan targets listed in a file, one path per line:

python -m codeecho targets.txt --target-list

Find where code from a reference/basis set of files is duplicated elsewhere in the codebase:

python -m codeecho src --basis basis.txt

Configuration

Environment variable Description
CODEECHO_CONFIG_DIR Directory where logging.ini, .ignore, and config.ini are seeded on first run. When unset, the bundled copies inside the package are used directly.

.ignore file

On first run, a .ignore file is seeded into CODEECHO_CONFIG_DIR (or the package directory when unset). It follows gitignore syntax and is applied during file scanning to exclude paths in addition to any --exclude patterns passed on the command line. Edit this file to permanently suppress paths you never want scanned.

Overriding the ignore filename

config.ini (also seeded into CODEECHO_CONFIG_DIR on first run) contains an [override] section with an ignore-file key, which names the file used in place of .ignore, resolved relative to CODEECHO_CONFIG_DIR:

[override]
ignore-file = .ignore

Point ignore-file at a different filename to use an alternate ignore file (also placed inside CODEECHO_CONFIG_DIR). If the configured file is missing, codeecho logs a warning and falls back to the bundled .ignore.

Development

Prerequisites

  • Poetry 2.2+

Setup

poetry install

Run

poetry run python -m codeecho <path> [options]

Architecture

flowchart TD
    CLI["__main__.py\n(Click CLI)"] --> ScannerM["scanner.py\nFile discovery"]
    ScannerM --> Parser["parser.py\nTree-sitter parsing"]
    Parser --> Extractor["extractor.py\nFragment extraction\n(functions · classes · files)"]
    Extractor --> Normalizer["normalizer.py\nRegex tokeniser\nType-2 normalisation"]
    Normalizer --> Fingerprint["fingerprint.py\nSHA-256 hashing"]
    Fingerprint --> DB["db.py\nSQLite session store"]
    DB --> Detector["detector.py\nType-1 / 2 hash grouping\nType-3 Jaccard similarity"]
    Detector --> DB
    DB --> JSON["reporter/json_reporter.py\nJSON report"]
    DB --> HTML["reporter/html_reporter.py\nHTML report"]
    DB -->|delete session| Cleanup["Session cleanup"]

Format and Lint

poetry run black codeecho
poetry run pylint codeecho

Run Tests with Coverage

poetry run pytest --cov=codeecho tests --cov-report html

Changelog

License

This project is licensed under the MIT License.

Author

Ron Webb

Release files for codeecho 1.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for codeecho 1.2.0
File Size Uploaded
codeecho-1.2.0.tar.gz 31.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for codeecho 1.2.0
File Interpreter ABI Platform
codeecho-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 67.4 kB

Release files / codeecho-1.2.0.tar.gz

Download URL codeecho-1.2.0.tar.gz
Size 31.1 kB
Tags Source
SHA-256 checksum
How to use checksums
2f3acc6591c66f2609cc20d885631f2b1f35e1b6477c7a646af40f950b6c38ff
BLAKE2b-256 checksum
How to use checksums
6e1eb0f8154ab43a87904b82037d140ef55eedda41897239ba74dac9a2e81340
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.2.0 CPython/3.14.7 Linux/6.17.0-1022-azure

Release files / codeecho-1.2.0-py3-none-any.whl

Download URL codeecho-1.2.0-py3-none-any.whl
Size 36.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1a1ffaddbb892d103c61ce4cfb5de788089bb5b4b81618150dbbcf40b7f3056b
BLAKE2b-256 checksum
How to use checksums
80c2620f0e5f4e3afff093951e49ae11213cc8cdf7bcef1462dbb287da09e28e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.2.0 CPython/3.14.7 Linux/6.17.0-1022-azure

Release history Release notifications | RSS feed

1.2.1

2 release files

This release

1.2.0 This release

2 release files

1.1.0

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page