A few thoughts on building a terminal ePub reader with AI A developer used AI coding agents to port the terminal e-book reader epy from Python to Rust, creating repy, after the original project stopped being maintained. The project took months instead of hours due to the complexity of rendering EPUB in a terminal, and received minimal attention on GitHub. The author reflects on the devaluation of software in an age of abundant AI-generated content. I like to do things in the terminal. It has little to do with efficiency. It is more my obsession with fiddling with software, so I don't have to think about all the depressing things happening in the world. One terminal program I tried is epy https://github.com/wustho/epy , an e-book reader. I quite liked its speed. But like many other open source projects, it stopped being maintained. So last November 2025 , when coding agents like Codex CLI and Claude Code got better, I started to port epy from Python to Rust. I thought it was a task for an afternoon. After all, how hard can it be to display text in a terminal? It turns out that rendering EPUB correctly in a terminal is a messy business. The format was not designed to be displayed in a terminal at all. And for a reasonable reading experience, you have to solve the problem of navigating the book correctly, which the AI struggled with quite a bit. Instead of a few hours, the agents worked for days, adding more and more features, until I was comfortable sharing the project in February this year 2026 . It got five up-votes and eight stars on GitHub. Perhaps there is not enough interest in terminal-based EPUB readers. Perhaps there is a general dislike of AI-built software. But had this project been published a few years earlier, I doubt the interest would have been so little. With the recent release of Claude Fable 5 and GPT Sol 5.6, I added quite a few more features. Yet I doubt it would get even five up-votes this time. With the abundance of software comes the devaluation of software. "Why would I use this, when I can ask my agent to spit out something similar, but closer to my own likes and dislikes?" A thing anyone can have made at will is a thing nobody treasures. Books may be an analogue, even before authors began publishing hundreds of AI-generated novels. I used to read a lot, sometimes two dozen books a year. I kept an eye on authors I liked and tracked what they were publishing. Then I realized there are already far more good books than I can read in this lifetime. So new books, even great ones, mean nothing to me anymore. It is not that the books got worse. It is that my time was always the scarce thing, and now I can see it. If we are really seeing the dawn of AGI, perhaps humans have to reckon with this: when there are far more intellectual artifacts --- games, software, books, music, films --- than anyone could consume in a lifetime, what is the meaning of creating more? But maybe the question is older than it looks. Seneca complained two thousand years ago that the abundance of books distracts. There was already more than one life could hold; only the speed is new. And nobody ever wrote to finish writing, or read to finish reading. I did not port epy because the world lacked an e-book reader. I ported it to have something to fiddle with --- an afternoon that became months. The worth of making was never in being consumed. If it keeps my mind off the depressing things happening in the world, that is meaning enough, five up-votes or none. This is 100% AI-generated code. Every single line was written by Codex CLI https://github.com/openai/codex , Gemini CLI https://github.com/google-gemini/gemini-cli , and Claude Code https://claude.ai/claude-code --- the human has not written a single line of Rust. That said, it works well for daily use. No guarantee it won't eat your epub, delete your database, or crash your terminal. You're on your own. PRs welcome. Rust reimplementation of the excellent CLI ebook reader epy https://github.com/wustho/epy . repy keeps the keyboard-first reading experience familiar while adding fast chapter rendering, inline terminal graphics, persistent annotations, and a self-contained SQLite library. EPUB artwork rendered directly in the reading flow. Jump through the table of contents, then select, copy, annotate, or look up text without leaving the reader. Functional for daily use Core reading features are complete: TUI navigation, search, bookmarks, library management, two-phase cursor/selection modes, image viewing, link/footnote handling, dictionary lookup, Wikipedia lookup, persistent highlights/comments, highlight export, and TTS text-to-speech all work. Text is intelligently wrapped and hyphenated. Reading state and preferences are persisted per-book. Supported formats: EPUB, FictionBook .fb2 and .fb2.zip , MOBI6 .mobi , plain text .txt , Markdown .md , and comic book archives .cbz --- set "inline images": "shown" and use a graphics-capable terminal such as kitty to see the pages . AZW/AZW3 files are accepted on a best-effort basis; KF8-only content may not be readable by the MOBI6 parser. See to-do.md /newptcai/repy/blob/main/to-do.md for detailed feature status and roadmap. You can download pre-built binaries for Linux, Windows, and macOS from the GitHub Releases https://github.com/newptcai/repy/releases page. Linux : Download repy-linux-x86 64 compatible with most modern distributions . Windows : Download repy-windows-x86 64.exe . macOS : Download repy-macos-universal works natively on both Intel and Apple Silicon Macs . After downloading, rename the file to repy or repy.exe on Windows and make it executable: Linux/macOS chmod +x repy- - mv repy- - /usr/local/bin/repy If you prefer to build it yourself, you need Rust and Cargo installed. Clone this repository git clone https://github.com/newptcai/repy.git cd repy Build and install cargo install --path . The bundled rusqlite feature is enabled, so no system-wide libsqlite3 installation is required; SQLite is compiled and linked as part of the build. To open any EPUB, plain-text, or Markdown file doesn't need to be in your library : repy /path/to/book.epub repy /path/to/notes.md repy If there is a reading history, repy reopens the last-read book at the last saved position. Otherwise, it starts in the reader UI without a book loaded. The EBOOK argument can be a file path, a reading-history number, or a pattern matched case-insensitively against the title, author, and path of history entries the most recently read match wins : repy -r Print the reading history with numbers and progress repy 3 Open the 3rd book in the reading history repy dorian Open the most recent history entry matching "dorian" repy -d BOOK Dump the parsed text of an ebook to stdout pipe to less/grep repy -c FILE Use a specific configuration file repy -v Increase verbosity for debugging repy --debug Enable debug output repy --export-highlights /path/to/book.epub --export-highlights writes all persisted highlights/comments for that EPUB to stdout. The default format is JSON including the book identity ; pass --format md for Markdown grouped by chapter, with quotes, notes, and dates: repy --export-highlights book.epub --format md notes.md Search functionality supports regular expressions. Start Search : Press / to open the search input. Incremental : Matches update live as you type, and the view previews the first match at or after your current position. Esc while typing cancels and restores the original position. Invalid partial regexes simply show no matches. History : Up / Down while typing recall previous queries persisted across sessions, most recent first, capped at 100 . Down past the newest entry restores the query you were typing. Navigation : Enter : Confirm the query recorded in history . Then j / k or Up / Down browse results, and a second Enter jumps and closes the window. n : Jump to the next search hit. p / N : Jump to the previous search hit. Clear Highlights : There is no dedicated key to clear highlights. A workaround is to press / to start a new search which clears existing highlights and then Esc to cancel. Current Hit : All matching text is highlighted in yellow; the line containing the current hit is highlighted in orange. A match N/M counter is shown in the top bar and status messages while navigating with n , p , or N . Press ? in the TUI to see the help window at any time Help ? . k / Up --- Line Up j / Down --- Line Down h / Left --- Page Up l / Right --- Page Down Space --- Page Down Ctrl+u --- Half Page Up Ctrl+d --- Half Page Down L --- Next Chapter H --- Previous Chapter g --- Chapter Start G --- Chapter End Home --- Book Start End --- Book End Ctrl+o --- Jump Back Ctrl+i / Tab --- Jump Forward + / - --- Increase/Decrease Width = --- Reset Width T --- Toggle Top Bar c --- Cycle Color Theme A --- Highlights list Enter in highlights list --- Jump to selected highlight e in highlights list --- Edit comment d in highlights list --- Delete highlight d in cursor mode --- Delete highlight under cursor / --- Search --- Text-to-Speech Toggle v --- Cursor Mode t --- Table of Contents m