This handbook covers the earlier research demos (previously 10–13) — the synthetic Obsidian vault, the Zotero bibliography, the join between them, and the funding radar. They all still work and nothing here has moved.
The new demo 10 is a different, narrower package: papers, citations and a Word document with live Zotero fields, built on your library rather than a synthetic one. It carries its own setup guide and does not need this handbook. Paper writing with Zotero →
Contents
- What the four parts are
- Prerequisites, and how to check them
- Where to put everything
- The files that matter
- How information moves
- First run, step by step
- Daily: a paper arrives
- Weekly: the two routines
- Monthly: drift and decisions
- Adding each kind of new data
- What goes wrong over time
- Troubleshooting
1. What the four parts are
Four packages. They were built to be run in order and they share one body of literature on purpose, so each can teach its own lesson instead of re-explaining the papers.
| Demo | The thing | The question it answers |
|---|---|---|
| 10 | An Obsidian vault | Are the notes right? Documents arrive, notes get written. What stops a note from being wrong? |
| 11 | A Zotero library | Can you cite what you have? Three views of one library that disagree in five places. |
| 12 | Both, side by side | Do they still agree? The join between them, and what ten months of ordinary use does to it. |
| 13 | A funding radar | Is this worth an afternoon? An agent layer over a pipeline you already run. |
You can run any one on its own. If you only do one, do Demo 10 — it is the foundation and the other three assume its vocabulary.
The single idea underneath all four
Three ways to control what an agent does, in increasing order of force. Every demo is an application of this and nothing else:
| Mechanism | Where it lives | How strong |
|---|---|---|
| Context | CLAUDE.md |
A request. Usually obeyed. Nothing enforces it. Good for conventions, judgement, taste. |
| Permission | .claude/settings.json |
A refusal. Checked before the tool runs, client-side. The agent cannot argue with it. |
| Capability | a subagent’s tools: list |
Absence. The tool is not there. Nothing to refuse, nothing to work around. |
When something in your own setup goes wrong, the useful question is always which of these three should have caught it? — and the answer is usually the one you did not write.
2. Prerequisites, and how to check them
Run all four checks before unzipping anything. Each one tells you what a pass looks like and what to do about a fail.
Claude Code
claude --version
2.1.x.command not found → you have not finished Week 3 setup. Field Guide Part 8, slides 62–65, or the Setup section on this site.pdftotext — needed by all four
pdftotext -v
pdftotext version 24.x (it prints to stderr, which is normal).brew install poppler · Ubuntu/Debian sudo apt install poppler-utils · Windows: install inside WSL.
Demo 10 survives without it — Claude Code reads short PDFs natively, up to 20 pages per call. Demos 11–13 will be slow and expensive without it, because they search inside documents repeatedly.
git — this is not optional
git --version
You will git init inside every one of these folders before letting
an agent near them. It is the single most useful line in all four packages and
it costs nothing.
Python 3 — Demo 13 only
python3 --version
Obsidian and Zotero — both optional
Neither is required for any demo. This surprises people, so it is worth being blunt about:
- An Obsidian vault is a folder of Markdown files. Obsidian is a viewer for that folder. Install it to see property tables, backlinks and the graph; skip it and every demo still works.
- A Zotero library on disk is a
.bibexport, a.csvexport and astorage/folder of PDFs. Demos 11–13 ship exactly that, so you need no Zotero account, no API key and no plugin.
Install them when you want to use this on your own material. For the demos, they are scenery.
3. Where to put everything
Make one parent folder and unzip all four inside it. Keeping them together matters for Demo 12, which uses a library and a vault side by side.
mkdir -p ~/research-system
cd ~/research-system
unzip ~/Downloads/Demo10_obsidian_research_vault.zip
unzip ~/Downloads/Demo11_zotero_bibliography.zip
unzip ~/Downloads/Demo12_zotero_obsidian_claude.zip
unzip ~/Downloads/Demo13_funding_radar.zip
ls
Demo10_obsidian_research_vault
Demo11_zotero_bibliography
Demo12_zotero_obsidian_claude
Demo13_funding_radarEach package has the same shape, which is worth learning once:
ANSWER_KEY.md last. It lists
every planted defect. Reading it first turns the exercise into a reading
comprehension test, which is not the point.4. The files that matter
Each package has 25–45 files. Six of them do the work. Everything else is material for the agent to chew on.
Throughout, these labels mean:
YOU EDIT yours to change, and the point of the exercise is changing it GENERATED written by a script or an agent; safe to delete and remake NEVER TOUCH the system of record; a deny rule stops the agent and should stop you too
The six that matter, in every package
| File | What it actually does | |
|---|---|---|
CLAUDE.md | YOU EDIT | Loaded into context automatically every time you run claude in that folder. It is how you say "notes go in papers/", "read past the abstract", "never state a number that is not in the source". It is a request, not a rule — the agent usually obeys and sometimes does not, and noticing when it does not is half of what these demos teach. |
.claude/settings.json | YOU EDIT | The deny list. Checked before a tool runs, so no amount of prompting gets around it. This is what protects .obsidian/, your Zotero library, your own synthesis notes, and a pipeline database. Deny beats ask beats allow; first match wins; an allow cannot carve an exception out of a deny. |
.claude/agents/*.md | YOU EDIT | Subagents. Frontmatter sets name, description (which is what decides when it gets used), tools (an allowlist — omit it and the agent inherits everything), and model. The prose below the frontmatter is its brief. |
_templates/*.md | YOU EDIT | The shape of the output. Changing a template changes every note written afterwards, which is the cheapest lever in the whole system. |
inbox/ | YOU EDIT | Where new material lands. This is the folder you will actually use day to day. Drop a PDF in, run a prompt. |
| the system of record | NEVER TOUCH | pdfs/, zotero/, pipeline/radar.db, .obsidian/. Different in each demo; always denied; always for the same reason — a record an agent can edit is no longer a record. |
Demo 10 — the vault, annotated
The one to understand: topics/ is denied to every
agent, and proposals/ exists because of that. The agent can tell you
your synthesis note is out of date and hand you the exact replacement lines; it
cannot apply them. That is deliberate — a synthesis note you accepted is
yours, and one that appeared while you were not looking is not.
Demo 11 — the library, annotated
The one to understand: the three views — the .bib,
the .csv and storage/ — disagree in five places, and the
Key column of the CSV is the only stable identifier. Cite keys are
regenerated whenever you fix metadata; titles get retyped; filenames carry
years that turn out to be wrong.
Demo 12 — the join, annotated
The one to understand: a single frontmatter field,
zotero_key, is the entire integration. Two of the seven notes have
one that resolves. The other five show the five ways ten months of ordinary use
breaks the link.
Demo 13 — the radar, annotated
The one to understand: profile/research_profile.md
has two halves, and the second one — uncommitted FTE, indirect rate, smallest
viable project, cost-share appetite, down-select timing — is what decides.
Four of the five traps in that demo are caught by that table alone.
5. How information moves
Every one of these systems is the same three-stage shape. Learn it once:
SYSTEM OF RECORD → YOUR NOTES → THE DELIVERABLE
what exists what you decided what you send
pdfs/ zotero/ radar.db papers/ topics/ bib/ memos/
───────────────────── ─────────────── ───────────────
NEVER written by an agent agent writes; agent writes
deny rules enforce it you own topics/ freely
Three rules hold it together, and they are the same three in all four demos:
- Information flows left to right, never right to left. Notes never write back into the library. The vault never edits the database. If you want the record changed, you change it in the tool that owns it — Zotero, your scraper — by hand.
- Regeneration must be safe. Anything marked GENERATED can be deleted and rebuilt. The corollary is the thing to watch for in your own setups: any generator that touches a file you also write into must preserve your part verbatim. Demo 13's exporter does this, and an earlier version of it silently destroyed decision blocks on every run until a verification pass caught it.
- The verifier cannot write.
skeptic,citecheck,driftandrecurrenceall ship with noWritetool. A verifier that can edit is a verifier you cannot trust, because it can make its own findings disappear.
6. First run, step by step
Demo 10, from a clean unzip. The same pattern applies to the other three; only the prompts differ.
Step 1 — get into the working directory
cd ~/research-system/Demo10_obsidian_research_vault/vault
ls
CLAUDE.md _templates inbox papers pdfs proposals topics wave2 web
If you see README.md and SETUP.md instead, you are one level too high. cd vault.
CLAUDE.md and .claude/ are picked up from the directory you launch claude in. Start one level up and the agent runs with no contract and no deny list — it will happily do the thing the demo is about preventing.Step 2 — make the undo button
git init
git add -A
git commit -m "before the agent"
35 files changed, ... insertions(+)From here on, git diff reviews everything the agent did and
git checkout . undoes all of it. Do this in your own vault
before you point an agent at five years of notes. It is worth more than
every configuration file in these packages combined.
Step 3 — read the contract before running anything
cat CLAUDE.md
cat .claude/settings.json
ls .claude/agents/
librarian.md, skeptic.md, curator.md.Two minutes here saves twenty later. You are looking for: where notes go, what the agent is forbidden to touch, and which agent has which tools.
Step 4 — look at the raw material
ls -la inbox/
1-s2.0-S0022283624001147-main.pdf, scan0043.pdf,
mps-12-44.pdf, three .md clips, a .csv and a .docx.Check the scan behaves as advertised before you start:
pdftotext inbox/scan0043.pdf - | wc -c
0 or 1. That file has no text layer — it is a photocopy. How the agent handles that is one of the things being tested.Step 5 — start Claude Code
claude
/status if you want to confirm which project it thinks it is in.Then work through the nine prompts in SETUP.md, one at a time,
reading the output before pasting the next one. The demo does
not work as a batch — most of the findings are in what the agent says between
steps.
Step 6 — check what actually changed
git diff --stat
git status --short topics/
papers/, web/ and proposals/. topics/ empty.topics/ shows changes, the deny rule is not working — check you launched claude from inside vault/ and that .claude/settings.json is valid JSON (python3 -m json.tool .claude/settings.json).7. Daily: a paper arrives
This is the loop you will actually run, and it takes about two minutes once the folders exist.
The 30-second version
cd ~/research-system/Demo10_obsidian_research_vault/vault
cp ~/Downloads/whatever-i-just-downloaded.pdf inbox/
claude
then:
File everything in inbox/.
That is it. The contract in CLAUDE.md carries the conventions, so
you do not re-explain them. Then, when you have a minute:
Use the curator subagent on the note you just wrote.
which tells you which of your topic notes it bears on, what it contradicts,
and what gap it opens — as a proposal in proposals/, for you to
accept or not.
The habit that makes it worth doing
Fill in ## My take yourself, the same day. Every
template has that section and no agent writes in it. Two sentences is enough.
Six months from now it is the only part of the note you will trust without
re-reading the paper, because it is the only part you wrote.
A vault where that section is always empty is a vault of summaries, and summaries are what you could have generated at any time. The notes are not the asset; your reaction to them is.
What not to do daily
- Do not run the skeptic on every note. It is a cross-document pass and it needs several documents to have anything to say. Weekly.
- Do not accept proposals the day they are written. Let them sit. A proposal that still looks right a week later usually is.
- Do not tidy. Resist asking the agent to reorganise folders. There is nothing to gain and a rename breaks every wikilink pointing at it.
8. Weekly: the two routines
Friday, ten minutes — verify
cd ~/research-system/Demo10_obsidian_research_vault/vault
claude
Use the skeptic subagent to cross-check everything added this week
against the sources in pdfs/.
Then skim the report for one thing only: claims in notes that are not in the source. Everything else can wait. That is the error that compounds, because a wrong number in a note becomes a wrong number in a draft becomes a wrong number in a submission.
git add -A && git commit -m "week of $(date +%Y-%m-%d)"
Friday, five more minutes — decide
Open proposals/. For each one: accept it by pasting the lines
into the topic note yourself, or write one line under ## Rejected
reasons saying why not.
A rejected proposal with a reason is worth as much as an accepted one. It stops the same suggestion coming back next month, and the reason is often more interesting than the proposal.
Then delete the proposal file. proposals/ should be near-empty
most of the time; a folder with forty pending proposals is a folder nobody
reads.
9. Monthly: drift and decisions
Reconcile the library against the notes — Demo 12's job
Once a month, or after any session of cleaning up Zotero:
cd ~/research-system/Demo12_zotero_obsidian_claude/workspace
claude
Use the drift subagent on the whole workspace.
Read the last section of its report first — which conclusions rest on a note I just flagged? A broken link is bookkeeping; a belief resting on one is the reason to run this at all.
What to expect in a real vault: drift accumulates at roughly the rate you edit Zotero. If you fixed metadata on ten items this month, expect ten stale notes. This is normal and is not anyone's mistake.
Re-export the radar — Demo 13's job
cd ~/research-system/Demo13_funding_radar/radar
python3 pipeline/export_vault.py
new for ones that did not exist, kept decision=pass for ones where you had already decided. Then N new, M refreshed. Decisions preserved.Then, before reading any new solicitation:
Use the recurrence subagent. Which calls in this cycle are reissues
of ones I have already decided on?
Quarterly: is the profile still true?
profile/research_profile.md decays silently. Your FTE changes, a
student graduates, the indirect rate goes up, a collaborator leaves. Nothing in
the system notices, and a stale constraints table produces confidently wrong
triage.
Four lines to re-check every few months: uncommitted FTE, indirect rate, smallest viable project, collaborators in place.
10. Adding each kind of new data
Six kinds of thing arrive in real use. Here is where each goes.
A PDF of a paper
cp paper.pdf ~/research-system/.../vault/inbox/
Then "File inbox/paper.pdf." The librarian renames it into
pdfs/, writes a note in papers/, and fills in the
frontmatter. Keep the download name — the agent should not need it to be tidy,
and if it does, that is a finding.
A web page
Use the Obsidian Web Clipper and save it into inbox/.
It uses your logged-in browser, so it gets past paywalls and institutional
logins that an agent cannot. Capture in the browser, process in the
agent — do not ask the agent to be your scraper.
Then "File the new clip in inbox/." It lands in web/,
citing the paper note it refers to.
A scanned PDF with no text layer
Same place. Check first:
pdftotext scan.pdf - | wc -c
If that prints a number under about 100, there is no text layer. Say so in
the prompt — "this is a scan, read it as images" — because Claude Code
can read PDF pages visually, 20 at a time, but will waste a step discovering
the extraction is empty. For a long scan, OCR it first with
ocrmypdf.
A fresh Zotero export
In Zotero: select the collection → right-click → Export
Collection → Better BibTeX, tick Export Files. Then again as
CSV. Replace all three — the .bib, the .csv and
storage/ — as a set.
.csv against an old storage/ produces exactly the
broken-attachment symptoms Demo 11 is built from. After any re-export, run
Demo 12's drift pass — that is precisely when new drift appears.A funding solicitation
cp ~/Downloads/NSF-27-xxx.pdf ~/research-system/.../radar/inbox/
Then "Use the recurrence subagent" first, and only then "Use the triage subagent on inbox/NSF-27-xxx.pdf." That order is not decoration: checking the decision log costs one prompt and can save the whole afternoon.
Saved web pages work the same way. If you have both the program page and the solicitation PDF, put both in — they often disagree, and finding out which is authoritative is part of the job.
Your own data — a spreadsheet of measurements
Into inbox/, and say what the units are in the prompt. The most
common real failure in these demos is comparing numbers in different units
without noticing, and the fix is one sentence from you at the start.
11. What goes wrong over time
Nothing here fails loudly. Four things decay quietly, and each has a tell:
| What rots | How you notice | What to do |
|---|---|---|
| The join notes ↔ library |
A note cites a year that does not match its PDF. Or Demo 12's drift starts reporting more each month. |
Run drift monthly, and always after editing Zotero. Repair with linker, which may change only the key field. |
| The profile Demo 13 |
Triage verdicts stop matching your judgement — it recommends things you would decline. | Re-read the constraints table quarterly. It is four numbers and they all change. |
CLAUDE.md |
It grows. Once it is long, the agent follows the first half and drifts on the rest. | Keep it under roughly one screen. When a rule gets ignored repeatedly, that is the signal to move it from CLAUDE.md into settings.json — from a request to a refusal. That migration is the single most useful maintenance habit in this whole system. |
| The decision log | decision: undecided on things whose deadline has passed. |
Decide, even if the decision is "pass, no reason recorded". An empty log is the state Demo 13 diagnoses: 90 items, 0 votes. |
The rule of thumb for all of it
When the agent does something you did not want:
- Was it a convention? → a line in
CLAUDE.md. Cheap, flexible, not enforced. - Should it have been impossible? → a deny rule in
settings.json. Enforced, and it will not be argued with. - Should this agent never have been able to? → remove the tool
from its
tools:list. Absolute.
Most people only ever write the first kind and then wonder why it keeps happening.
12. Troubleshooting
| Symptom | Cause and fix |
|---|---|
The agent ignores CLAUDE.md entirely |
You launched claude from the wrong directory. It loads from the folder you start in. cd into vault/, library/, workspace/ or radar/ — not the package root. |
| It edits a file that should be denied | Same cause nine times out of ten. Otherwise check the JSON parses: python3 -m json.tool .claude/settings.json. One trailing comma disables the whole file silently. |
Subagent not found |
The file must be in .claude/agents/ with YAML frontmatter and a name: that matches what you typed. Check with head -6 .claude/agents/*.md. |
| A subagent refuses to launch | An entry in its tools: list does not resolve — usually an MCP tool for a server that is not configured. Remove the entry or configure the server. |
| It will not read a PDF | Either no text layer (pdftotext file.pdf - | wc -c → 0; tell it to read as images) or over 10 pages, where it must read in ranges. For anything long, pdftotext -f 1 -l 12 file.pdf - first. |
| Everything is slow and expensive | pdftotext is missing, so it is reading whole PDFs as images repeatedly. Install poppler. |
| It summarises abstracts instead of reading tables | The failure the demos exist to show. Add an explicit instruction to CLAUDE.md and name the sections it must open. If that does not hold, run the verifier pass separately — a dedicated agent with one job beats a longer instruction. |
| The exporter wiped my notes | Should not happen — Demo 13's preserves the ## Decision block verbatim and that is tested. git checkout . gets them back, which is why step 2 is git init. If you wrote your own exporter, this is the bug to look for first. |
| Obsidian shows frontmatter as raw text | Turn on Properties in the right sidebar, or Settings → Editor → Properties in document → Visible. |
| Obsidian will not open the folder | Point it at the folder containing .obsidian/ — vault/, not the package root. "Trust author" when asked. |
| I want to start over | git checkout . && git clean -fd inside the working directory. Back to the shipped state, with your git history intact. |
A standing caveat. In all four packages the material is verified — every planted defect was checked mechanically against the files. The agent's behaviour was not measured: the packages were assembled on a machine without Claude Code, so the expectations in the guides are predictions. If your run differs, your run is the data. Everything in the demos is synthetic — the papers, the library, the solicitations and their deadlines do not exist. Do not cite or act on any of it.