Install
$ agentstack add skill-benjibromberg-zotero-context-setup-zotero-references Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.
Security review
⚠ Flagged1 finding(s); flagged for manual review. · v0.1.0 How review works →
- • Prompt-injection patterns
- • Secret / credential exfiltration
- • Dangerous shell & filesystem operations
- • Untrusted network calls
- • Known-malicious package signatures
- high Pipes remote content directly into a shell (remote code execution).
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
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 install pyzotero globally. The official one-line installer is: > > ``bash > curl -LsSf https://astral.sh/uv/install.sh | sh > ` > > This is the install method recommended by the uv docs and matches the pattern used by rustup, nvm, bun, and homebrew`. 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_KEY is not yet set, the stored library_id will be 0 (a local-only convention). This breaks web-API fallback when Zotero desktop is closed. Remind the user that adding ZOTERO_API_KEY to .env before or after setup lets list_libraries.py resolve 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 --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):
## 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.
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 "" --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.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: benjibromberg
- Source: benjibromberg/zotero-context
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.