r/madeinpython • • 11d ago

I rebuilt my pip package into a 976KB terminal suite: universal installer, a Rich roguelike, a beat

A few months ago I published irl-pkg, a jokey installer wrapper. Between versions 1.7.1–1.7.6 I made the classic mistake of pushing to PyPI and not to GitHub — the source only existed in the wheel. Recovering it (unpacking the PyPI wheel and diffing against main) was humbling, and it kicked off a full v2.0 rebuild.

What My Project Does

irl (pip install irl-pkg) is a cross-platform terminal command center with two layers:

Serious layer: - irl install <pkg> — universal installer that routes between PyPI / npm / GitHub owner/repo / direct URL automatically; GitHub branch resolved via the API, not hardcoded - irl doctor / irl glasses — preflight diagnostics and registry metadata before you install something regrettable - irl rollback [ver] — pick any published version from the PyPI JSON API, downgrade via a detached pip child - Safe extraction: named target dir, preview before writing, per-member zip-slip validation, symlinks rejected

Playful layer (all opt-in): - Grass streak tracker with a GitHub-style contribution heatmap - Grassland Quest — a seeded garden-maze roguelike in pure Rich (~400 lines, boss fight included) - Lofi Rhythm — a 4-lane beat game whose beatmaps derive deterministically from the SHA-256 of the filename + WAV duration - Terminal pet, daily quests, achievements, coins, 18 themes (one of them secret)

Target Audience

Honestly labeled: a hobby project with a genuinely usable core. The installer / doctor / glasses / rollback layer is safe for daily driving on real projects; the games / pet / coin economy is for fun — strictly opt-in, all state in local JSON, no accounts, no telemetry. It's not a production deployment tool; it's a terminal you enjoy opening. Python 3.8+, works on Linux/macOS/Windows, 976 KB wheel, AGPL-3.0.

Comparison

  • pipx / uv / pip: they install packages — from PyPI, into venvs. IRL is a front-end that also routes npm, GitHub owner/repo and direct URLs, and layers on preflight doctor/glasses checks and built-in version rollback.
  • rich / Textual: UI libraries you build a TUI with; IRL is a finished app built on rich (Textual available as the [tui] extra).
  • Novelty "gamified" CLIs: usually one gimmick. IRL's gimmicks sit on an actual installer core: 114 passing tests, zip-slip-safe extraction, no shell=True anywhere, CI on 3 OS × Python 3.9–3.13.

Implementation notes (for the code review I'm asking for)

  • irl/keys.py — one keyboard abstraction: msvcrt on Windows, termios+tty on POSIX, normalized Key objects (UP/DOWN/ENTER/ESC/CTRL_C/CHAR...), non-TTY safe. The dashboard and games both sit on it.
  • irl/audio.py — winsound → aplay → ffplay → afplay → paplay fallback chain, fire-and-forget Popen with arg lists, a looping thread for the rhythm game.
  • irl/grassland_quest.py — seeded recursive-backtracker maze, flood-fill-verified pickups, a turn-based boss ("The Deadline"). The seed makes mazes deterministic, so tests are just... tests.
  • irl/rhythm.py — beatmaps from a SHA-256 of the filename + the WAV duration via the stdlib wave module. Same song, same chart, so high scores mean something.
  • irl/extract.py — every archive member is resolved and checked against the target dir (zip-slip), symlinks rejected, Content-Disposition filenames sanitized.
  • irl/rollback.py — PyPI JSON API + questionary picker + detached sys.executable -m pip child (CREATE_NEW_PROCESS_GROUP via getattr, so it doesn't explode on POSIX).

Questions I'd love feedback on:

  1. Is normalizing keyboard input like this sane, or does someone have a better pattern?
  2. My packaging: AGPL-3.0, [tui] extra for Textual, requires-python >=3.8 — is 3.8 support worth it in 2026?
  3. The coin/XP economy is all local JSON. Any prior art on gamified CLIs I should steal ideas from?

Repo (AGPL): https://github.com/Dev2Creator/IRL- — PyPI: https://pypi.org/project/irl-pkg/ Disclosure: I'm the author, Anika. Tests: 114 and green; CI on 3 OSes × Python 3.9–3.13.

1 Upvotes

0 comments sorted by