$npx -y skills add Aperivue/medsci-skills --skill lit-syncSync research references from .bib files to Zotero library + Obsidian literature notes. Extract cross-cutting concept notes when enough literature accumulates. Works after /search-lit or standalone.
| 1 | # Literature Sync: Zotero + Obsidian Pipeline |
| 2 | |
| 3 | Takes the `.bib` output of `/search-lit` (or any user-specified .bib file) and |
| 4 | synchronizes the references into the Zotero library and Obsidian literature notes. |
| 5 | When enough literature notes accumulate, extracts cross-cutting concept notes. |
| 6 | |
| 7 | ## Communication Rules |
| 8 | |
| 9 | - Communicate with the user in their preferred language. |
| 10 | - **Vault layout — honor what exists, default to English.** Before creating notes, detect the |
| 11 | vault's existing layout: if the vault already uses a particular folder structure (including a |
| 12 | Korean one such as `02 연구/문헌/` and `02 연구/개념노트/`), **honor it — never silently |
| 13 | rename a user's folders**. For a new or unclear vault, default to the English folders |
| 14 | `Literature/` and `Concepts/` with the English note templates below. |
| 15 | - A Korean opt-in variant (Korean folder layout + Korean-heading templates) lives in |
| 16 | `references/locale/ko/note_templates.md` — use it when the vault is Korean-structured or the |
| 17 | user prefers Korean notes. |
| 18 | |
| 19 | ## When to Use |
| 20 | |
| 21 | - After `/search-lit` completes — sync the produced .bib into Zotero + Obsidian. |
| 22 | - Bulk-register references from an existing .bib into Zotero + Obsidian. |
| 23 | - Tidy the `references/` folder inside a project workspace. |
| 24 | - On explicit concept-extraction request → extract cross-cutting concepts from existing literature notes. |
| 25 | |
| 26 | ## Prerequisites |
| 27 | |
| 28 | - **Project owner only** — `/lit-sync` is an owner-scoped operation per `docs/zotero_policy.md`. Collaborators consume the committed `manuscript/_src/refs.bib` snapshot read-only. |
| 29 | - Zotero desktop 7.x + Better BibTeX plugin installed. |
| 30 | - Better BibTeX "Keep updated" auto-export configured to `<project>/manuscript/_src/refs.bib` (owner setup checklist in `docs/zotero_policy.md` §Setup). |
| 31 | - Zotero MCP server available (skip the Zotero phase if not connected; auto-export refresh still fires once Zotero is reopened). |
| 32 | - Obsidian CLI or direct file writing to the Obsidian vault. |
| 33 | - Obsidian vault path: configured in user's environment (e.g., `$OBSIDIAN_VAULT`). |
| 34 | |
| 35 | ## Artifact Contract |
| 36 | |
| 37 | Per `docs/artifact_contract.md`, `/lit-sync` is the **sole writer** of: |
| 38 | |
| 39 | | Artifact | Writer | Readers | |
| 40 | |---|---|---| |
| 41 | | `manuscript/_src/refs.bib` | `/lit-sync` (via Better BibTeX auto-export trigger) | `/write-paper`, `/verify-refs`, `/manage-refs` | |
| 42 | | `references/zotero_collection.json` | `/lit-sync` | `/verify-refs`, `/sync-submission` | |
| 43 | |
| 44 | Direct hand edits to `refs.bib` are drift — revert on sight. |
| 45 | |
| 46 | ## Pipeline Overview |
| 47 | |
| 48 | ``` |
| 49 | .bib file (or /search-lit output) |
| 50 | │ |
| 51 | ▼ Phase 1: Parse |
| 52 | Extract DOI, PMID, title, authors, journal, year |
| 53 | │ |
| 54 | ▼ Phase 2: Zotero Sync (owner) |
| 55 | Dedupe → zotero_add_by_doi → place in collection → pin citekey |
| 56 | │ |
| 57 | ▼ Phase 2.5: refs.bib snapshot refresh |
| 58 | Trigger Better BibTeX auto-export → verify manuscript/_src/refs.bib mtime updated |
| 59 | │ |
| 60 | ▼ Phase 2.7: Fulltext Retrieval (opt-in) |
| 61 | Disk OA PDFs via /fulltext-retrieval + in-library via find_available_pdf.js → reconcile report |
| 62 | │ |
| 63 | ▼ Phase 3: Obsidian Literature Notes |
| 64 | Create Literature/{citekey}.md (empty note OK — fill later with highlights) |
| 65 | │ |
| 66 | ▼ Phase 4: Concept Extraction (conditional) |
| 67 | ≥10 literature notes → scan for cross-cutting concepts → propose concept notes |
| 68 | ``` |
| 69 | |
| 70 | --- |
| 71 | |
| 72 | ## Phase 1: Parse BibTeX |
| 73 | |
| 74 | ### Input |
| 75 | |
| 76 | The user-specified .bib file path, or the .bib just produced by `/search-lit`. |
| 77 | |
| 78 | ### Process |
| 79 | |
| 80 | ```python |
| 81 | # Parse .bib entries with regex. |
| 82 | # Extract per entry: |
| 83 | # - citekey (e.g., Kim_2024_Validation) |
| 84 | # - doi |
| 85 | # - pmid |
| 86 | # - title |
| 87 | # - authors (first + last minimum) |
| 88 | # - journal |
| 89 | # - year |
| 90 | # - volume, number, pages (if present) |
| 91 | ``` |
| 92 | |
| 93 | Log any parse failures and skip those entries. |
| 94 | |
| 95 | --- |
| 96 | |
| 97 | ## Phase 2: Zotero Sync |
| 98 | |
| 99 | ### Step 2.1: Determine project collection |
| 100 | |
| 101 | Identify the project from the current working directory or from an explicit user |
| 102 | override. Reuse an existing collection key if one is recorded; otherwise create a |
| 103 | new collection. |
| 104 | |
| 105 | **Collection mapping**: Check existing Zotero collections for the current project. |
| 106 | If no collection exists, create one with `zotero_create_collection`. Record the |
| 107 | collection key for future use. |
| 108 | |
| 109 | ### Step 2.2: Dedupe + add |
| 110 | |
| 111 | For each entry: |
| 112 | |
| 113 | 1. Use `zotero_search_items` to search by DOI or title — if already present, skip. |
| 114 | This search-first step is what prevents duplicates; `zotero_add_by_doi` does **not** |
| 115 | dedupe by itself (it fetches CrossRef and creates the item), so never skip the search. |
| 116 | 2. Otherwise call `zotero_add_by_doi` (when a DOI is available) or |
| 117 | `zotero_add_by_url` (falling back to the PubMed URL when no DOI is available). |
| 118 | - `zotero_add_by |