FTL Lab

Python CLI tools & solo-dev lessons
Tools: FTL Lab tools on Gumroad · Payhip · Lemon Squeezy

I Built 10 Free Python CLI Tools — Here's Why Zero-Dependency Matters

Cover image: none — a clean terminal is the point.

A year ago, I started building Python CLI tools to automate my data workflow. Today, I have 10 free, open-source tools in the wild — and every single one of them runs on nothing but the Python standard library.

No pip install. No requirements.txt. No virtual environment. Just python3 tool.py your_file.csv.

That wasn't laziness. It was the most deliberate engineering decision I made all year. Here's why zero-dependency became my whole philosophy — and why I think more CLI tool authors should consider it.


The problem with "just add a dependency"

When I started, my first tool used the stack everyone recommends: Click for the CLI, Rich for pretty output, pandas for analysis. It looked gorgeous in the README demo. And then reality hit:

The tools worked. The installation was the product — and it was broken.

The zero-dependency rewrite

So I rewrote everything using only the standard library. Here's the real code from my CSV Analyzer — the whole analysis engine, ~60 lines, zero imports beyond csv, sys, and collections:

#!/usr/bin/env python3
"""CSV Analyzer — zero-dependency statistical report."""
import csv
import sys
from collections import Counter

def analyze_csv(filepath):
    with open(filepath, 'r') as f:
        reader = csv.reader(f)
        headers = next(reader)
        rows = list(reader)

    print(f"\n{'='*60}")
    print(f"  CSV ANALYZER — Statistical Report")
    print(f"  File: {filepath}")
    print(f"  Rows: {len(rows)} | Columns: {len(headers)}")
    print(f"{'='*60}\n")

    for col_idx, header in enumerate(headers):
        values = [r[col_idx] for r in rows if col_idx < len(r) and r[col_idx].strip()]
        if not values:
            print(f"  [{header}] — empty column, skipping")
            continue

        try:
            nums = [float(v.replace(',','').replace('$','').replace('%','').replace('€',''))
                    for v in values]
            print(f"  [{header}]")
            print(f"    Type: Numeric | Count: {len(nums)}")
            print(f"    Mean: {sum(nums)/len(nums):,.2f}")
            print(f"    Min: {min(nums):,.2f} | Max: {max(nums):,.2f}")
        except ValueError:
            uniq = Counter(values)
            top3 = uniq.most_common(3)
            print(f"  [{header}]")
            print(f"    Type: Text | Unique values: {len(uniq)}")
            print(f"    Top values: {', '.join(f'{k} ({v})' for k,v in top3)}")

if __name__ == "__main__":
    analyze_csv(sys.argv[1])

Run it anywhere Python runs. That's the entire pitch.

The 5 principles I now build by

1. Stdlib is more powerful than you remember

csv, json, sqlite3, argparse, re, pathlib, collections, statistics, zipfile, email, http.server — between them you can build 90% of the "data tools" people pay for. Python's stdlib is a hidden gem because nobody shows it off. When you remove the sugar, you rediscover the tool.

2. One file beats a package

A single .py file you can read top-to-bottom is a product in itself. Users trust it, audit it, and fork it. The moment you need a package structure, you've added a barrier between your tool and the person who just wants to analyze a CSV.

3. Installation is part of the UX

python3 csv_analyzer.py data.csv

That's the entire onboarding. No venv, no pip install -e ., no "Python 3.10+ recommended". For a data tool, the path from "heard about it" to "ran it" should be under 10 seconds.

4. Fewer dependencies = fewer security reviews

Supply-chain attacks are the #1 vector in open source right now. A tool with zero runtime dependencies has a supply chain of exactly one: Python itself. That's a feature you can put on the README in bold.

5. It forces honest engineering

With no pandas to lean on, you write the actual logic. You learn how CSV parsing works, how type detection works, how flattening nested JSON works. Every rewrite made me a better Python developer — and the tools got faster, because there's no 200MB import to wake up first.

What happened after the rewrite

The honest trade-offs

Zero-dependency isn't dogma — it has real costs:

The line I use: a dependency must pay for itself in product value, not in author convenience.

What's in the toolbox

The 10 free tools I ship cover the boring-but-recurring data chores:

All free, all MIT, all stdlib-only.

If you're building CLI tools, I'd love to see you try the experiment: take your next tool and build it with zero dependencies. Not because it's pure — because it's a better product. Smaller, faster, safer, and readable by anyone.

The whole collection lives at github.com/ftllab/datacrafted-tools — grab one, read the source, and steal the patterns. 🐍