Bridge a Zotero collection to a reMarkable Paper Pro: push PDFs, pull annotations.
Project description
zotrm
Read your Zotero papers on a reMarkable Paper Pro, then get your handwritten notes back into Zotero — with one command.
Demo
Recording the GIF: see how to record the demo.
What it does, in plain words:
- push — sends the PDFs from one Zotero collection to your reMarkable tablet.
- pull — brings the marked-up PDFs back and attaches them to the same Zotero papers.
- status — shows which papers are waiting, on the tablet, or already done.
- sync — does a pull and then a push, together.
You never push or pull the same paper twice by mistake — the tool remembers what it has done. It is safe to run again and again.
One honest limit (this is reMarkable's behavior, not a bug here): Your highlights and handwriting come back as part of the PDF image — "painted onto" the page. They do not come back as clickable Zotero highlights.
Why zotrm?
If you read research papers on a reMarkable, getting them on and off the tablet is fiddly: export each PDF, drag it into the reMarkable app, and later dig the annotated copy back out and re-file it in Zotero. zotrm makes that one command in each direction, driven by the collection you already curate in Zotero:
- No manual file shuffling — it reads your Zotero collection and uploads the PDFs for you.
- Folders match your library — Zotero sub-collections become nested folders on the tablet.
- Nothing pushed or pulled twice — progress is tracked with Zotero tags, so it's safe to
re-run or schedule with
zotrm cron. - No extra database or account — just your Zotero API key and the
rmapitool.
It's a small, focused CLI — not a sync daemon or a cloud service.
Before you start (what you need)
- A Zotero account with some PDFs in it.
- A reMarkable tablet, turned on and connected to WiFi.
- A reMarkable Connect subscription — this is what lets files move to and from the tablet over the internet. Without it, push and pull may not work.
- A computer (Mac or Linux) where you can open a Terminal (a window where you type commands). On a Mac, open the app called Terminal.
You will copy and paste a few commands. That is all.
Setup (about 10 minutes)
Step 1 — Install uv
uv installs this tool for you. Paste this into the Terminal and press Enter:
curl -LsSf https://astral.sh/uv/install.sh | sh
Close the Terminal and open it again so the change takes effect.
Step 2 — Install rmapi and connect it to your tablet
rmapi is a separate program that talks to your reMarkable:
brew install rmapi
(No Homebrew? See https://github.com/ddvk/rmapi for other ways. Use the ddvk version — the original does not work with new tablets.)
Now connect it to your tablet one time:
rmapi
It shows a web address and asks for a code. Open https://my.remarkable.com/device/desktop, copy the code shown there, and paste it into the Terminal. Done — you won't do this again.
Step 3 — Install zotrm
uv tool install zotrm
Step 4 — Set up your account
A friendly wizard fills in your settings for you. First grab two things from Zotero, then run it.
4a. Get your Zotero details (about a minute)
Open https://www.zotero.org/settings/keys and log in. You need two things from this page:
- Your library ID — near the top it reads "Your userID for use in API calls is 1234567." That number is your library ID.
- An API key — click Create new private key, give it a name, tick Allow library
access with both read and write (write lets
zotrmsave tags and attach your annotated PDFs), click Save Key, and copy the key — you can't see it again later.
4b. Make a collection to sync (recommended)
In the Zotero app, create a collection — say, named reMarkable — and drag in a few papers
you want to read. zotrm only ever touches papers in this one collection. Start with a
throwaway collection of 1–2 papers while you try things out.
4c. Run the wizard
zotrm config
Use the arrow keys ↑↓ to choose and Enter to confirm. Here is every question and what to put:
| Question | What to enter |
|---|---|
| Zotero library ID | The userID number from step 4a. |
| Zotero API key | The key from step 4a (hidden as you type/paste). |
| Library type | user — choose group only for a shared group library. |
| Local Zotero storage dir (optional) | Where the Zotero app keeps your PDFs, usually ~/Zotero/storage. Lets zotrm read files from disk instead of re-downloading. Press Enter to skip if unsure. |
| Zotero collection to sync | The collection name from step 4b (e.g. reMarkable) — must match exactly, capitals included. |
| reMarkable folder | Where papers land on the tablet, e.g. /Papers (created if missing). |
| Mirror sub-collections? | Yes recreates your Zotero sub-collections as nested folders on the tablet; No puts everything in one folder. |
| Where to save annotated PDFs | A folder on your computer for the marked-up copies, e.g. ~/Zotero/annotated. |
| Re-attach annotated PDF? | Yes adds the annotated copy back onto the paper in Zotero. |
When you finish, it checks your details (you'll see ✓ Zotero connection OK), warns if
rmapi is missing, and saves everything to ~/.config/zotrm/config.ini.
The wizard also starts on its own the first time you run any command before setting up. To change settings later, run
zotrm configagain; to see what's saved (API key masked), runzotrm config --show.
Step 5 — Use it
Send your papers to the tablet:
zotrm push
Read and annotate them on the reMarkable. When you're done, bring them back:
zotrm pull
That's the whole loop. 🎉
Step 6 (optional) — Make it automatic
Want it to sync by itself on a schedule? Run:
zotrm cron
Pick how often (every hour, daily, etc.) and it sets everything up for you. Remove it
later with zotrm cron --remove.
Everyday commands
zotrm push # send waiting papers to the tablet
zotrm pull # bring marked-up papers back into Zotero
zotrm status # see what is waiting / on the tablet / done
zotrm sync # pull, then push, in one step
zotrm config # change your settings any time
zotrm cron # set up (or change) automatic syncing
Not sure what a command will do? Add --dry-run to see without changing anything:
zotrm --dry-run push
If something goes wrong
- "rmapi not found" → Step 2 was missed, or reopen the Terminal.
- "config not found" → Run
zotrm configto set up your account. - "no Zotero collection named ..." → The collection name in your settings doesn't
exactly match a collection in Zotero. Check spelling and capital letters
(
zotrm config --showprints your current settings). - Pull finds nothing → Make sure the tablet is online and finished syncing, and that you have a reMarkable Connect subscription.
Run any command with --dry-run first if you're unsure — it changes nothing.
FAQ
Do I need a reMarkable Connect subscription?
Yes, in practice. zotrm talks to the reMarkable cloud through rmapi, and two-way
document sync (uploading PDFs and downloading annotated ones) needs Connect.
Why don't my highlights come back as real Zotero highlights?
The reMarkable returns a flattened PDF — your marks are baked into the page image. That's a
reMarkable limitation, not something zotrm can change. You get a faithful annotated PDF
re-attached to the item, just not editable highlight objects.
Does it duplicate files if I run it again?
No. It tags items rm:synced once pushed and rm:annotated once pulled back, and skips
anything already done. Re-run it (or schedule it) freely.
Can I use it with more than one Zotero library?
Yes — keep separate config files and pass --config. See
advanced usage.
Does it work on Windows?
Not currently. zotrm targets macOS and Linux (the cron scheduler is Unix-only).
Is my Zotero API key safe?
It's stored only in your local config file (~/.config/zotrm/config.ini) and never sent
anywhere except Zotero's own API. zotrm config --show masks it.
More
- Advanced usage — editing the config file by hand, the full settings reference, how the scheduled sync works, multiple configs, and deeper troubleshooting.
- Contributing — set up the project for development and run the tests.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zotrm-0.1.1.tar.gz.
File metadata
- Download URL: zotrm-0.1.1.tar.gz
- Upload date:
- Size: 2.0 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7afd3de17a2163a1dcde8285e847cc990baa7b0f01739a7288063248d8a8a2f1
|
|
| MD5 |
d4ff5261230f2595679e05ec6b492956
|
|
| BLAKE2b-256 |
eb37003837ab0083af28b67455559d2f2ebfbf372abb0e26ee840a38fe5e4c20
|
Provenance
The following attestation bundles were made for zotrm-0.1.1.tar.gz:
Publisher:
release.yml on dipta007/zotRm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zotrm-0.1.1.tar.gz -
Subject digest:
7afd3de17a2163a1dcde8285e847cc990baa7b0f01739a7288063248d8a8a2f1 - Sigstore transparency entry: 1944959197
- Sigstore integration time:
-
Permalink:
dipta007/zotRm@e7e10ceaf164f6b44ecf0c9403023a6aa2d93350 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/dipta007
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e7e10ceaf164f6b44ecf0c9403023a6aa2d93350 -
Trigger Event:
push
-
Statement type:
File details
Details for the file zotrm-0.1.1-py3-none-any.whl.
File metadata
- Download URL: zotrm-0.1.1-py3-none-any.whl
- Upload date:
- Size: 17.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9efc7696ac2544783bcd329d4c5c76e6d23e148611e4ba3ad5d3f7b129c99250
|
|
| MD5 |
7e3f0d6e8c5a9f1cb55eee6b3f8de33f
|
|
| BLAKE2b-256 |
2a9c20eabb8b5df24486925cac6f6b3317238b9d9769805a9367433aa7e3b119
|
Provenance
The following attestation bundles were made for zotrm-0.1.1-py3-none-any.whl:
Publisher:
release.yml on dipta007/zotRm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zotrm-0.1.1-py3-none-any.whl -
Subject digest:
9efc7696ac2544783bcd329d4c5c76e6d23e148611e4ba3ad5d3f7b129c99250 - Sigstore transparency entry: 1944959319
- Sigstore integration time:
-
Permalink:
dipta007/zotRm@e7e10ceaf164f6b44ecf0c9403023a6aa2d93350 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/dipta007
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e7e10ceaf164f6b44ecf0c9403023a6aa2d93350 -
Trigger Event:
push
-
Statement type: