Setup zotero references
Skill benjibromberg/zotero-context/skills/setup-zotero-references
Project-scoped Zotero references for Claude Code — auto-triggering skill, vendored scripts, no MCP server. For surfacing curated literature while you code.
npx -y skills add benjibromberg/zotero-context --skill setup-zotero-referencesAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Use when the user wants to configure Zotero references for the current project, when they say "set up zotero", "configure zotero references", "/zotero-context:setup-zotero-references", or when starting a new project that should reference a Zotero library
SKILL.md
9.3 KB, as published. Nobody here has run it
Setup Zotero References
Overview
One-time bootstrap: ensures uv is available, lists the user's Zotero libraries, prompts which to scope to this project, samples each chosen library, derives trigger keywords + a one-line description per library, vendors the search scripts into the repo, and renders the deployed using-zotero-references skill with the project-specific keywords.
After this skill runs, future Claude sessions in this repo will auto-trigger using-zotero-references for project-relevant topics and call .zotero-context/bin/search_items.py for reference lookups. Each vendored script is a PEP 723 self-contained inline-metadata script — uv reads its dependency declaration and provisions an isolated environment on first invocation. The user does NOT need to install pyzotero globally.
When to Use
- User says "set up zotero", "configure zotero references", "/zotero-context:setup-zotero-references"
- User asks how to make a Zotero library available to Claude in this project
- User wants to scope new libraries to an existing
.zotero-context/config
Workflow
Run these steps sequentially. Stop after each user prompt and wait for input.
Step 0: Check for uv
The vendored scripts use uv to manage their Python dependencies (no global pip install required). Detect it:
command -v uv
If uv is found, proceed to Step 1.
If uv is not found, ask the user:
The vendored Zotero scripts use
uv(from Astral) to manage Python dependencies, so we don't have to installpyzoteroglobally. The official one-line installer is:curl -LsSf https://astral.sh/uv/install.sh | shThis is the install method recommended by the
uvdocs and matches the pattern used byrustup,nvm,bun, andhomebrew. Install it now? [y/N]
If the user confirms, run:
curl -LsSf https://astral.sh/uv/install.sh | sh
Then verify:
uv --version
If uv is still not on $PATH, point the user at the installer's output (it usually prints a source $HOME/.local/bin/env line) and ask them to restart their shell or source that file before re-running this skill.
If the user declines, stop here — the plugin requires uv to run the vendored scripts.
Step 1: Connectivity check
curl -s -o /dev/null -w "%{http_code}" http://localhost:23119/api/users/0/groups
- If
200: local API works. Proceed. - Else: check
.envforZOTERO_API_KEY. If absent, print:Zotero is not reachable. Either start Zotero desktop (preferences → advanced → "Allow other applications") or add
ZOTERO_API_KEY=...to.env. Re-run when ready. Then stop.
Step 2: List libraries
${CLAUDE_SKILL_DIR}/../../scripts/list_libraries.py
(${CLAUDE_SKILL_DIR} is the absolute path of this skill's directory, provided by Claude Code. The plugin root is two levels up.) The script's #!/usr/bin/env -S uv run --script shebang causes uv to provision a one-shot venv on first invocation (cached for subsequent runs).
Display the JSON to the user as a numbered list:
1. Personal — 73 items (user/12345)
2. Benji's Cell Ag Library — 187 items (group/5178481)
3. Methods Reading — 42 items (group/9999)
Step 3: Library selection
Ask the user which libraries to scope to this project (multi-select by number, comma-separated). Save the chosen IDs and types.
Note: If the user picks the personal library and
ZOTERO_API_KEYis not yet set, the storedlibrary_idwill be0(a local-only convention). This breaks web-API fallback when Zotero desktop is closed. Remind the user that addingZOTERO_API_KEYto.envbefore or after setup letslist_libraries.pyresolve a portable numeric user ID that works with both APIs.
Step 4: Sample fetch + keyword analysis
For each chosen library:
${CLAUDE_SKILL_DIR}/../../scripts/sample_library.py --lib <ID> --type {user|group} --limit 30
(sample_library.py bypasses config loading, so it is safe to call before Step 5 writes config.json.)
Read the sample output. You (the running Claude session) propose:
- 8–15 domain keywords representing the library's topical focus (no generic terms like "research", "paper").
- A 1–2 sentence description of the library suitable for CLAUDE.md.
Show your proposal to the user:
For library "Benji's Cell Ag Library":
Description: Curated cellular agriculture literature spanning precision fermentation, scaffold biomaterials, and cultivated meat process development.
Trigger keywords:
- cellular agriculture
- precision fermentation
- ...
Wait for user edits/approval before proceeding.
Step 5: Write .zotero-context/config.json
Combine all libraries' descriptions and union all keywords into one project-level list (deduped).
{
"version": 1,
"libraries": [
{"id": 5178481, "type": "group", "name": "Benji's Cell Ag Library", "description": "..."},
...
],
"trigger_keywords": ["cellular agriculture", "precision fermentation", ...],
"defaults": {
"include_notes": true,
"include_annotations": true,
"output": "full"
}
}
Step 6: Vendor scripts
mkdir -p .zotero-context/bin
cp ${CLAUDE_SKILL_DIR}/../../scripts/{common,zotero_client,list_libraries,search_items,get_item,enrich_abstract,sample_library}.py .zotero-context/bin/
chmod +x .zotero-context/bin/{list_libraries,search_items,get_item,enrich_abstract,sample_library}.py
The five entry-point scripts are made executable so the deployed skill can invoke them directly via shebang. common.py and zotero_client.py are imported as modules by the others and don't need to be executable.
Step 7: Render the deployed skill
Read ${CLAUDE_SKILL_DIR}/../../templates/using-zotero-references/SKILL.md.template. Substitute:
{{KEYWORDS}}→ comma-joinedtrigger_keywordsfrom config.{{LIBRARY_DESCRIPTIONS}}→ bullet list, one per library:- {name}: {description}.
Write the result to .claude/skills/using-zotero-references/SKILL.md.
Step 8: Gitignore
- Always: ensure
.envis in.gitignore. If absent, add it. - Prompt: "Should
.zotero-context/be gitignored? Default is no — committing it makes the repo self-contained for collaborators and future worktrees. (y/N)" - If yes, add
.zotero-context/to.gitignore.
Step 9: CLAUDE.md update
Append (or update an existing managed block):
<!-- BEGIN zotero-context -->
## Zotero References
This project uses the `using-zotero-references` skill to look up curated literature in:
- {library 1 name}: {description}
- {library 2 name}: {description}
The skill auto-triggers on project-relevant topics and calls `.zotero-context/bin/search_items.py` (a self-contained `uv run --script` shebang). Run `/zotero-context:enrich-zotero-abstracts` to fix items with missing abstracts.
<!-- END zotero-context -->
If the block already exists, replace it; otherwise append at the end of CLAUDE.md (or AGENTS.md if CLAUDE.md doesn't exist).
Step 10: Smoke test
.zotero-context/bin/search_items.py --query "<first trigger keyword>" --limit 2
The first invocation triggers uv to install pyzotero into a script-scoped cache (~5MB, one-time). Show the user the JSON output and confirm setup is working.
Idempotency
When .zotero-context/config.json already exists, offer:
- Add libraries — re-list, multi-select additions, re-derive keywords for new ones, merge into config.
- Refresh keywords — re-sample chosen libraries, re-propose, replace
trigger_keywordsand re-render the deployed skill. - Re-vendor scripts — copy latest plugin scripts to
.zotero-context/bin/(use this after the plugin updates).
Never silently overwrite — confirm action with user.
Common Mistakes
- Skipping Step 0 (uv check) — vendored scripts will fail with
env: 'uv': No such file or directoryifuvisn't on$PATH. - Skipping Step 4 and using library names as keywords. Library names are vague; sample-derived keywords trigger more reliably.
- Hand-editing
.claude/skills/using-zotero-references/SKILL.mdand losing the changes on next setup re-run. Edit the template instead, then re-render. - Forgetting Step 6 (vendoring) — the deployed skill expects scripts at
.zotero-context/bin/. - Forgetting Step 6's
chmod +x— without the executable bit the shebang doesn't fire and Claude gets a "Permission denied" error.