Skip to content

markdaly/omnivore-rescue

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

omnivore-rescue

When Omnivore shut down in 2024 I had a year's worth of saved articles and highlights sitting in an export archive with nowhere to go. This script moves them into Zotero — an open-source reference manager that stores attachments locally, syncs across devices, and handles both PDFs and web articles well. The highlights were the whole point, so the script embeds them as PDF annotations and as a child note on every item, giving you two ways to find them later.

This was also my first experiment building a real tool through vibe coding with Claude. The spec lives in CLAUDE.md; the script was written entirely through that conversation. It worked on the first real run.


Migrate a personal Omnivore export archive into Zotero.

Each article that has highlights gets imported as a Zotero item with:

  • Full metadata (title, author, URL, tags, dates)
  • The original PDF or HTML as a stored attachment
  • Highlights embedded as yellow PDF annotations (PDFs, best-effort text search)
  • Highlights as a Zotero child note (always — the reliable fallback and search layer)

Articles with no highlights are skipped entirely.


Prerequisites

  • Python 3.10+
  • A Zotero account with a personal library
  • Your Omnivore export zip (obtained from Omnivore's settings before shutdown)

Install dependencies:

pip install -r requirements.txt

Zotero credentials

You need two values from your Zotero account:

  1. Go to zotero.org/settings/keys
  2. Note your numeric user ID shown at the top of that page
  3. Click Create new private key
    • Give it a name (e.g. omnivore-rescue)
    • Allow library access: Read/Write
    • Save and copy the key

Copy .env.example to .env and fill in both values:

cp .env.example .env

.env is gitignored — it will never be committed.


Usage

python migrate.py \
  --zip /path/to/omnivore-export.zip \
  --user-id YOUR_ZOTERO_USER_ID \
  --api-key YOUR_ZOTERO_API_KEY \
  --collection "Omnivore Archive"

Or with credentials in .env (loaded automatically):

python migrate.py --zip /path/to/omnivore-export.zip --collection "Omnivore Archive"

Options

Flag Description
--zip Path to the Omnivore export zip file
--user-id Zotero numeric user ID (or set ZOTERO_USER_ID in .env)
--api-key Zotero API key (or set ZOTERO_API_KEY in .env)
--collection Zotero collection name to import into (created if absent)
--dry-run Validate and parse everything, make no API calls
--limit N Process only the first N highlighted articles (useful for testing)

Dry run first

python migrate.py --zip /path/to/omnivore-export.zip --dry-run

This parses the full archive, reports how many articles have highlights, and validates content without touching Zotero. Good sanity check before the real run.


Resumability

The script writes migrate.log with one line per document (slug, status, Zotero item key). On re-run it checks Zotero for existing items by URL and skips anything already imported. Safe to interrupt and resume.


What gets skipped

  • Articles with no highlights file, an empty highlights file, or no > quote lines
  • That's it — everything else gets imported regardless of reading progress

AI disclosure

This project was built with Claude (Anthropic). The migration spec, architecture decisions, and testing were mine; Claude wrote the code. Commits carry Co-Authored-By: Claude Sonnet 4.6 attribution. Licensed MIT — Anthropic's terms assign output ownership to the user, and the usual caveats about AI-generated code apply: read it before you run it.


Output

Total articles in export:           137
  With highlights:                   XX
  Skipped (no highlights):           XX

Zotero items created:               XX
  PDFs - full annotation:            XX
  PDFs - partial annotation:         XX
  PDFs - no annotation (scanned):    XX
  HTML articles:                     XX
  Missing content file:              XX

Child notes created:                XX
Highlights total:                  XXX
  Matched to PDF text:             XXX
  Fell back to sticky note:         XX

Errors:                              X  (see migrate.log)

About

export from omnivore archive into zotero

Resources

License

Stars

Watchers

Forks

Contributors

Languages