🌿 dupnames v1.0.0 · MIT

Detect same-basename files with different content — the "same name, different role" collisions that cause silent mistakes: a script edited in one copy while the build loads another, a doc updated in a subfolder while readers consult the root one.

Why this exists

Two real incidents motivated this tool: a plugin edited in the workspace copy while the runtime loaded another file of the same name, and a doc edited in a skill folder while the test battery read the root one. Nothing crashed; the wrong file just won. The preventive rule is simple — reference files by their full path and give distinct names to files with distinct roles. dupnames makes every violation visible.

classmeaning
ambiguoussame name, different content — the real risk (exit 1)
identicalsame name, byte-identical content (harmless copies)
conventionalexpected duplication — the folder is the identity (README.md, SKILL.md, package.json, __init__.py, 2026-09-19.md, …)

Install (pip)

pip install dupnames @ git+https://mandrilly.com/git/dupnames.git

Zero runtime dependencies — Python ≥ 3.9, standard library only.

Quick start

dupnames .                        # scan current tree
dupnames ~/projects --ext py      # only Python files (repeatable)
dupnames . --ignore-case          # Foo.py vs foo.py (case-insensitive FS)
dupnames . --skip generated       # extra dir to skip (repeatable)
dupnames . --json                 # machine-readable report
dupnames . --quiet                # one AMBIGUOUS line per finding (cron-friendly)

Honest exit codes: 0 clean · 1 ambiguous collisions found · 2 usage error. Classification is by SHA-256 content, not timestamps — a touched-but-unchanged file stays identical. Case-insensitive matching is opt-in (--ignore-case) for filesystems where Config.py and config.py share one slot.

Source

git clone https://mandrilly.com/git/dupnames.git

15 unit tests cover ambiguous/identical/conventional classification, extension and skip filters, hidden dirs, case handling, JSON/quiet output, and exit codes. This repository audits clean against itself — try dupnames . on the clone.