Every few months I install a small utility, and every few months something in its dependency tree ships a breaking change and the utility stops working. The tool was four lines of real logic wrapped in forty packages.
So I set a rule for a set of command-line tools: import nothing outside the Python standard library. Not "few dependencies" — none. If a machine has Python 3.9+, it runs. Here is what that constraint buys, and what it genuinely costs.
What the constraint buys
- Nothing can rot. No transitive dependency can break my tool by releasing a major version.
- It installs where pip does not. Air-gapped machines, locked-down corporate images, containers where you are not allowed to pull anything.
- It is small enough to read. A few hundred lines you can audit in ten minutes beats a package you trust because it has stars.
- It starts instantly. No import of a framework to convert a CSV file.
The seven tools
Typed CSV to JSON, JSON back to CSV, bulk renaming, duplicate detection, a link checker, Markdown to HTML, and a directory size report. Boring, recurring jobs.
Three places where the boring version is the hard version
Renaming files is a destructive operation. The naive os.rename loop will overwrite a file that happens to have the target name, and you find out later. So the rename tool builds a plan first, refuses any target that already exists, prints the plan, and only then acts. Every applied batch writes an undo log, so --undo replays the moves backwards. Destructive tools should default to dry-run.
CSV type inference is a trap. "1" might be a number, an ID, or a boolean. "true" might be a string in a column of strings. Empty is not the same as zero, and a spreadsheet saved on Windows starts with a UTF-8 BOM that will silently corrupt your first column name. My rule: convert only unambiguous scalars, treat empty as null, and give people a flag to turn inference off entirely.
Hashing everything is wasteful. Duplicate detection by SHA-256 means reading every byte of every file. Bucket by size first — two files of different sizes cannot be identical — then hash only within size groups. On a photo library this turns minutes into seconds.
Where the standard library is the wrong choice
I would not build image processing on it, or PDF parsing, or anything that needs a real HTTP client with retries and connection pooling. urllib is fine for checking whether a URL returns 200; it is not fine for scraping at scale. Pretending otherwise would be ideology over engineering. The constraint is worth it for small, dependency-hostile utilities, not for everything.
What I would do differently
I would write the tests before the type-inference code. The "1" vs true vs "yes" cases are exactly where bugs live, and the test suite caught behaviour I had already convinced myself was correct.
I packaged these tools. Two of them — Markdown to a single self-contained HTML file, and the disk usage report — are free, MIT licensed, source included, so you can judge the code before deciding anything: free lite edition.
The full set is $7 on the same store. I am the author, so treat the link as self-promotion; the technical parts above stand on their own regardless.
Source for the two free tools (MIT) is on GitHub: https://github.com/ClaireMananite/zdk
Top comments (0)