GitHub Releases already solves the actual storage problem. Release assets sit outside git history, support files up to 2GB, are served from GitHub's CDN, and can be downloaded individually on demand.
The architecture is simple: one repo per topic shelf, PDFs uploaded as release assets, a catalog.yml in the repo holding searchable metadata. Git only versions the metadata, never the files.
shelfctl is the CLI/TUI that manages this:
# add a book shelfctl shelve ~/Downloads/sicp.pdf --shelf programming --title "SICP" --tags lisp,cs
# open one - downloads only that file from GitHub's CDN shelfctl open sicp
# migrate existing PDFs out of a bloated repo shelfctl migrate scan --source you/old-books-repo > queue.txt shelfctl migrate batch queue.txt --n 20 --continue
It has three interfaces that share the same feature set: an interactive Bubble Tea TUI, a scriptable CLI with --json on every command, and a generated static HTML index for offline browsing.
The interesting implementation challenge was the multi-book edit carousel - books laid out with adjacent cards peeking in from each side. ANSI-aware column clipping with charmbracelet/x/ansi was necessary to clip rendered lipgloss output by visible character width rather than bytes.
The obvious question is "why not Calibre or a cloud storage service?" - the answer is that GitHub is already where these files live for a lot of developers, there's no new service to trust or pay for, and it fits naturally into existing git workflows. It's not the right tool for everyone, but for the developer who already lives in GitHub it removes a lot of friction.
If you've hit this problem, shelfctl might be worth a look.