Activating the skill & daily workflow
Activating the research workflow skill
The skill is a markdown file that tells Claude Code how to behave during research sessions. One-time installation:
# Create the skills folder in your vault
mkdir -p ~/Documents/ResearchVault/.claude/skills
# Copy the skill file to the vault
cp SKILL.md ~/Documents/ResearchVault/.claude/skills/
Then add the following line to your CLAUDE.md (at the bottom):
## Active skills
- Read and follow `.claude/skills/SKILL.md` during every research session.
From that point on, the skill is active as soon as you open Claude Code in your vault. You can start the workflow by typing: /research or simply "start research workflow".
Daily workflow after installation
Once everything is set up, the daily workflow is straightforward. The feedreader runs automatically — no action required.
- Browse the filtered feed at
http://localhost:8765/filtered.html(or in NetNewsWire via the three type-specific Atom feeds). Items are sorted by relevance score. Send interesting ones to Zotero_inboxvia the Zotero browser extension or iOS app. Press 👎 on clearly off-topic items to give a negative signal to the learning loop. - Open Terminal in your vault:
cd ~/Documents/ResearchVault && claude - Activate the skill: type
/researchor "start research workflow" - Claude Code asks an intake question and guides you interactively from there
You do not need to know exactly what you are looking for — the skill is designed to help you with that.
Full session flow
-
Browse the filtered feed and forward interesting items to Zotero
_inbox -
Open Terminal, navigate to your vault, and start Claude Code:
cd ~/Documents/ResearchVault claude -
Activate the research workflow:
/researchor just type:
start research workflow -
Optionally, run
index-score.pyfirst to prioritize your review:~/.local/share/uv/tools/zotero-mcp-server/bin/python3 .claude/index-score.pyThis ranks all
_inboxitems by semantic similarity to your existing library (using the ChromaDB embeddings from zotero-mcp), so you know which items to focus on. -
Claude Code retrieves all items from your Zotero
_inboxand presents each one with a short summary and relevance assessment — the Phase-2 preview summary is generated locally bysummarize_item.py(fallback model qwen3.5:9b). You respond Go or No-go per item. -
For each Go: Claude Code builds a canonical bundle with
build-zotero-bundle.py(writingraw/{citekey}__{itemKey}.md), then runs the olw pipeline —olw ingest→olw compile(drafts land inwiki/.drafts/) →olw review. Theolw reviewstep is the human quality gate; approved pages are published towiki/. olw drives the local primary model (mistral-small:22b) viawiki.toml. -
For each No-go: Claude Code removes the item from
_inbox(after your confirmation). -
At the end of the session, Claude Code shows a summary: X approved, Y removed. The Zotero semantic search database is updated automatically each day as part of the login-triggered morning batch job (
nl.pietstam.nachtelijke-takendaemon) — no manual action needed before a session. If you process items later in the day and want the database to reflect them immediately, run:zotero-mcp update-db --fulltext # recommended (includes full text, 5–20 min on Apple Silicon)Or use the alias:
update-zotero. Check database status withzotero-mcp db-status.
Helper scripts
The workflow uses three helper scripts in .claude/. They keep source content out of Claude Code's context and handle Zotero write operations.
fetch-fulltext.py — retrieve and save attachment text
Fetches the full text of a Zotero attachment and saves it to a local file. Only prints status; never prints content.
~/.local/share/uv/tools/zotero-mcp-server/bin/python3 .claude/fetch-fulltext.py ITEMKEY inbox/bron.txt
# Output: Saved: inbox/bron.txt (12,345 chars, type: application/pdf)
For HTML snapshots the script extracts only the main article text via trafilatura (extract_article_text()), stripping navigation/ads/comments so full-page snapshots (e.g. Tweakers) don't bloat the bundle or slow olw ingest; it falls back to a naive tag-strip if trafilatura is unavailable or returns nothing. trafilatura must be installed in the zotero-mcp venv.
ollama-generate.py — generate text via local LLM (Ollama or MLX)
Calls a local LLM REST API directly (no CLI, no ANSI codes). Supports two backends:
- ollama (default): Ollama REST API on localhost:11434
- mlx: mlx_lm OpenAI-compatible server on localhost:8080
Backend is selected via --backend ollama|mlx or the LLM_BACKEND env var in ResearchVault/.env. Prepends /no_think to suppress the reasoning step. Prints only status lines.
~/.local/share/uv/tools/zotero-mcp-server/bin/python3 .claude/ollama-generate.py \
--input inbox/bron.txt \
--output raw/notitie.md \
--prompt "Summarise this source in Dutch..." \
[--backend ollama|mlx]
# Output: Input: inbox/bron.txt (12,345 chars) | Model: mistral-small:22b | backend: ollama | Written: raw/notitie.md (3,200 chars)
zotero-remove-from-inbox.py — remove processed item from _inbox
Removes the item from the _inbox collection in Zotero. Uses the local Zotero API by default (requires Zotero desktop running); mode is controlled by ZOTERO_ACCESS (see zotero_api.py).
~/.local/share/uv/tools/zotero-mcp-server/bin/python3 .claude/zotero-remove-from-inbox.py ITEMKEY
# Output: Item ITEMKEY removed from _inbox.