Skip to main content

Export Zotero collections into clean, incremental research workspaces.

Project description

Zotero Project Manager (zpm)

zpm creates clean, ordinary project folders from Zotero collections. Zotero remains the source of truth; zpm only reads its database and attachments and writes into a separate output directory.

The current release supports recursive collection export, multiple collections, portable metadata-based filenames, incremental updates, SHA-256 verification, safe pruning, DOI/tag metadata, Markdown indexes, dry runs, diagnostics, and a versioned JSON manifest.

Quick start: export My-AI

On this Mac, zpm is installed as a user-local command and can be run from any directory. Export My-AI with:

zpm export "My-AI" --output ~/ResearchProjects

The files are written to:

~/ResearchProjects/My-AI/

Preview the export without writing anything:

zpm export "My-AI" --output ~/ResearchProjects --dry-run --verbose

Run the same zpm export command whenever the Zotero collection changes. The manifest makes the update incremental: new or changed PDFs are copied and unchanged PDFs are left alone.

Inspect changes without writing anything:

zpm status "My-AI" --output ~/ResearchProjects

Preview files removed from Zotero that can be safely pruned:

zpm status "My-AI" --output ~/ResearchProjects --prune

After reviewing the preview, apply safe pruning:

zpm export "My-AI" --output ~/ResearchProjects --prune

Only manifest-owned files whose SHA-256 still matches are deleted. Files changed outside zpm, files without a trusted hash, and unsafe paths are protected.

Other useful global commands:

zpm list
zpm doctor --output ~/ResearchProjects
zpm export --help
zpm --version

Configuration and named projects

Set global defaults once:

zpm config set --zotero-dir ~/Zotero --output ~/ResearchProjects
zpm config show

The default configuration file is ~/.config/zpm/config.toml. Override it with the global --config PATH option or the ZPM_CONFIG environment variable.

Create a named project from one or more collections:

zpm project add ai "My-AI" "Claude"
zpm project list
zpm project show ai

Synchronize it from any directory:

zpm sync ai
zpm sync ai --dry-run

A named project can save recursive traversal, non-PDF inclusion, pruning, full hash verification, metadata generation, and its own output directory. Use --force with zpm project add to replace an existing project definition.

Metadata and research index

Exports generate two additional workspace files by default:

  • metadata.json contains collection keys, Zotero item and attachment keys, titles, dates, creators, DOI, tags, source and destination paths, state, and SHA-256.
  • INDEX.md provides a human-readable table with DOI links and relative PDF links.

Disable these generated artifacts when needed:

zpm export "My-AI" --output ~/ResearchProjects --no-metadata

For safety, zpm refuses to overwrite an existing metadata.json or INDEX.md unless that file was previously generated by zpm.

Safety model

  • The Zotero database is opened with SQLite mode=ro and PRAGMA query_only.
  • Queries run in a consistent read-only SQLite transaction. Optional --snapshot mode uses the SQLite backup API when an isolated copy is useful.
  • zpm never renames, moves, or edits Zotero files.
  • Output paths inside the Zotero data directory are rejected.
  • Existing directories without a zpm manifest are rejected unless explicitly adopted with --overwrite.

Always keep independent backups of important research data.

Requirements and installation

  • Python 3.11 or newer

Install the current GitHub release globally with pipx:

brew install pipx
pipx install git+https://github.com/sbilmis/zotero-project-manager.git

After the first PyPI release is published, the shorter command is:

pipx install zotero-project-manager

Upgrade an existing pipx installation with:

pipx upgrade zotero-project-manager

Install from a checkout:

python -m pip install .

For development:

python -m pip install -e '.[dev]'
pytest

Usage

Optional shell helpers

For a checkout at ~/zotero-collection-mirror, create its environment once:

cd ~/zotero-collection-mirror
python -m venv .venv
.venv/bin/pip install -e .

Load the convenience functions in the current shell:

source ~/zotero-collection-mirror/scripts/zpm-helper.sh

Then use:

zpm_collections
zpm_my_ai
zpm_export "My-AI" "Claude"
zpm_export "My-AI" --dry-run --verbose

The helpers default to ~/Zotero and ~/ResearchProjects. Override these locations before sourcing the file when needed:

export ZPM_ZOTERO_DIR="/path/to/Zotero"
export ZPM_OUTPUT_DIR="/path/to/ResearchProjects"
source ~/zotero-collection-mirror/scripts/zpm-helper.sh

List collections, including the keys needed to disambiguate duplicate names:

zpm list
zpm list --zotero-dir ~/Zotero

Export one collection to the current directory:

zpm export "My-AI"

Export several collections beneath a chosen parent directory:

zpm export "My-AI" "Claude" "Image_Processing" --output ~/ResearchProjects

Useful options:

--recursive / --no-recursive       Include descendants (default: recursive)
--pdf-only / --include-non-pdf     Attachment filter (default: PDF only)
--dry-run                          Show counts without writing
--prune                            Safely remove hash-verified stale exports
--verify                           Fully recompute source and destination hashes
--metadata / --no-metadata        Enable or disable metadata and index generation
--overwrite                        Adopt an unmanaged destination
--verbose                          Enable diagnostic messages
--linked-attachment-base-dir PATH  Resolve Zotero relative linked files
--snapshot                         Query an isolated temporary database copy

Collection selectors are matched first by exact Zotero key, then by case-insensitive full collection name. Ambiguous names produce an error listing the usable keys.

Incremental behavior

Each workspace contains manifest.json and README.md. On later runs, zpm uses recorded source and destination metadata plus SHA-256 digests to:

  • leave unchanged files alone;
  • replace changed managed files;
  • copy newly discovered files;
  • report missing source attachments without deleting an earlier export.
  • reconcile identical files re-added under a new Zotero attachment key;
  • track files removed from the collection until they are safely pruned.

--overwrite is not needed for normal updates. It is the explicit opt-in for adopting an existing directory or replacing an unmanaged filename conflict. Use --verify for a full content audit even when file metadata appears unchanged.

Manifest v1 workspaces are read automatically. The next successful export adds hashes and upgrades the manifest to v2; status and --dry-run never rewrite it.

Troubleshooting

Zotero database is locked

Zotero can normally remain open because zpm uses read-only SQLite access and waits briefly for transient locks. An export may still be blocked while Zotero is syncing, upgrading its database, or performing maintenance.

If zpm reports that the database is locked:

  1. Wait for Zotero synchronization or maintenance to finish, then retry.
  2. If it remains locked, close Zotero completely and run the command again.
  3. Use zpm doctor --output ~/ResearchProjects to check the configuration.

zpm does not modify Zotero when a lock occurs. A lock error happens before the collection can be read or any export changes are applied.

Attachment paths

Stored Zotero attachments (storage:...), absolute linked paths, and file:// paths are resolved automatically. Zotero's attachments:... relative paths require --linked-attachment-base-dir because that preference is not stored in zotero.sqlite.

Development layout

src/zotero_project_manager/
    cli.py          CLI parsing and presentation
    zotero.py       read-only SQLite and attachment path resolution
    collections.py hierarchy, lookup, and traversal
    exporter.py     safe incremental export orchestration
    filenames.py    portable filename generation and collisions
    manifest.py     versioned manifest serialization
    metadata.py     JSON metadata and Markdown research indexes
    models.py       shared domain dataclasses
    diagnostics.py  read-only doctor checks
    config.py       TOML defaults and named projects
    utils.py        logging and path safety helpers

Non-goals for v0.2

Better BibTeX, annotation export, DEVONthink or NotebookLM automation, watch mode, a GUI, and symlink mode are not implemented yet.

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

zotero_project_manager-0.5.0.tar.gz (33.3 kB view details)

Uploaded Source

Built Distribution

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

zotero_project_manager-0.5.0-py3-none-any.whl (31.0 kB view details)

Uploaded Python 3

File details

Details for the file zotero_project_manager-0.5.0.tar.gz.

File metadata

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

File hashes

Hashes for zotero_project_manager-0.5.0.tar.gz
Algorithm Hash digest
SHA256 67c12c8e2891ce042fb2da7a6bd7808ab1b10b2f7226e7b32ce71faeacec89ef
MD5 c700c9863f2bd10fcd6838f3cc9db2b4
BLAKE2b-256 bad86df79822c3441fd67f4905fe526959b2304261e2083b5d52bc5ff4d6999e

See more details on using hashes here.

Provenance

The following attestation bundles were made for zotero_project_manager-0.5.0.tar.gz:

Publisher: publish.yml on sbilmis/zotero-project-manager

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

File details

Details for the file zotero_project_manager-0.5.0-py3-none-any.whl.

File metadata

File hashes

Hashes for zotero_project_manager-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 74de512fe6d725d9bd38091ebcf51ad02c165794193d831d73239abec6a17058
MD5 fe209a994bf5a786e3c51173c7517e8f
BLAKE2b-256 56dbee42ddd4cf13355288142261fd7be5fecf5827d4bda0d6494260fc17c03a

See more details on using hashes here.

Provenance

The following attestation bundles were made for zotero_project_manager-0.5.0-py3-none-any.whl:

Publisher: publish.yml on sbilmis/zotero-project-manager

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