Headless Zotero-compatible runtime with CLI, HTTP API, MCP, local desktop interoperability, web sync, qmd-backed semantic search, and support for your agent tool of choice
Project description
zotero-headless
zotero-headless is a headless Zotero-compatible runtime with:
- a CLI for operators and scripts
- an HTTP API for apps and services
- an MCP server for agent tools
- a clean-room headless store
- Zotero web sync for user and group libraries
- local Zotero desktop interoperability
- qmd-backed semantic search that refreshes from library changes
- built-in recovery snapshots, restore flows, and backup repositories
It is built for two main deployment shapes:
- desktop interoperability: use an existing Zotero Desktop profile and optionally write supported changes back
- true headless runtime: run the daemon on a machine without Zotero Desktop and expose API or MCP to clients
Quick Setup
1. Install the CLI
uv tool install zotero-headless
or:
pipx install zotero-headless
Main entrypoints:
zotero-headless
zotero-headless-daemon
zotero-headless-mcp
Short aliases:
zhl
zhl-daemon
zhl-mcp
2. Run guided setup
zhl setup start
setup start tries autodiscovery first. On a normal desktop install it will usually find standard Zotero paths automatically, then prompt only for the missing pieces such as API credentials or remote-library selection.
3. Pick the common path that matches your use case
Codex plugin
Best if you want the richest Codex integration, not just raw MCP wiring.
zhl plugin install codex
zhl plugin update codex
zhl plugin update all
This installs the local Codex plugin bundle with:
- bundled Zotero skills
- bundled research and sync agents
- bundled MCP config
- a startup status hook
Claude Code
Use the Claude Code plugin bundle.
zhl plugin install claude-code
zhl plugin update claude-code
zhl plugin update all
This installs the repo-local Claude Code plugin bundle and refreshes its bundled .mcp.json from your local settings.
OpenClaw
Use OpenClaw's native plugin system plus the matching skill.
zhl plugin install openclaw
zhl plugin update openclaw
zhl plugin update all
zhl skill install openclaw
zhl plugin install openclaw runs the real OpenClaw plugin install and enable flow against ./plugins/openclaw-plugin-zotero.
zhl plugin update ... refreshes the installed plugin from the repo-local source bundle for the matching client. zhl plugin update all refreshes Codex, Claude Code, and OpenClaw in one pass.
The OpenClaw plugin source now builds through a package-manager-agnostic prepare lifecycle script, so linked installs work whether OpenClaw is configured to use npm, pnpm, or bun.
Codex or another client with plain MCP only
If you want raw MCP config without the full Codex plugin bundle:
zhl setup add codex --scope user
Other supported setup targets include cursor, claude-desktop, gemini, cline, antigravity, and windsurf.
Headless daemon on a server
If this machine is the runtime host:
zhl-daemon serve --host 0.0.0.0 --port 8787 --sync-interval 300
4. Smoke-test the install
zhl capabilities
zhl daemon status
zhl setup list
If you configured remote sync:
zhl raw sync discover
Most Common Workflows
Search the library
zhl qmd query "papers about retrieval augmented generation"
Use qmd-backed search for exploratory retrieval. Use exact MCP, API, or CLI reads for authoritative metadata.
Pull and push a remote library
zhl raw sync pull --library user:123456
zhl raw sync push --library user:123456
zhl raw sync conflicts --library user:123456
Always inspect conflicts before retrying a failed push.
Import from local Zotero Desktop
zhl local import
zhl local plan-apply --library local:1
zhl local apply --library local:1
Use plan-apply before any local writeback.
Create a safety snapshot
zhl recovery snapshot-create --reason "before bulk edits"
zhl recovery restore-plan --snapshot <snapshot_id> --library group:123
zhl recovery restore-execute --snapshot <snapshot_id> --library group:123 --confirm
Which Interface To Use
CLI
Use the CLI for:
- operator workflows
- shell scripts
- setup and diagnostics
- local administration
Human-facing commands live on the main surface such as setup, doctor, version, and daemon.
For strict machine-oriented automation, use:
zhl raw ...
HTTP API
Use the API for:
- app-to-app integration
- long-running services
- direct agent integrations without MCP
- runtime observability and job inspection
You can expose it with either:
zhl api serve --host 127.0.0.1 --port 8787
or:
zhl-daemon serve --host 127.0.0.1 --port 8787 --sync-interval 300
MCP
Use MCP when your client already speaks MCP and you want native tool use inside:
- Codex
- Claude Code
- Cursor
- Gemini
- Cline
- Windsurf
- similar agent tools
Start the stdio MCP server directly with:
zhl-mcp
Typical Setup Recipes
Desktop machine with Zotero installed and Codex as the client
uv tool install zotero-headless
zhl setup start
zhl plugin install codex
Useful next commands:
zhl local import
zhl qmd query "papers about transformers in NLP"
Standalone headless server
uv tool install zotero-headless
zhl setup start
zhl-daemon serve --host 0.0.0.0 --port 8787 --sync-interval 300
Useful next commands:
curl -s http://127.0.0.1:8787/capabilities
zhl raw sync discover
Claude Code on a project
uv tool install zotero-headless
zhl setup start
zhl plugin install claude-code
OpenClaw
uv tool install zotero-headless
zhl setup start
zhl plugin install openclaw
zhl skill install openclaw
Command Cheat Sheet
Status and diagnostics
zhl version
zhl update --check
zhl update
zhl doctor
zhl capabilities
zhl daemon status
zhl setup list
After a successful zhl update, zotero-headless automatically refreshes already-installed standalone skills and already-installed plugin targets using the packaged plugin bundles, with the current checkout used as an override when you are running from the repo.
Client setup
zhl plugin install codex
zhl plugin install claude-code
zhl plugin install openclaw
zhl plugin update codex
zhl plugin update claude-code
zhl plugin update openclaw
zhl plugin update all
zhl setup add codex --scope user
zhl skill install codex
zhl skill install openclaw
zhl skill export claude-desktop
zhl skill update all
Local desktop interoperability
zhl local libraries
zhl local import
zhl local poll
zhl local plan-apply --library local:1
zhl local apply --library local:1
Remote sync
zhl sync discover
zhl sync pull --library user:123456
zhl sync push --library user:123456
zhl sync conflicts --library user:123456
Recovery
zhl recovery repositories
zhl recovery snapshot-create --reason "before risky edit"
zhl recovery restore-plan --snapshot <snapshot_id> --library user:123456
zhl recovery restore-execute --snapshot <snapshot_id> --library user:123456 --confirm
Status
This project is still early-stage, but it already includes:
- a headless SQLite store and change log
- the
zotero-headlessCLI - the
zotero-headless-daemonruntime - the
zotero-headless-mcpstdio server - a local HTTP API
- Zotero web sync for user and group libraries
- local Zotero desktop import, polling, and narrow apply support
- remote attachment upload and download for the currently supported paths
- Better BibTeX-oriented citekey compatibility
- qmd export plus semantic search with automatic refresh
- MCP setup helpers and plugin installers for common agent tools
- runtime observability endpoints and background sync status
- recovery snapshots, restore planning, restore execution, and backup replication
Current compatibility baseline:
- Zotero
9.0(released April 10, 2026) is the newest tracked desktop/runtime baseline for local schema assumptions - Zotero 9 native citation-key fields are preserved on local reads and writes and attempted on remote writes with fallback behavior
- Zotero's browser-based account login does not replace the Web API key requirement for remote sync
Repository Layout
src/zotero_headless/: runtime, CLI, API, MCP, sync, and adapter codetests/: regression coverage across runtime and tooling surfacesdocs/: deeper guides and architecture notesplugins/: repo-local plugin bundles for supported agent clientsdesktop_helper/: metadata and patch workflow for the optional external Zotero desktop-helper path
Local-only workspace material should live in ignored directories such as:
.codex/.agents/.notes/.tmp/
Desktop Helper Workflow
This repository no longer vendors a Zotero source snapshot.
The current architecture is a clean-room headless runtime with adapters around Zotero Desktop and Zotero web sync. When contributors need the optional desktop-helper path, the repo keeps a small helper workflow under desktop_helper/ rather than an in-repo upstream mirror.
That workflow is intended to:
- pin an upstream Zotero commit or tag in
desktop_helper/metadata.json - keep helper deltas as explicit patch files under
desktop_helper/patches/ - build or validate against an external upstream checkout
Documentation
- docs/README.md
- USE_CASES.md
- CLI.md
- API_AND_MCP.md
- LOCAL_DESKTOP.md
- REMOTE_SYNC.md
- RECOVERY.md
- DESKTOP_HELPER.md
- ZOTERO_SOURCE_NOTES.md
- CONTRIBUTING.md
References
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 zotero_headless-1.1.6.tar.gz.
File metadata
- Download URL: zotero_headless-1.1.6.tar.gz
- Upload date:
- Size: 176.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b90863f5ec7ef76d1555f17c66fa5d8ecef170b1d5b84c8b9a842ff231c4a155
|
|
| MD5 |
e94dd6aae0ec62139aed54dfe718e35e
|
|
| BLAKE2b-256 |
14b03965e76840644db9efcfd04c722303ffa6e12e4115d5469082ac589d873f
|
Provenance
The following attestation bundles were made for zotero_headless-1.1.6.tar.gz:
Publisher:
publish.yml on robinradx/zotero-headless
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zotero_headless-1.1.6.tar.gz -
Subject digest:
b90863f5ec7ef76d1555f17c66fa5d8ecef170b1d5b84c8b9a842ff231c4a155 - Sigstore transparency entry: 1280229198
- Sigstore integration time:
-
Permalink:
robinradx/zotero-headless@bc64644a4aa7e046a3c196b73b90413e55bf788a -
Branch / Tag:
refs/tags/v1.1.6 - Owner: https://github.com/robinradx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bc64644a4aa7e046a3c196b73b90413e55bf788a -
Trigger Event:
push
-
Statement type:
File details
Details for the file zotero_headless-1.1.6-py3-none-any.whl.
File metadata
- Download URL: zotero_headless-1.1.6-py3-none-any.whl
- Upload date:
- Size: 175.8 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 |
eb43a407820d2224c1b545b3c547dc3f3ace81f5d82b2e650719a3c2228491ff
|
|
| MD5 |
8e64766a86194826afc3508dd15031ea
|
|
| BLAKE2b-256 |
9a92c51a8dbd51842f4f3e9ab54706a12d939abcf87d67c9464d2ae2f1e1b650
|
Provenance
The following attestation bundles were made for zotero_headless-1.1.6-py3-none-any.whl:
Publisher:
publish.yml on robinradx/zotero-headless
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zotero_headless-1.1.6-py3-none-any.whl -
Subject digest:
eb43a407820d2224c1b545b3c547dc3f3ace81f5d82b2e650719a3c2228491ff - Sigstore transparency entry: 1280229206
- Sigstore integration time:
-
Permalink:
robinradx/zotero-headless@bc64644a4aa7e046a3c196b73b90413e55bf788a -
Branch / Tag:
refs/tags/v1.1.6 - Owner: https://github.com/robinradx
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bc64644a4aa7e046a3c196b73b90413e55bf788a -
Trigger Event:
push
-
Statement type: