Later.ink
Your Readwise Reader queue, on your e-reader.
Later.Ink is a small server that turns your Readwise Reader account into an OPDS catalog. Point KOReader — or any ebook reader that speaks OPDS, including on iPhone and iPad (Fablum, justRead, PocketBook), Android (Moon+ Reader), or desktop (Thorium Reader) — at one URL and browse your saved articles, downloading any of them as a clean EPUB, generated on the fly from the article HTML that Reader has already cleaned up.
No plugin, no sync daemon, and nothing to install from us — ebook readers already speak OPDS.
Free and open source (MIT), and built to self-host with your own Readwise token. Run it on a NAS, a Raspberry Pi, a VPS, or your laptop — it stores nothing, reading your queue live from Readwise.
Scope: later.ink is a reading path, not a sync path. It never writes back to Readwise, so articles stay in your queue as you read them. If you want finished articles archived and removed from the device automatically, the Endle/readwisereader KOReader plugin does that — this project trades write-back for zero install and working on any OPDS client. (Note: Readwise already serves Kindle natively via send-to-Kindle; the sweet spot here is Kobo, Boox, and other non-Kindle e-ink.)
Self-host quickstart
Upgrading from ≤0.3.x? The internal package was renamed for the brand:
read_later_opdsis nowlater_ink. Docker users just rebuild (docker compose up -d --build --remove-orphans— the flag retires the container from the oldopdsservice name). If you run without Docker, reinstall (pip install -e .) and use the new module path:python -m uvicorn later_ink.main:app .... Your.envand database are untouched. One cosmetic side effect: EPUB identifiers changed with the rename, so a re-downloaded article registers as a new book in your reader's library rather than an update to the old copy.
Prebuilt image (fastest — no checkout; amd64 & arm64, Pi included):
docker run -d --name later-ink -p 8000:8000 \
-e READWISE_TOKEN=your_token_from_readwise.io/access_token \
-e DATABASE_PATH=/data/app.db -v later-ink-data:/data \
--restart unless-stopped \
ghcr.io/brendanlefebvre/later-ink:latest
(Or pin a version tag, e.g. :0.4.1. Add -e WALLABAG_*=... vars
to serve Wallabag too — see .env.example for the full list.
The same image drops straight into a Compose file or Portainer stack.)
With Docker Compose, from source:
git clone https://github.com/brendanlefebvre/later-ink.git
cd later-ink
mkdir -p ~/.config/later-ink && cp .env.example ~/.config/later-ink/env
# edit that file: READWISE_TOKEN=<your token from https://readwise.io/access_token>
docker compose up -d
Without Docker (Python 3.11+):
pip install later-ink
READWISE_TOKEN=your_token python -m uvicorn later_ink.main:app --host 0.0.0.0 --port 8000
Or from a source checkout:
git clone https://github.com/brendanlefebvre/later-ink.git
cd later-ink
python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
pip install .
mkdir -p ~/.config/later-ink && cp .env.example ~/.config/later-ink/env
# edit that file: READWISE_TOKEN=<your token from https://readwise.io/access_token>
python -m uvicorn later_ink.main:app --host 0.0.0.0 --port 8000
Config is read from $XDG_CONFIG_HOME/later-ink/env (default
~/.config/later-ink/env), falling back to ./.env; variables already set in
the real environment always take precedence.
Your catalog is now at http://your-host:8000/opds/.
KOReader setup: top menu → magnifying glass → OPDS catalog → + → enter
the URL. Browse folders (Later, New, Shortlist, Archive, Feed), tap an article
to download and read. Images are embedded in the EPUB, so articles read fully
offline. Use KOReader's OPDS search box to find articles by title, author, or
summary; search scans your most recent saved items (a bounded slice of a very
large queue) rather than the entire history.
On iPhone/iPad: use an ebook reader that supports OPDS — Fablum, justRead, or PocketBook — and add the same catalog URL. On desktop: Thorium Reader works too.
What appears: articles, newsletters, PDFs, books (uploaded EPUBs), video
transcripts, tweet threads, and podcasts — each delivered as an EPUB, converted
from the content Readwise exposes. Multi-section books and long articles are split
into chapters with a navigable table of contents, and every EPUB opens on a
generated cover. A podcast converts only after you've loaded its transcript in
Readwise Reader (until then the API returns a stub, and the download reports
that). Configurable via READWISE_CATEGORIES (e.g. article,pdf).
Hosted version
There's no public hosted instance running yet — self-hosting is the supported
path today. The server does include an optional multi-tenant mode (short,
e-ink-typeable catalog URLs like later.ink/maple-crater-lantern-owl/, with per-user
tokens encrypted at rest), so a free hosted instance may come later. If you want
to stand one up yourself, see the multi-tenant env vars in .env.example.
Architecture
src/later_ink/
main.py # FastAPI routes: OPDS feeds, EPUB downloads, onboarding
config.py # env-var configuration
opds.py # OPDS 1.x Atom feed builder
epub.py # HTML → EPUB (ebooklib + lxml cleanup)
covers.py # generated EPUB covers (hero image + typographic fallback)
store.py # SQLite user store + word-based secret URLs
words.py # wordlist behind the secret URLs (e-ink-typeable words)
ratelimit.py # per-IP throttle for unknown-secret probes
pages.py # server-rendered HTML pages
payments.py # Stripe verification (optional; inactive unless configured)
connectors/
base.py # Connector interface: folders / articles / article HTML
readwise.py # Readwise Reader API v3 connector
wallabag.py # Wallabag API v2 connector (OAuth2)
Readwise and Wallabag are supported today (set the
WALLABAG_* vars in .env.example to enable Wallabag). More connectors
(Instapaper) are planned — the connector interface is three methods.
Development
pip install -e ".[dev]"
ALLOW_FREE_SIGNUP=1 python -m uvicorn later_ink.main:app --reload
pytest
pyproject.toml keeps loose >= ranges, which is what anyone installing
Later.ink from PyPI resolves against. CI and the Docker image instead install
from requirements.txt / requirements-dev.txt, which pin every transitive
dependency with hashes, so a release is built from the versions that were
actually tested. Regenerate them after changing a dependency:
uv pip compile pyproject.toml --universal --generate-hashes \
--python-version 3.11 -o requirements.txt
uv pip compile pyproject.toml --extra dev --universal --generate-hashes \
--python-version 3.11 -o requirements-dev.txt
--universal keeps one file valid for both image architectures;
--python-version 3.11 matches the project's floor rather than whichever
interpreter you happen to be running. The audit CI job runs pip-audit
against the lock — pinning freezes known vulnerabilities in place as surely as
it freezes versions, so that job is what makes a stale pin visible.
Credits
Generated EPUB covers use League Spartan
by The League of Moveable Type, bundled under the SIL Open Font License
(src/later_ink/assets/fonts/OFL.txt).
License
MIT
Metadata
Release files for later-ink 0.4.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| later_ink-0.4.4.tar.gz | 1.4 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| later_ink-0.4.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.6 MB
Release files / later_ink-0.4.4.tar.gz
| Download URL | later_ink-0.4.4.tar.gz |
|---|---|
| Size | 1.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
befb30329ccb3d1d125d0c26f597d562040c624c2572b693b078a724d102ab8c
|
|
BLAKE2b-256 checksum How to use checksums |
ea3e09599461c520a6c5080f89635591cd4dfcc6eff09be35c8d5092d868649f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 8, 2026.
Transparency logRelease files / later_ink-0.4.4-py3-none-any.whl
| Download URL | later_ink-0.4.4-py3-none-any.whl |
|---|---|
| Size | 1.3 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c8656c963eed40d4d3dc96e3ce93f3e4d567bb5944a2ed959d635d7a45e1aba9
|
|
BLAKE2b-256 checksum How to use checksums |
51bcc46d8486ba7a29214309d8bf1a30f830b1316d2fbc95edf274472d2ad375
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 8, 2026.
Transparency log