Skip to main content

Deterministic local Zotero PDF to Notion files-property sync CLI

Project description

NoteroPDF

NoteroPDF uploads local Zotero PDFs to a files property in a Notion database already managed by Notero.

It reads Zotero in read-only mode, finds one deterministic PDF per item, matches the corresponding Notion row, and uploads the file.

Before You Start

You need:

  • Zotero installed with a local personal library
  • A Notion integration token
  • A Notero-managed Notion database shared with that integration
  • A Notion files property in that database, usually named PDF

Install

Standalone Bundle

Recommended for most users. Download the release bundle for your OS, extract it, place the noteropdf executable on your PATH, and run:

noteropdf setup

Python is not required when using the standalone bundle.

On macOS, the bundle can still hit Gatekeeper or privacy permission prompts on some systems. If that happens, xattr may clear the quarantine flag, but it does not fix every security or access failure.

xattr -dr com.apple.quarantine /path/to/noteropdf

If the macOS bundle still fails after that, use the source install below.

Source Install

Use this path on macOS if the bundle is blocked by system security or permission prompts.

Supported Python versions: 3.11, 3.12, 3.13.

python -m venv .venv
# Windows PowerShell
.venv\Scripts\Activate.ps1
# macOS/Linux
source .venv/bin/activate
python -m pip install -U pip
python -m pip install .

Run with:

python -m noteropdf setup

Contributor Install

python -m venv .venv
# Windows PowerShell
.venv\Scripts\Activate.ps1
# macOS/Linux
source .venv/bin/activate
python -m pip install -U pip
python -m pip install -e ".[dev]"

Use It

Start with the guided setup:

noteropdf setup

Then check that Zotero and Notion are reachable:

noteropdf doctor

Run a preview sync first. Setup starts with dry_run: true, so this checks what would happen without changing Notion:

noteropdf sync

If the preview looks right, edit your saved config.yaml, set dry_run: false, and run:

noteropdf sync

To check for Notion rows that are safe cleanup candidates, run:

noteropdf cleanup

The preview can include rows whose Zotero item no longer exists and duplicate rows when Zotero still points to a different canonical Notero page for the same item.

If the cleanup preview looks right, apply it. NoteroPDF will ask once before moving rows to Notion trash:

noteropdf cleanup --apply

For scripted runs, use noteropdf cleanup --apply --yes to skip that confirmation.

The setup flow tries to detect your Zotero data folder, discover accessible Notion targets, and write config.yaml for you. If discovery cannot find a target, it asks for a Notion database URL/ID or data source URL/ID and continues.

Terminal output is meant to be readable for normal users. Detailed technical logs are still written to a log file for troubleshooting. Use --verbose when you want those details in the terminal, or --no-color if your terminal should stay plain.

What It Does

  • Matching order is fixed: Notero page link, Zotero URI, DOI
  • A Zotero item must have exactly one usable PDF attachment
  • Files over Notion's upload limit are skipped with a clear error
  • Files up to 20 MB use single-part upload
  • Larger files use Notion multi-part upload when the workspace supports it
  • Cleanup is separate from sync and only trashes rows with a strong stale or duplicate classification
  • Zotero data is never modified

What Changes In Notion

sync only updates the configured Notion files property, usually PDF, on rows that can be matched confidently to Zotero items.

cleanup does not run during sync. By default it only reports cleanup candidates. With cleanup --apply, it moves only strongly classified stale rows and canonical duplicates from the local personal Zotero library to Notion trash. It skips rows that are ambiguous, outside the local personal library scope, or missing the configured Zotero URI field, so you can review them manually.

Results

Each run writes local artifacts under standard OS app directories managed by platformdirs:

  • run logs
  • JSON report
  • CSV report
  • summary JSON

The terminal shows the short version. Reports contain the full item-by-item details.

Troubleshooting

  • NOTION_AUTH_ERROR: check that your Notion token is correct and that the database is shared with the integration.
  • NOTION_SCHEMA_ERROR: check that the selected database has the configured properties, especially the PDF files property.
  • NO_NOTION_MATCH: check the Notero page link, Zotero URI, or DOI for that item.
  • MULTIPLE_NOTION_MATCHES: more than one Notion row matches the same Zotero item; make the Notion data unique.
  • NO_PDF: add one PDF attachment to the Zotero item.
  • MULTIPLE_PDFS: keep only the intended PDF attachment for that Zotero item.
  • FILE_TOO_LARGE: the PDF is larger than Notion accepts for your workspace.
  • AMBIGUOUS_CLEANUP_MATCH: cleanup found duplicate Notion rows for a live Zotero item and skipped them for review.
  • UNMANAGED_NOTION_ROW: cleanup found a row without a usable Zotero URI and left it untouched.

For harder cases, rerun the same command with --verbose and check the detailed log path shown at the top of the terminal output.

Scope

  • Supported: Windows, macOS, Linux
  • Supported: personal Zotero libraries
  • Not supported in this release: Zotero group libraries

Contributor Docs

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

noteropdf-0.3.0.tar.gz (51.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

noteropdf-0.3.0-py3-none-any.whl (39.3 kB view details)

Uploaded Python 3

File details

Details for the file noteropdf-0.3.0.tar.gz.

File metadata

  • Download URL: noteropdf-0.3.0.tar.gz
  • Upload date:
  • Size: 51.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for noteropdf-0.3.0.tar.gz
Algorithm Hash digest
SHA256 68ba7b9b180c06a405b11accfcda7b6543d6ce3154b4a42bacef09ccda396340
MD5 670ee71be1f8cb60dd70626160468889
BLAKE2b-256 ddbfe54a471f87b2a36b469af036990637ae6b73fe4c5d8d6073a7dd48b34cdd

See more details on using hashes here.

Provenance

The following attestation bundles were made for noteropdf-0.3.0.tar.gz:

Publisher: release.yml on diyanko/NoteroPDF

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file noteropdf-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: noteropdf-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 39.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for noteropdf-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ef958b0bc1ae03f2f11a34b8c167507447935b1baf4ccd2f1509f370963c9c4b
MD5 d0460409cb919c59bec8a442be7ae594
BLAKE2b-256 545c29806d475dfd6582e761ee82b693a41ba4cd196db3cb2de03faf29beaac5

See more details on using hashes here.

Provenance

The following attestation bundles were made for noteropdf-0.3.0-py3-none-any.whl:

Publisher: release.yml on diyanko/NoteroPDF

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page