
Earworm
Tools
What worked
First Go project in the portfolio — the language choice paid off immediately with a CGo-free single binary that cross-compiles cleanly. The plan engine (draft/ready/apply lifecycle with SHA-256 verification and audit logs) emerged from real usage: within 48 hours of shipping a feature I was running it against real data. The 'additive before destructive' philosophy — inject metadata first, then move/delete — survived contact with a messy 500+ book library and became the design principle for the whole tool.
What broke
The audible-cli subprocess boundary is a clean license firewall but its output format isn't formally versioned, so the wrapper has to be defensive. Audible's rate-limit thresholds are undocumented, meaning conservative 5-30s delays that may be overly cautious — no way to tune without risking a ban. The daemon mode cannot auto-apply plans (deliberate safety trade-off for destructive ops) which limits unattended usefulness.
Roles
I defined the plan-engine philosophy and the safety model (dry-run default, double-confirmation on destructive steps, CSV as the offline composition format). Claude Code wrote the state machine, fileops package, and scanner heuristics. The decision to use pure Go SQLite to avoid CGo was mine.
Earworm (Audiobook Library Manager)
Overview
Earworm is a Go CLI that started as a reliable Audible downloader (replacing Libation) and evolved into a full library operations engine: deep scanning for structural issues, plan-based remediation with metadata carriage, idempotent file operations, and auditable plan review/approval.
Target users: Audiobook collectors running self-hosted media servers (Audiobookshelf) who need reliable batch downloading and ongoing library hygiene for collections that grew chaotically over years.
What It Does
- Fault-tolerant batch downloads with rate limiting, exponential backoff, crash recovery, and per-book state tracking in SQLite
- AAXC decryption via FFmpeg (AAXC to M4B conversion)
- Configurable library organization — flat or author/title hierarchy, with cross-filesystem moves (local to NAS) using copy-verify-delete
- Deep library scanning — detects nested folders, multi-book containers, missing metadata, naming inconsistencies
- Plan engine — draft/ready/apply lifecycle with dry-run default, double confirmation on destructive steps, SHA-256 verification, and audit logs
- Split and flatten operations — collapse nested folder structures, split multi-book bundles into per-book folders with metadata inference
- Metadata carriage through CSV — title, author, series, series_index travel through the CSV/plan/apply pipeline, enabling offline plan composition via spreadsheet
- Daemon mode and integrations — polling for unattended operation, Audiobookshelf scan triggers, Goodreads CSV export
How It Evolved
The v1.0 download-and-organize core shipped in about a week. Then I started using it on a real 500+ book NAS library, and every complaint became a feature within days.
The library cleanup CSVs tell the story: ~315 entries including a full Discworld series sweep, 18 Warhammer 40k folders that were nested three levels deep (Audiobookshelf couldn't traverse them), Malazan and Beast Arises bundles that needed splitting into ~10 per-book folders each. Each of these drove a specific capability — flatten operations, split detection, metadata carriage through plans.
The "additive before destructive" principle emerged from this usage: always inject metadata first, review the plan, then apply file operations. This became the design center for the whole tool.
Post-v1.3 maintenance added library layout flexibility (flat vs hierarchical), directory-level plan operations, and pre-order retry handling — all driven by real-world friction, not speculative features.
Architecture Decisions
- Go over TypeScript — Single-binary distribution, excellent CLI/subprocess ecosystem, cross-compilation. First non-TypeScript project in the portfolio; the problem domain demanded it.
- Pure Go SQLite (modernc.org) — Eliminates CGo, enables true cross-compilation for a single binary.
- SQLite on local filesystem only — Network filesystems cause silent corruption and broken locking.
- Wrap audible-cli as subprocess — Clean license boundary (MIT wrapper over Python tool); proven Audible auth without GPL contamination.
- Staging directory pattern — Downloads land in staging, get verified, then move to library. Prevents partial files in the final location.
- Conservative rate limiting — Audible throttle thresholds are undocumented; 5-30s delays protect against bans at the cost of speed.
- Embedded Python venv — Users don't manually install Python or audible-cli; the binary bootstraps everything.
Weaknesses and Open Questions
- Audible rate limits are a black box — Conservative defaults may be overly cautious, but there's no safe way to test the boundaries.
- audible-cli output not formally versioned — The subprocess wrapper must be defensive; upstream format changes could break parsing silently.
- Requires Python 3.9+ and FFmpeg — External runtime dependencies, though auto-bootstrapped.
- Single-service focus — Audible only. No Libro.fm, Chirp, or other audiobook services.
- Plan review is a manual gate — Daemon cannot auto-apply plans (deliberate safety trade-off), which limits fully unattended operation.
- Limited Audiobookshelf integration — Only library scan triggers; no metadata field updates or two-way sync.
Ecosystem Role
Earworm is the first Go project in the portfolio, validating Go as an alternative to the TypeScript default for CLI/systems work. It has no AI/LLM component — pure infrastructure built around a personal pain point where the existing tool (Libation) simply wasn't reliable enough.