NoteroPDF
NoteroPDF puts the PDFs in your personal Zotero library onto the matching Notion pages created by Notero.
NoteroPDF is a terminal application. You install it once, then run one command whenever you want to sync.
It is designed around one workflow:
install → open Zotero → run → paste a Notion token → choose database → preview → confirm
No configuration file or hosted service is required.
Before You Start
You need:
- Zotero with a personal library and local PDF attachments
- Notero already syncing that library to a Notion database
- full membership in the Notion workspace, with permission to create a personal access token
Leave Zotero open and enable Settings → Advanced → Allow other applications on this computer to communicate with Zotero. NoteroPDF makes only read requests to Zotero's local API and never changes the Zotero library.
Group libraries are not supported in this release.
Install
From PyPI (recommended)
NoteroPDF requires Python 3.10 or newer and is tested through Python 3.14. Install it as an isolated command-line application with pipx:
pipx install noteropdf
noteropdf --version
If pipx is not available, use pip:
python -m pip install noteropdf
To update, run pipx upgrade noteropdf. If the command is not found, restart the
terminal or run python -m noteropdf (py -m noteropdf on Windows).
Use
Run one command:
noteropdf
On the first run, NoteroPDF:
- Connects to your personal Zotero library.
- Opens Notion's personal access token page in the browser.
- Asks you to create a token with the Notion API capability and paste it once. The token input is hidden.
- Saves the token in your operating system's credential store.
- Lets you choose the database managed by Notero.
- Finds a dedicated
NoteroPDF PDFfiles property, or asks before creating it. - Matches items through their exact Notero-created links and shows what will be uploaded.
- Uploads PDFs only after one confirmation.
Later runs go directly to the preview. If no interactive terminal is available, sync remains preview-only unless --apply is supplied and exits nonzero when uploads are pending.
Commands
| Command | Purpose |
|---|---|
noteropdf |
Preview, confirm, and sync. |
noteropdf sync |
The same complete sync workflow. |
noteropdf sync --apply |
Preview and apply without a prompt; useful for automation. |
noteropdf connect |
Reconnect Notion or choose a different database. |
noteropdf doctor |
Check Zotero, Notion, credentials, schema, and local storage. |
noteropdf --version |
Show the installed version. |
Add --verbose for technical details or --no-color for plain terminal output.
Safe by Design
- The preview never writes to Notion.
- Confirmation applies only the exact file/page actions in that preview.
- A changed PDF or missing target page is skipped and must be previewed again.
- A Notion PDF field changed after preview is skipped instead of overwritten.
- Multiple or unknown files in the destination field are never removed.
- Ambiguous PDF or Notion matches are skipped instead of guessed.
- Uploads are serial, retry transient Notion errors, and respect
Retry-Afterand workspace size limits. - Zotero data and PDFs go directly from your computer to Notion. NoteroPDF has no hosted service.
- In normal setup, the Notion token is stored only in Keychain, Credential Manager, Secret Service, or KWallet. Setup stops with a clear error if the operating system's credential store is unavailable.
- A small rotating diagnostic log is retained (the current file plus up to three backups).
Matching is deliberately narrow: an item must have exactly one Notero-created
link attachment named Notion, and the linked page must be accessible in the
selected database. NoteroPDF does not fall back to Zotero URI, DOI, title, or
fuzzy matching. Unrelated Notion bookmarks are ignored. Notion property IDs are
stored locally, so renaming a connected column does not break sync.
Troubleshooting
Start with:
noteropdf doctor
Then try noteropdf connect if the token expired or was revoked, the selected database changed, or a required property was removed. Choose not to reuse the saved token when you need to paste a replacement. Common skips such as no PDF, multiple PDFs, a missing Notero link, or an oversized file are explained in the terminal without changing either library.
If doctor reports that the running Zotero library cannot be read, confirm that
Zotero is open and its local API setting under Settings → Advanced is enabled.
To repair a pipx installation, run pipx reinstall noteropdf. For pip, use
python -m pip install --upgrade --force-reinstall noteropdf.
Notion personal access tokens act with your existing page permissions and can be created only by eligible full workspace members. Choose the Notion API capability, treat the token like a password, and replace it before its selected expiration date (at most one year). See Notion's personal access token guide.
The diagnostic log is stored in the operating system's normal per-user log folder for NoteroPDF. It can include Zotero titles, item keys, and Notion page IDs needed for troubleshooting; review it before sharing.
Development
See Contributing for project invariants and Maintaining and Releasing for the complete local-to-release workflow. Report vulnerabilities through the Security policy.
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 noteropdf-0.4.0.tar.gz.
File metadata
- Download URL: noteropdf-0.4.0.tar.gz
- Upload date:
- Size: 53.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b487afc76de5b5b02401d2f2a2426307205996bb9b31b8a96b57bcddb53f1d73
|
|
| MD5 |
b0873c9c53e7b98fb85651b8b4493986
|
|
| BLAKE2b-256 |
9b0f627205f9a55d31432f6b9fd74f6a5de9b42cc25ee5f7742de4891cda2704
|
Provenance
The following attestation bundles were made for noteropdf-0.4.0.tar.gz:
Publisher:
release.yml on diyanko/NoteroPDF
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
noteropdf-0.4.0.tar.gz -
Subject digest:
b487afc76de5b5b02401d2f2a2426307205996bb9b31b8a96b57bcddb53f1d73 - Sigstore transparency entry: 2401350304
- Sigstore integration time:
-
Permalink:
diyanko/NoteroPDF@cb8bc3e1a0b210a00f2675e4a84dd14c9c7c71b1 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/diyanko
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@cb8bc3e1a0b210a00f2675e4a84dd14c9c7c71b1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file noteropdf-0.4.0-py3-none-any.whl.
File metadata
- Download URL: noteropdf-0.4.0-py3-none-any.whl
- Upload date:
- Size: 38.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
21f301bd7fb016eb8c250522cde46d03942296591d1d6d1039588643844fd4c3
|
|
| MD5 |
15b88c8d933aad8f8571049b7fdb10ca
|
|
| BLAKE2b-256 |
e9ef8f395dae4de11eefc0856dcf08eafdb19227ee6b1deff0d72fbffaab4450
|
Provenance
The following attestation bundles were made for noteropdf-0.4.0-py3-none-any.whl:
Publisher:
release.yml on diyanko/NoteroPDF
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
noteropdf-0.4.0-py3-none-any.whl -
Subject digest:
21f301bd7fb016eb8c250522cde46d03942296591d1d6d1039588643844fd4c3 - Sigstore transparency entry: 2401350324
- Sigstore integration time:
-
Permalink:
diyanko/NoteroPDF@cb8bc3e1a0b210a00f2675e4a84dd14c9c7c71b1 -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/diyanko
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@cb8bc3e1a0b210a00f2675e4a84dd14c9c7c71b1 -
Trigger Event:
push
-
Statement type: