Skip to content

Safe-by-default writes

Every write command — items enrich, tags audit fix, items duplicates resolve, items create/update/move/delete, import apply, vault push — flows through one mutation envelope with identical, predictable semantics. You never have to remember which command is dangerous; they all behave the same way.

zotio write-safety lifecycle Preview-first write command lifecycle with gates, explicit apply, Web API write, local mirror replay, append-only journal, and reversible undo. Safe by default: preview, gate, apply, journal, undo Every zotio write command starts as a reviewable plan; nothing mutates until explicit consent passes safety gates. preview / local gates apply / Web API journal / undo 1. COMMAND tags audit fix items enrich --missing-doi 2. PLAN (preview) plan / result envelope default: preview only NO changes yet 3. GATES --max-changes 500 (50 under --agent) --allow-destructive irreversible ops --require-fresh fresh mirror REFUSE loud failed gate = no write 4. Decision --yes provided? No: STOP preview is the final output no yes 5. APPLY explicit mutation applies the change --agent does NOT auto-apply --dry-run always wins WRITE to Zotero Web API update / delete / enrich / tags with configured api_key REPLAY to local mirror read-your-writes fresh re-audit without sync 6. RECORD append-only JOURNAL journal list journal show journal undo <run-id> UNDO reverses tag rename collection membership REFUSES rest merges, deletes field overwrites loud, not silent Hook: safe by default — preview, gate, apply, journal, undo.

The contract

  • Preview is the default. You get a plan/result envelope with zero changes. --yes applies; --dry-run always wins.
  • --agent does not auto-apply. Agent mode sets JSON + non-interactive defaults, but a write still needs an explicit --yes.
  • Gates cap the blast radius. --max-changes defaults to 500 (50 under --agent); irreversible ops (merge, permanent delete, empty-trash) refuse to run without --allow-destructive.
  • Read-your-writes. An applied write is replayed into the local mirror immediately, and the post-write item state comes back in the envelope — a re-audit sees the fix with no follow-up sync.
  • Journaled + reversible. Every applied run is recorded append-only (journal list / journal show). journal undo <run-id> reverses the reversible ops (tag renames, collection membership) and loudly refuses the rest (merges, deletions, field overwrites) rather than guessing.

Where writes land

Writes split by intent — new items prefer the keyless local desktop connector; everything else routes to the Zotero Web API and needs a key.

zotio hybrid routing architecture Hero diagram showing zotio routing reads locally without an API key, writes to Zotero Web API with a key, external metadata providers, local-only desktop commands, local version reads before writes, and replay into the SQLite mirror. zotio hybrid routing Local-fast reads, key-gated cloud writes, and an immediately refreshed local mirror. READ WRITE EXTERNAL LOCAL-only Semantic colors are shared across README diagrams. READ plane Local-first Local Zotero API :23119 Zotero desktop running items list/get collections annotations fulltext Local SQLite mirror Synced cache for compound reads search items audit stats Desktop connector New-item create path create items · attachments · PDFs prefers local · else Web API local reads/creates need no key · cloud writes do CLOUD write path Zotero Web API api.zotero.org Auto-routed mutation target items update/delete/move enrich · tags audit fix collections create/update vault push · journal undo LOCAL-only plane Files · desktop · introspection vault sync items open doctor capabilities EXTERNAL plane Metadata providers CrossRef · OpenAlex Semantic Scholar Unpaywall · OpenCitations zotio routing + safety layer one CLI surface reads new items writes replay → mirror enrich · import local ops

The capabilities reference lists the operation, write target, destructiveness, and requirements for every command. See Authentication for key setup.

Example

zotio tags audit fix --agent            # preview: the merge plan, zero changes
zotio tags audit fix --agent --yes      # apply
zotio journal list                      # find the run id
zotio journal undo <run-id>             # reverse the tag renames