Give it a book, and an AI reads it the way you would study one: one page at a time. PDF, EPUB, Word, Markdown and plain text all work.
On every page it writes down what it learned, each note tagged with its page number. Every 20 pages it stops and writes down what it understands so far. When it reaches the last page, it pulls the whole book together into one final summary. You watch it happen live in your terminal, page by page.
| You have | Run with | Set up once |
|---|---|---|
| A ChatGPT plan | --backend codex (Codex CLI) |
codex login |
| A Claude plan | --backend claude (Claude Code) |
run claude and sign in |
| A Grok plan | --backend grok (Grok Build) |
grok login |
| An OpenAI API key | --backend openai (the default) |
export OPENAI_API_KEY=... |
| An Anthropic API key | --backend anthropic |
export ANTHROPIC_API_KEY=... |
| A Gemini API key | --backend gemini |
export GEMINI_API_KEY=... |
| An xAI API key | --backend xai |
export XAI_API_KEY=... |
| An OpenRouter key | --backend openrouter |
export OPENROUTER_API_KEY=... |
A plan needs no API key: the reader uses the coding CLI that comes with it. Whichever you pick, it still reads one page per call, and the model only ever sees the page in front of it plus the reader's own notes. It never gets the book file, a shell, or any tools (see What the AI can see).
git clone https://github.com/echohive42/AI-reads-books-page-by-page
cd AI-reads-books-page-by-page
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtThen try 3 pages of the bundled meditations.pdf, starting at page 31 where Book One begins. Use the line for whatever you have:
python read_books.py --backend codex --start-page 31 --test-pages 3 # ChatGPT plan
python read_books.py --backend claude --start-page 31 --test-pages 3 # Claude plan
python read_books.py --backend grok --start-page 31 --test-pages 3 # Grok plan
python read_books.py --start-page 31 --test-pages 3 # OpenAI API key
python read_books.py --backend anthropic --start-page 31 --test-pages 3 # Anthropic API key
python read_books.py --backend gemini --start-page 31 --test-pages 3 # Gemini API key
python read_books.py --backend xai --start-page 31 --test-pages 3 # xAI API key
python read_books.py --backend openrouter --start-page 31 --test-pages 3 # OpenRouter keyWhen you are ready for a whole book:
python read_books.py path/to/your_book.pdf --backend codexAn .epub, .docx, .md or .txt file works the same way (see What it can read). Stop it any time with Ctrl+C. Every finished page is saved, and running the same command again carries on from where it stopped.
| File | How it is read | Its pages |
|---|---|---|
PDF (.pdf) |
With PyMuPDF; add --ocr auto for scanned pages |
The PDF's own pages |
EPUB (.epub) |
The chapters in reading order, straight from the file | Reader pages |
Word (.docx) |
The document's paragraphs | Reader pages |
Markdown (.md) and text (.txt) |
As written | Reader pages |
EPUB, Word, Markdown and text are read directly with Python's standard library: no conversion to PDF, and nothing extra to install.
Reader pages. These formats have no fixed pages, because their text reflows to fit the screen. So the reader cuts them into pages of about 2,400 characters (roughly one printed page), always at a paragraph break, or at the end of a sentence inside a very long paragraph. The page numbers in the notes and summaries count these reader pages, not the pages of a printed edition. The same file always gives the same pages, so stopping and carrying on is safe.
Not read directly:
- Kindle files (
.mobi,.azw,.azw3): convert the book to EPUB first, for example with the free Calibre app, then read the.epub. - Old Word files (
.doc): open it in Word or Pages and save it as.docx. - Books with DRM: only DRM-free books can be read or converted.
Being straight with you about what was run for real:
- Run on real pages (3 pages of
meditations.pdf, with a look back and a final summary): the Claude Code, Codex and Grok Build CLIs. - EPUB, run on real pages (2 reader pages of a small EPUB made from the first chapter of the Meditations, with a final summary): Claude Code. Word, Markdown and text files go through the same page cutting and have offline tests, but no live run yet.
- Checked against each provider's official docs, but not yet run live: the OpenAI, Anthropic, Gemini, xAI and OpenRouter APIs. Each one has offline tests that run the real SDK and check the exact request the provider would receive and how its answers and errors are handled. The doc pages each backend follows are linked in
backends.py. For Gemini, its real answers to a wrong key, an unknown model and an account with no credit were checked live; no page has been read with it yet.
If you run one of the untested ones, an issue saying how it went would help everyone.
The idea is simple: read like a person, not like a search engine. Nobody understands a book by seeing all of it at once. You read a page, connect it to what you already know, and your understanding grows as you go.
Every page is its own model call. For page N, the reader sends:
- π the text of page N (pulled out with PyMuPDF for a PDF),
- βοΈ the last lines of page N-1, so a sentence that runs over the page break still makes sense,
- π its most recent notes, each tagged with the page it came from,
- π one-line memories of the last few pages,
- π§ what it understood so far, from its last look back.
It answers with a small JSON object: is this page worth reading (it skips contents, index, copyright and bibliography pages), a one-line gist of what the page adds, and the new knowledge points. Points it already has are dropped, so the notes do not fill up with repeats. Then the page is saved.
Every 20 pages it looks back. It takes what it understood last time, adds the notes from the pages since, and writes an updated "What I understand so far, after page N". It keeps page references like (p. 34) and ends with the threads it expects the book to develop. That understanding then travels with every page that follows, so page 140 is read in the light of pages 1 to 139.
At the end it pulls the whole book together from every page-tagged note and its latest understanding. A very long book is summarised part by part first, so no single request grows without limit.
Here is page 33 of meditations.pdf from a real run on Grok. Look at the first point: a sentence that started at the bottom of page 32 gets finished here.
π Reading page 33/248...
π The catalogue finishes Rusticus with careful reading, slow assent, and Epictetus, then credits Apollonius withβ¦
β
Found 11 new knowledge points (23 so far) Β· 26.2 s
β’ The lesson from Rusticus that broke off at the end of the previous page is completed here: read carefully andβ¦
β’ Marcus owes to Rusticus his acquaintance with the discourses of Epictetus, which Rusticus communicated to himβ¦
β’ From Apollonius (Book I, section 8) Marcus learned freedom of will and undeviating steadiness of purpose, andβ¦
β¦ and 8 more
πΎ Saved knowledge base (23 items)
And when it stops to look back (that test run used --interval 2; the default is every 20 pages):
π Progress: 32/248 pages read
π€ Updating what I understand so far (12 new notes)...
β¨ What I understand so far, saved to: book_analysis/summaries/meditations_interval_00032.md
This repo is one small piece of what I build and share at echohive.ai: build better with AI, see markets more clearly, and strengthen the mind behind both.
- π₯ Get Amplified: a living field guide for AI, markets, and mind. 90+ self-paced video lessons, and some are free to watch. Also on Patreon.
- π§ 1000x Lab: live every Sunday at 12 PM Pacific. Join it live, then rewatch any past session in the archive. It comes with the Architect membership.
- β€οΈ Membership: start free and upgrade when you are ready. Join on Patreon.
- π€ Consulting: private, one-to-one strategic sessions on AI strategy, agentic systems, research and market intelligence. Bring an ambitious project or a consequential decision.
- πΊ YouTube and π @hive_echo for new videos and experiments.
For your_book.pdf:
book_analysis/
βββ pdfs/your_book.pdf # a copy of the book (other formats go in books/)
βββ knowledge_bases/your_book_knowledge.json # every note with its page, gists, progress
βββ summaries/
βββ your_book_interval_00020.md # what it understood after page 20
βββ your_book_interval_00040.md # ...after page 40, and so on
βββ your_book_final.md # the whole book, pulled together
The knowledge base is saved safely after every page, together with the book file's fingerprint and how it was cut into pages. If you change the book but keep its name, the reader stops instead of mixing two books; use --reset to start that book over. --reset only touches that one book's files.
Run python read_books.py --help for all of them. The ones you will use most:
| Option | What it does |
|---|---|
book |
The book to read: PDF, EPUB, Word, Markdown or text (default: meditations.pdf) |
--backend NAME |
Who reads it: openai (default), anthropic, gemini, xai, openrouter, claude, codex or grok |
--model NAME |
The model for pages and summaries (defaults below) |
--summary-backend, --summary-model |
Let a different backend or model write the summaries |
--effort LEVEL |
Reasoning effort, for models that have it (for example low, medium, high) |
--start-page N |
Start at page N, for example to skip the front matter |
--test-pages N |
Read only N pages, to try things out |
--interval N |
Look back every N pages (default: 20; 0 turns it off) |
--context-window N |
How many recent notes travel with each page (default: 8) |
--ocr auto |
Read scanned PDF pages with Tesseract (brew install tesseract on a Mac) |
--reset |
Forget this book's notes and summaries and start over |
--timeout SECONDS |
How long one model call may take (default: 600) |
--base-url URL |
Send --backend openai requests to another OpenAI-compatible endpoint |
The default models:
| Backend | Reads pages with | Writes summaries with |
|---|---|---|
openai |
gpt-6-luna |
gpt-6.1-sol |
anthropic |
claude-opus-5-5 |
claude-opus-5-5 |
gemini |
gemini-3.8-flash |
gemini-4-argon |
xai |
grok-4.7 |
grok-4.7 |
openrouter |
openai/gpt-6-luna |
openai/gpt-6.1-sol |
claude, codex, grok |
the CLI's own default | the same |
--model sets both; add --summary-model to give the summaries their own. On Anthropic, --model claude-haiku-5-5 reads for a fraction of the price of Opus. On Gemini, --effort takes minimal, low, medium or high. On OpenRouter, pick a model that can return structured outputs (this list); the reader only sends pages to providers that honour the format, and tells you if your model has none.
You can mix backends. For example, read with Grok but let Claude write the summaries:
python read_books.py your_book.pdf --backend grok --summary-backend claudeOnly the text the reader sends it: one page, the end of the page before it, and its own notes.
The API backends send that text with a fixed system prompt and nothing else: no tools, no files.
Each CLI call is a one-shot run with no shell, in an empty temporary folder, and with its tools switched off. The page text goes in through standard input (or a temporary prompt file for Grok), never on the command line. No call ever uses an always-approve or skip-permissions flag.
- Claude Code:
claude -p --tools "" --safe-mode --strict-mcp-config --no-session-persistence --json-schema ... - Codex:
codex exec -s read-only --ephemeral --ignore-user-configwith its shell, exec, image and plugin features turned off and web search disabled, plus--output-schema. - Grok Build:
--sandbox strict --no-subagents --disable-web-search, every built-in tool removed and denied, a turn limit, and--json-schema.
You can see every flag in backends.py.
Codex and Claude runs are not saved anywhere. Grok Build has no such option yet, so it keeps each page's call in its own local session history (~/.grok/sessions), like any other Grok session.
- A CLI is slower than an API. Every page starts a fresh CLI run, and that startup time comes on top of the model's own thinking. In our 3 page test with each CLI's default model, a page took about 10 seconds on Claude Code, about 13 seconds on Codex and about 19 seconds on Grok. So a 250 page book is roughly an hour or more of reading, plus the summaries. You can leave it running, and Ctrl+C never loses a finished page.
- An API key is billed per use. A book is one call per page plus a few summaries, so a 250 page book is a few hundred calls. Try
--test-pages 3first to see what a page costs you. - Limits can stop a long book. When your plan hits its usage limit or your API account runs out of credit, the reader stops, keeps every page so far, and tells you. Run the same command later and it carries on.
- Your book's text goes to the provider you choose (OpenAI, Anthropic, Google, xAI, or OpenRouter and the provider it routes to), under your account's terms. Only send books you are happy to share with them.
- Summaries are AI writing. They can miss or bend things. Every note keeps its page number, so you can check it against the book.
- PDF text is not always clean. Multi-column or heavily designed pages can come out in the wrong order, and scanned pages need
--ocr auto. - Reader pages are not printed pages. For EPUB, Word, Markdown and text, a note's page number counts reader pages, so it won't match a printed edition of the book.
pip install -r requirements-dev.txt
python -m pytest -qThe tests use fake backends, a stand-in CLI, and the real OpenAI and Anthropic SDKs talking to a fake server, so they never call a real model or use any of your plan or credit.
Thanks to xdlkc for the pull request that made reading resumable: safe saving after every page, page-tagged notes, bounded summaries, OCR and the first test suite. This version builds on it. Thanks to TomLucidor for the idea of reading EPUB and other lighter formats directly.
MIT, see LICENCE.