skillZs
★ LIVE SKILL TAGS ★
>>> LIVE SKILLS INDEX <<<
* OPEN SOURCE *
NO LOGIN, NO TRACKING
※ REAL INSTALL DATA ※
← back to all skills
aperivue/medsci-skills105 installs

manage-refs

Use when references must be written, rendered or converted. Checks [@key] citation keys, renders the reference list with a journal CSL via pandoc, converts [N] markers, injects Zotero Word field codes and runs manuscript-DOCX cross-reference QC. Read-only auditing is /verify-refs.

How do I install this agent skill?

npx skills add https://github.com/aperivue/medsci-skills --skill manage-refs
view source ↗

Is this agent skill safe to install?

  • Gen Agent Trust Hubpass

    The manage-refs skill is a comprehensive toolkit for automating scientific manuscript reference workflows, including citekey validation, formatting via pandoc, and Zotero integration. It performs external data fetching from the PubMed API and interacts with a local Zotero instance to retrieve bibliographic metadata. Analysis identified standard data-ingestion surfaces and tool-chaining operations (pandoc execution), all of which are consistent with the skill's primary purpose. No malicious patterns such as credential exfiltration, prompt injection, or obfuscation were detected.

  • Socketpass

    No alerts

  • Snykpass

    Risk: LOW · No issues

What does this agent skill do?

Manage-Refs Skill

Pick the tool from the Decision Tree; do not invent a parallel pipeline. References are never hand-typed: the list is always rendered by pandoc citeproc + journal CSL or by the Zotero Word plugin (CWYW). This skill writes (renders, injects, converts); bibliographic correctness against PubMed/CrossRef stays in /verify-refs — one read-only audit, one writer.

Decision Tree

SituationToolWhy
Validate [@bibkey] ↔ refs.bib (UNDEFINED / UNUSED keys)scripts/check_citation_keys.pyHard build gate, runs in seconds
Single-author submission lockdown, frozen outputscripts/render_pandoc.sh -j <journal>Reproducible, CI-friendly
Cascade rejection (e.g., ER → JVIR → CVIR)render_pandoc.sh with new -jCSL swap reformats references in seconds
Verify a journal CSL renders the in-text format / DOI / journal-name style the author guide actually requiresscripts/check_csl_render.py --csl <x>.csl --bib refs.bib --journal <key>A stub/"dependent" CSL inherits its parent's format, which may differ from the guide (parenthetical vs superscript, DOI kept, full journal names). Run BEFORE submission, not after the proof PDF
Reference list prints FULL journal names but the journal wants NLM abbreviationsscripts/fill_journal_abbrev.pyResolves each entry DOI → PMID → PubMed NLM shortjournal into the .bib so CSL form="short" renders abbreviations; never invents abbreviations
Reviewer revision: add 1–2 refs to a Word doc with co-authors liveZotero Word plugin (user GUI)Minimal disruption to track-changes flow
Reviewer revision: bulk reference changeEdit markdown SSOT, re-run render_pandoc.shConsistency, no cherry-pick risk
Migrate [N] numeric markers → [@key] for pandocscripts/md_marker_convert.py --to-keysMapping-driven, partial conversion safe
Convert [@key] → [N] for round-trip / debugscripts/md_marker_convert.py --to-numbersSame map, opposite direction
Wire native Zotero CWYW field codes into a .docx (live Refresh in Word)scripts/inject_zotero_cwyw.pyCo-author Word workflow, post-circulation editability
Manuscript ↔ rendered DOCX cross-reference QCscripts/check_xref.py --strictSubmission gate (P0 blocker on mismatch)
Figures/tables submitted as separate attachments (radiology, most medical journals)check_xref.py --strict --allow-separate-attachmentsDowngrades MISSING_DOCX to WARN; MISSING_BODY/MISMATCH remain P0
v_(N+1) docx build-time regeneration checkcheck_xref.py --vN-docx-md5 <prev>.docx [--vN-md <prev>.md]Identity = unmodified seed copy; missing diff lines = body not regenerated
Duplicate bibliography in the built artifactscripts/check_reference_duplication.py --docx <built>.docx (or --text <rendered>.md)DUP_REF_HEADING / REF_NUMBER_RESTART / REF_SIGNATURE_DUP (Major). Catches a hand-typed ## References list plus the pandoc --citeproc auto-bibliography, which renders two lists (the second often after the legends). Run after any citeproc build
Publisher markup in a .bib title (renders as garbage)scripts/check_bib_title_markup.py --bib refs.bib --strictCrossRef titles carry <scp>WHO</scp> / <i>IDH</i>; BBT escapes them ({$<$}scp{$>$}) or strips them without restoring the space (andTERTPromoter). verify_refs proves the reference is true; this proves it will print. TITLE_MARKUP / TITLE_FUSION (Major)
Master pre-submission gate (recommended before any submission)scripts/pre_submission_gate.shChains check_citation_keys → check_bib_title_markup → verify_refs --strict → render_pandoc (optional) → check_xref --strict; single artifact qc/pre_submission_gate.json
Direct render with a built-in reference auditscripts/render_pandoc.sh (audits the .bib via /verify-refs first; blocks on FABRICATED/MISMATCH/duplicates; reports UNVERIFIED rows as not clean, without blocking)Best-effort (skips with a warning if /verify-refs is not alongside); opt out with -S. The master gate passes -S because it runs verify_refs in its stage 3
Bibliographic audit against PubMed / CrossRefdelegate to /verify-refsAudit-only — keep writer/auditor separation

Workflows

A. Pandoc citeproc (default for solo authors and final submissions)

User provides manuscript.md with [@bibkey] citations + refs.bib.

  1. Gate: python3 "${CLAUDE_SKILL_DIR}/scripts/check_citation_keys.py" manuscript.md refs.bib — exits non-zero on UNDEFINED keys. Fix and re-run. A [@NEW:topic_slug] drafting placeholder from /write-paper is reported as UNDEFINED too: resolve each by adding the citation to Zotero (/lit-sync then refreshes refs.bib) and replacing the placeholder with the real [@bibkey]. Never let a [@NEW:...] reach a rendered DOCX.
  2. Render:
    "${CLAUDE_SKILL_DIR}/scripts/render_pandoc.sh" \
      -j european-radiology \
      -i manuscript.md \
      -b refs.bib \
      -o manuscript_final.docx
    
    For the current inventory and what each style renders, read citation_styles/README.md — that table is the registry. render_pandoc.sh also lists what is on disk when -j names a style it cannot find, so ask the script rather than trusting a list written here. Two standing fallbacks: use radiology for RYAI and vancouver for JVIR (neither has a dedicated CSL). A cited key that is not in the .bib makes the render exit 5 and name the key: pandoc prints it as (key?) in the output and does not fail on its own.
  3. QC:
    python3 "${CLAUDE_SKILL_DIR}/scripts/check_xref.py" \
      --md manuscript.md --docx manuscript_final.docx \
      --out qc/xref_audit.json --strict
    
    Treat submission_safe: false as a halt. Route fixes by symptom — see the table in references/check_xref_symptoms.md.
  4. Audit hand-off: invoke /verify-refs for the PubMed/CrossRef audit before sign-off.

B. Zotero CWYW (co-author Word workflow)

User has a markdown SSOT and wants reviewers to edit citations directly in Word. Each reference must already exist as a Zotero item; the user supplies a [N] → ZoteroKey mapping.

  1. Convert markers:
    python3 "${CLAUDE_SKILL_DIR}/scripts/md_marker_convert.py" \
      --input manuscript.md --output manuscript_keys.md \
      --map ref_map.json --to-keys
    
    The conversion never guesses a Zotero key for a number: unmapped markers stay as [N], are reported on stderr, and make the script exit 1 (the partial output is still written; pass --allow-partial to accept it). Ranges such as [1-3] are expanded. Any bracketed number counts as a marker, so a year in brackets ([2019-2021]) is reported UNMAPPED too. Optionally stage with --active-ns 1,2,3,4,19 for a sample build first (a 5-reference sample limits the Word Refresh blast radius while debugging).
  2. Render to .docx with pandoc (workflow A) so the body has plain text [@key] markers, OR pre-build a .docx some other way that still contains plain [@key] text.
  3. Inject CWYW:
    python3 "${CLAUDE_SKILL_DIR}/scripts/inject_zotero_cwyw.py" \
      --input manuscript_keys.docx --output manuscript_cwyw.docx \
      --user-id <zotero-user-id> --keys-from keys.txt
    
    The script fetches item metadata live from the local Zotero connector (port 23119), so Zotero must be running locally; there is no web-API fallback. Any HTTP failure aborts with a non-zero exit, so a partial bibliography never reaches the user. Never invent Zotero metadata.
  4. First-build instruction (REQUIRED): the script writes an empty ADDIN ZOTERO_BIBL stub, which Word's Zotero Refresh treats as user-customized and refuses to populate. Open the output in Word → Zotero tab → Add/Edit Bibliography once. After that, Refresh keeps citations and bibliography in sync as authors edit.
  5. Surgical patches are unsafe: for ref additions in later rounds, edit the markdown SSOT and rebuild the whole .docx instead of regex-patching the post-CWYW file. Zotero's rendered [N] superscripts can collide with plain [N] markers and corrupt the field codes.

C. Cascade rejection re-render (find-journal hand-off)

User got rejected from journal A and /find-journal recommended journal B.

  1. Confirm the new CSL exists in citation_styles/ (or fetch from https://citationstyles.org/styles and drop in).
  2. Re-run render_pandoc.sh -j <new-csl> against the same manuscript.md + refs.bib.
  3. Re-run check_xref.py --strict.
  4. Re-run /verify-refs if any new references were added during the inter-journal revision.

D. Cross-reference QC only

User shipped a manuscript and a reviewer flagged a Table/Figure mismatch.

  1. Run check_xref.py --strict on the current manuscript.md + .docx.

  2. Inspect qc/xref_audit.json. Body caption is the SSOT — fix manuscript.md and rebuild, never patch the .docx by hand.

  3. See references/check_xref_symptoms.md for the MISSING_BODY / MISSING_DOCX / MISMATCH triage table.

  4. For journals that accept figures and tables as separate attachment files (European Radiology, Radiology, AJR, JVIR, KJR, and most medical journals), pass --allow-separate-attachments. It downgrades two rows, reported apart because their evidence differs:

    • MISSING_DOCX — a --docx was supplied and proved the float is not in the rendered main document. That is what a separate attachment looks like.
    • MISSING_BODY with no --docx supplied — nothing was checked. Excused on your word, printed as EXCUSED WITHOUT EVIDENCE, and counted in summary.downgraded_unchecked.

    MISMATCH stays P0. So does MISSING_BODY when the float is in the rendered DOCX — that is SSOT drift, which no attachment policy excuses.

    Run once with --docx before submitting. The flag is a declaration, not a verification; supplying the DOCX is what converts an excuse into evidence.

D'. v_(N+1) docx regeneration check (build-time companion)

When building v_(N+1) from a frozen v_N, the v_(N+1) docx MUST differ from v_N docx by content — a byte-identical copy is a silent seed-copy that will revert markdown edits at peer review. check_xref.py carries two flags for the build-time companion to the submission-time gate in /sync-submission's scripts/verify_package_integrity.py --assert-vN-docx-changed:

python3 "${CLAUDE_SKILL_DIR}/scripts/check_xref.py" \
    --md manuscript_v2.md \
    --docx manuscript_v2.docx \
    --vN-docx-md5 manuscript_v1.docx \
    --vN-md manuscript_v1.md \
    --strict
  • --vN-docx-md5 alone: MD5 identity check. Identical bytes = FAIL.
  • --vN-docx-md5 + --vN-md: additionally extracts the markdown-only diff between v_N and v_(N+1) and verifies each ≥40-char diff line appears verbatim (whitespace-normalized, case-insensitive) in the new docx body XML. Missing diff lines = body did not pick up the markdown edits.

Output records the result under vN_docx_check in qc/xref_audit.json. Either failure mode causes a non-zero exit even without --strict.

E. Master pre-submission gate (recommended end-to-end chain)

The single entry point that combines workflows A and D plus /verify-refs into one aborting chain. Use this immediately before submission or before circulating a v_N package to senior co-authors.

bash "${CLAUDE_SKILL_DIR}/scripts/pre_submission_gate.sh" \
    --md manuscript/manuscript.md \
    --bib manuscript/_src/refs.bib \
    --docx submission/<journal>/manuscript.docx \
    --allow-separate-attachments    # omit if the journal accepts inline figures/tables

Stage order (first failure aborts):

  1. check_citation_keys.py manuscript.md refs.bib — UNDEFINED / UNUSED keys
  2. check_bib_title_markup.py --strict — publisher markup / tag-strip fusion in .bib titles
  3. verify_refs.py refs.bib --strict — PubMed / CrossRef per-entry verification
  4. render_pandoc.sh -S -j <csl> -i ... -b ... -o ... — invoked only when --docx is omitted (--journal <csl>, default vancouver)
  5. check_xref.py --md ... --docx ... --strict [--allow-separate-attachments]

On success the chain writes qc/pre_submission_gate.json (plus the per-stage artifacts qc/bib_title_markup.json, qc/reference_audit.json and qc/xref_audit.json) with submission_safe: true. On any failure the JSON records the failing stage and exit code, and the script exits non-zero — do not submit until the failing stage passes.

The gate does not reimplement any check; it calls the existing scripts as subprocesses. A new check belongs in the underlying script, which the gate then picks up.

F. BibTeX author-format corruption (rendered-name check)

Entries written as author = {Surname AB and Surname2 CD} (family + initials, no comma) make BibTeX treat the last token as the family name, rendering "AB S, CD S2". Always store author = {Family, Full Given}. Concatenated initials even with a comma (Family, AB) still collapse to a single initial under CSL initialize-with, so use the full forename from PubMed efetch.

/verify-refs compares bib content against PubMed but does not see the rendered output; grep the rendered docx and the bib separately:

unzip -p out.docx word/document.xml | sed 's/<[^>]*>//g' | grep -oE "[A-Z]{2} [A-Z], [A-Z]{2} [A-Z]"   # corruption signature in output
grep -nE 'author\s*=\s*\{[A-Z][a-z]+ [A-Z]{1,3}( |\})' refs.bib                                          # no-comma source entries

Quality Gates

This skill defines three submission gates and one user approval gate:

  • Gate 1 (citekey integrity): check_citation_keys.py exits non-zero on UNDEFINED keys. The pipeline halts; the user reviews and fixes.
  • Gate 2 (cross-reference integrity): check_xref.py --strict exits 1 on any MISSING_DOCX / MISSING_BODY / MISMATCH row (a float the markdown defines but the DOCX lacks is MISSING_DOCX even when no in-text citation of it was recognised; a legend inside an HTML comment or fenced code is not rendered, so it stays UNCITED). With --docx and no python-docx it exits 2: the DOCX audit did not run. The user reviews qc/xref_audit.json and resolves before proceeding. Under --allow-separate-attachments, check summary.downgraded_unchecked as well as submission_safe: a non-zero count means rows passed without being checked.
  • Gate 3 (audit hand-off): before sign-off, the user must run /verify-refs and confirm submission_safe: true in qc/reference_audit.json. This skill never marks the bibliography audited on its own.
  • User approval gate (CWYW first build): the user must perform Word → Zotero → Add/Edit Bibliography manually after the first inject_zotero_cwyw.py build. The skill cannot automate this and warns on stderr that it is required.

Provenance

scripts/_vendor_citation_writer.py is vendored from alisoroushmd/zotero-mcp @ ed5dfb71, MIT licensed. See NOTICE.md and LICENSE.zotero-mcp.

Known Limitations

  • Webpage / non-journal item types: handled by the patched zotero_to_csl_json that fetches Zotero's native CSL-JSON; do not bypass this patch.
  • "Table 1 and 2" (singular kind word, number list): check_xref.py reads only Table 1 from it; parsing a bare number after "and" in prose would read "Table 1 and 2 patients" as a citation. A float defined in the markdown but absent from the DOCX is still blocked as MISSING_DOCX; one that is neither defined nor rendered is not seen. Write "Tables 1 and 2" or "Table 1 and Table 2".

Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.

<a href="https://skillzs.dev/skills/aperivue/medsci-skills/manage-refs">View manage-refs on skillZs</a>