Fill the missing PDFs in your Zotero library — and keep it that way
Docs: Get started · Commands · MCP tools · How it works · User guide
Finding a paper is easy; getting its PDF, legitimately is the tedious
part. papio backfills the works in your library that lack full
text, checking open-access and licensed sources first and falling back to a
visible institutional pass in your own browser only when needed. Watch a
collection and new matches arrive with verified full text; or hand the loop
to a research agent over MCP — without handing it your university
credentials. Every PDF is validated before it reaches Zotero through
zotio's
preview-and-confirmation boundary.
brew install orgmentem/tap/papio # or grab a signed binary from Releases
papio init # guided setup: config, data folder, database, browser connector, health check
papio doctor # checks the whole chain, including the browser extension and zotio
papio search "appropriate reliance on AI" --limit 20 --year-from 2023
papio acquire 10.1371/journal.pone.0262026 --auto-import --wait
papio status --follow # working / awaiting-human / needs-review / ready / failed
papio actions list # open browser handoffs and identity reviewsDiscovery is a solved problem — getting the PDF is not. The gap between "found it on OpenAlex" and "validated PDF in my library" is a swamp of publisher landing pages, single sign-on redirects, dubious downloads, and hand-filed imports. Existing tools either stop at metadata or cross lines you don't want crossed.
papio owns exactly that glue, with hard boundaries:
- Legitimate by construction. Open-access and explicitly licensed APIs run
before institutional access. Institutional fetches happen as an OpenURL
handoff in your ordinary Chrome or Firefox session — login, MFA, and
CAPTCHAs stay human decisions.
papionever stores institution credentials and never does subscription crawling. - Repeatable jobs. Every request becomes a job with a stable ID — running it again is safe and won't duplicate, batches are capped, and budgets and allowed/blocked sources are enforced by papio, not by hope.
- Validated before trusted. Every candidate PDF is quarantined and gated on
structure, identity, and an OCR fallback. Ambiguous identity parks in
needs_reviewfor a human verdict instead of silently importing the wrong paper. - Zotero writes only through zotio.
papio zotio planproduces an immutable preview;papio zotio applyrequires that preview's exact confirmation SHA-256.papionever touches Zotero credentials.
Each acquisition is a job. papio ranks the possible sources by a fixed
set of rules and tries them in order — it never accepts the first URL
it finds:
| Stage | Source / tooling | Handles credentials? |
|---|---|---|
| Discovery | OpenAlex (read-only) | No |
| Download — open | arXiv · Europe PMC · Unpaywall · OpenAlex · CORE · Crossref TDM | No (API keys only where configured) |
| Download — institutional | OpenURL handoff in your ordinary browser session | No — login/2FA/CAPTCHA stay human |
| Validation | Local PDF structure + identity + OCR (Poppler, Tesseract) | No |
| Zotero writes | zotio — preview (plan) then confirmed apply |
No — papio never stores Zotero credentials |
papio runs in one of three access modes — conservative, assisted, or
delegated. A fresh papio init chooses conservative; institutional handoff
opens a browser only under assisted/delegated, and even then automation stays
inside legitimate, user-authorized access
(access modes & safety).
Discover, acquire in bulk, watch progress, review the exceptions — then let the finished PDFs flow into Zotero:
# 1. Discover — read-only; marks works already in your zotio library
papio search "trust in AI advice" --limit 20 --year-from 2022
papio search --cites 10.1002/mar.21498 # citation snowball: who cites this paper?
# 2. Acquire — one work or a capped batch of jobs
papio acquire 10.1016/j.chb.2020.106607 --auto-import --wait
papio acquire arXiv:2401.00001 --desired-version published
# 3. Observe — jobs settle as ready, awaiting-human, needs-review, or failed
papio status --follow
papio jobs list
# 4. Act on the exceptions
papio actions list # open browser passes and identity reviews
papio doctor # whole-chain readiness when something looks off
# 5. Standing discovery — a watchlist that runs the same pipeline on a cadence
papio watch add "appropriate reliance on AI" --cadence weeklyA browser handoff is a normal job state, not a failure: the job parks as
awaiting_human, papio actions list names it, and one sign-in pass in your
own browser lets the extension finish the download — validated, filed, and
imported like any other PDF
(browser handoff).
No PDF is trusted because a server returned 200 OK. Every candidate is
quarantined and must pass three gates before it becomes a trusted PDF
(validation & provenance):
- Structure — it is a real, parseable PDF, not an HTML error page with a
.pdfname. - Identity — the document's own metadata and text match the requested work;
ambiguity parks the job in
needs_reviewwith the quarantine path exposed for human inspection (papio actions list→ accept/reject). - Text — an OCR fallback (Tesseract) makes the PDF searchable before import.
What survives is a permanent acquisition bundle:
the validated PDF plus a record of where it came from, how it was
fetched, and every check it passed — exportable with papio bundle, inspectable
with papio artifacts.
papio acquires; zotio imports. The
handoff is explicit and verifiable:
papio zotio plan <job-id> # preview of the exact changes + a confirmation code
papio zotio apply <plan-id> --confirm-sha256 <sha256> # applies exactly that preview; safe to repeat--auto-import on acquire routes through the same plan/apply machinery.
Without zotio installed, papio still works — it stops at validated bundles
you can import however you like.
papio is designed to be driven by a coding agent as naturally as by a human
(MCP agent guide):
--jsonon any command for structured output.papio mcpserves an MCP server with the same configuration, background service, jobs, and zotio boundary as the CLI.- A command facade derived from the CLI, so agents reach the whole tool
surface through two tools without a parallel layer that can drift:
papio_command_searchto discover commands andpapio_command_runto execute one (JSON output). SetPAPIO_MCP_SURFACE=mirrorto expose onepapio_<command>tool apiece instead (full reference). - Two composite tools with no single-command equivalent —
papio_acquire_batch(bulk work input) andpapio_batch_wait(polls until settled or timeout). - Read resources —
papio://jobs,papio://artifacts,papio://bundles,papio://zotio/plans,papio://exports— expose recent saved state without creating jobs or mutating anything. - One writer.
papio_command_runwithzotio applyis the only path that writes to Zotero, and it demands the exact confirmation SHA-256 fromzotio plan.
Register it in an MCP host:
# Claude Code
claude mcp add papio -- papio mcpHomebrew (macOS):
brew install orgmentem/tap/papioLinux (deb / rpm / apk): download the package for your distro from the
GitHub releases and install it
with dpkg -i, rpm -i, or apk add --allow-untrusted.
Scoop (Windows):
scoop bucket add orgmentem https://github.com/OrgMentem/scoop-bucket
scoop install papioPrebuilt binaries: every GitHub release
ships archives for macOS, Linux, and Windows (amd64/arm64) with cosign-signed
checksums and SBOMs. Unpack and put papio on your PATH; on macOS clear the
Gatekeeper quarantine (xattr -d com.apple.quarantine papio).
From source:
git clone https://github.com/OrgMentem/papio && cd papio && go build ./cmd/papio- Poppler and Tesseract for PDF validation and the OCR text gate:
brew install poppler tesseract(or disable OCR in the config). - Chrome or Firefox with the papio extension for human-authenticated
institutional access — Chrome installs it from the
Chrome Web Store;
Firefox loads the built
extension/firefox/viaabout:debugginguntil the AMO listing clears review.papio initprints the exact steps; skip withpapio init --skip-browserfor OA-only headless use. - zotio on
PATH(or[zotio] executablein the config) for Zotero import; optional — without it papio stops at validated bundles.
Then let the CLI walk you through setup — config, data directory, database, native-messaging host, and a first health check:
papio init
papio doctorpapio doctor # sources, PDF tools, background service, extension, connector, zotio- Extension shows disconnected — reload it in the browser after upgrades;
papio doctorreports version mismatches between the background service and extension. - Job stuck in
awaiting_human—papio actions listnames the browser pass or identity review it is waiting for. - zotio errors — the boundary reports stable error classes; see the troubleshooting guide.
Config file: ~/.config/papio/config.toml — on Windows %APPDATA%\papio\config.toml
(override with --config). Access
modes, resolver profiles, source allow/deny lists, budgets, OCR, and the zotio
executable are all configured there — every key, default, constraint, and
effect is in the
configuration reference.
Run papio --help for the full command list, or papio <command> --help for
any subcommand.
Top-level commands
acquire · actions · artifacts · batch · bundle · config · daemon
· doctor · init · jobs · mcp · native-host · search · status ·
version · watch · zotio
papio acquires validated, provenance-tracked PDFs. zotio is the trust-and-automation layer for Zotero that imports them preview-first — and audits, heals, and certifies the library they land in. If papio fills the gaps in your library, zotio makes sure the library stays fit to cite.
papio also works without zotio, stopping at validated bundles.
Licensed under MIT.
Zotero is a registered trademark of the Corporation for Digital Scholarship. papio is an independent project and is not affiliated with or endorsed by Zotero or the Corporation for Digital Scholarship.