Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Bib Manage

ASecurity

ALWAYS use when a manuscript's BIBLIOGRAPHY is the thing being fixed, or when a cite's PDF turns out to be wrong — 'link my bib entries to the PDFs', 'which sources am I missing a PDF for', 'audit my sources.bib', 'my bib entry has no file field', 'fetch the Federal Register PDFs', 'why can't pincite find this source'. WRONG FILE: 'is this PDF the published version or the preprint', 'this PDF is a book review, not the book', 'the file field points at the wrong paper', 'the PDF doesn't match t...

21 stars
0 votes
0 copies
0 views
Added 9/19/2026
researchpythonrustgobashtestinggit

Works with

cli

Security Analysis

A100/100

Scanned 9/19/2026

Install to Claude Code

$npx -y skills add edwinhu/workflows --skill bib-manage --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Bib Manage?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Bib Manage
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/edwinhu-bib-manage/badge)](https://www.skillsdirectory.com/skills/edwinhu-bib-manage)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: bib-manage
description: "ALWAYS use when a manuscript's BIBLIOGRAPHY is the thing being fixed, or when a cite's PDF turns out to be wrong — 'link my bib entries to the PDFs', 'which sources am I missing a PDF for', 'audit my sources.bib', 'my bib entry has no file field', 'fetch the Federal Register PDFs', 'why can't pincite find this source'. WRONG FILE: 'is this PDF the published version or the preprint', 'this PDF is a book review, not the book', 'the file field points at the wrong paper', 'the PDF doesn't match the citation'. METADATA: 'reconcile my bib against Paperpile', 'these entries were extracted by a model, check them', 'fix the metadata in sources.bib', 'my bib has no DOIs and the fields look wrong', 'pull the real author/journal/volume from my library', 'where did this bib entry's metadata come from'. PAGE RANGES: 'does my bib have page ranges', 'my bib only has start pages', 'backfill the page ranges', 'pull the pages from the DOI', 'add DOIs to my bibliography'. Use proactively before any pincite run — pincite resolves footnotes through `file = {...}` and silently skips entries that lack one. NEGATIVE ROUTING: the page number inside a footnote is pincite, but whether that footnote's PDF is the version of record or the wrong document is THIS skill, mid-pincite-run included; whether a cited source says what the footnote claims is source-verify; Bluebook FORM is bluebook or bluebook-audit; finding or downloading a paper is fetch-paper or paperpile."
---

# Bib-manage

**What this skill carries** — grep `references/` for any subject the names below miss:
!`d=${CLAUDE_SKILL_DIR}; command -v skill-toc >/dev/null 2>&1 && exec skill-toc "$d"; s=$HOME/.claude/skills/plugin-utils/bin/skill-toc; [ -x "$s" ] && exec "$s" "$d"; echo "(skill-toc unavailable: references and scripts are NOT listed here — install the plugin-utils plugin, or start a new session so its bin/ reaches PATH)"`

Owns the bibliography as an **index**: every entry pointing at the right PDF, and
that PDF being the version of record.

pincite CONSUMES this index — it resolves footnote → source through
`file = {...}` and through nothing else. So the two failures this skill exists to
prevent are both silent in pincite: an entry with no `file` is a pincite that is
never attempted, and an entry pointing at a preprint is a pincite that is
confidently wrong.

```
audit    entries with/without file, files missing on disk, entries without a
         DOI, PDFs no entry claims          <- run this first
link     citekey -> PDF, written back as file = {...}
version  is each entry's PDF the published version, or a preprint/proof?
doi      backfill missing DOIs from Crossref, verified against the bib's pages,
         and the PAGE RANGE that same verified record already carries
reconcile
         rewrite the entry's OWN FIELDS from a better source:
         Paperpile > Crossref > the extracted value. Never `file`, never a key
fedreg   fetch the Federal Register PDFs the entries cite
```

## CLI

```bash
B="${CLAUDE_SKILL_DIR}/scripts/bibman.py"

python3 "$B" audit   --root .                 # start here
python3 "$B" link    --root . --dry-run       # inspect the mapping first
python3 "$B" link    --root . --backup        # then write
python3 "$B" version --root .
python3 "$B" doi     --root . --dry-run --only aggarwal2015
python3 "$B" reconcile --root . --dry-run            # read the full set FIRST
python3 "$B" reconcile --root . --backup --fields doi,pages
python3 "$B" fedreg  --root . --dry-run
```

Every path is a flag — `--bib`, `--pdf-dir`, `--fedreg-dir` — defaulting to the
layout pincite uses, so the tool works on any manuscript. `--only` scopes
`version` and `doi` to named citekeys; `--dry-run` reports without writing;
`--backup` leaves a `.bak`; `--strict` makes `version` exit 1 on any entry that
is not the version of record.

`--fields` scopes `reconcile` to a subset of `author,title,journal,volume,pages,
year,doi,publisher`; `--pp-index` points at the Paperpile CLI's index cache.

`audit`, `link` and `version` never touch the network. `doi` and `fedreg` do.
`reconcile` reads Paperpile locally and reaches Crossref only for what Paperpile
does not cover.

## Facts

- **The link threshold depends on the YEAR, and that is the whole of its
  accuracy.** Two matchers run in order: PDF stem == citekey (48 of 79 on the
  test bibliography), then Paperpile-style `Author Year - Title.pdf` on
  first-author surname plus title similarity (the other 31). Same year, the year
  corroborates and **0.55** is enough. DIFFERENT year — a working paper against
  its published version, `Lund 2017` → `lund2018` — demand **≥ 0.95**, because
  only the title separates two papers by one author. At 0.55 with the year
  ignored, `alexander2010` ("Interim News and the Role of Proxy Voting Advice")
  claims the PDF "The role of advisory services in proxy voting" at **0.52**.
  That is a wrong `file` in the bib, which is the one input pincite trusts
  absolutely — a mis-link there sends a footnote to another paper and can verify
  CONFIRMED while doing it.

- **Never force a match; REPORT what stays unmapped.** On the test bibliography
  four PDFs stay unclaimed and every one is correct: `Alexander et al. 2009`
  (0.52), `Cremers and Romano 2011` whose filename is truncated mid-title by the
  filesystem (`...proxy voting on co ... ion plans...`, best match 0.89 against a
  2007 entry), and two whose filenames are not `Author Year - Title` at all. An
  unmapped PDF costs a minute of human attention. A forced one costs a wrong
  citation nobody looks at again.

- **Paperpile writes SURNAMES ONLY, so the first-author surname is the FIRST
  token.** `Barzuza et al.`, `Bebchuk and Hirst`, `Rock`. Taking the last token —
  the correct habit for a bibtex `author` field — reads "Barzuza et al." as an
  author named "al." and unmapped **14 of 83** PDFs here before it was caught.

- **A 6-digit `pages` is an Elsevier ARTICLE NUMBER, not a page.**
  `J. Fin. Econ. 154 (2024) 103810` is paginated 1–N in its own PDF and IS the
  version of record. Range-testing it reports every such entry as a preprint —
  `shu2024` and `cabezon2025` are both genuinely published and both false alarms
  without this exception.

- **A publisher's own PDF can be an ADVANCE-ACCESS PROOF.** OUP served
  `iliev2021` as pages 1–49 instead of 5581+, `v 00 n 0`, internal name
  `RFS-OP-….tex` — authenticated, current, and useless for a pincite. Flag when
  the range test fails AND page 1 carries no nonzero volume designation. A
  successful fetch never means the pagination problem is solved.

- **Do NOT identify the version of record by matching the journal name against
  page 1.** Bib journal names are Bluebook abbreviations ("Rev. Fin. Stud.")
  that never appear in a masthead ("The Review of Financial Studies"). That test
  flagged **46 of 61** entries and is worthless. The derived printed-page range
  against the bib's start page is the test that works: 5 of 79 flagged, all five
  real preprints.

- **The page derivation is pincite's, imported not copied.** `pages_of`,
  `page_numbers` and `page_offset` are pure functions and pincite does nothing at
  import time. Copying them lets the two skills' notion of "what page is this"
  drift, and a `version` verdict that disagreed with pincite's own would be worse
  than no verdict.

- **A bibliographic title query returns the SSRN PREPRINT DOI.** Measured on
  `aggarwal2015`: title alone returns `10.2139/ssrn.2120797`,
  `10.2139/ssrn.1688993`, `10.2139/ssrn.2023480` — the top three hits are all
  SSRN, none carries a page. Query with title **+ journal + volume + pages**, then
  VERIFY the returned record's start page equals the bib's `pages` before
  accepting: that yields `10.1111/jofi.12284`, page 2309–2346 against the bib's
  2309. A DOI that fails the page check is reported, never written — it is
  usually the preprint of the very work the entry means.

- **The verified Crossref record already carries the END page; `doi` writes it.**
  The match test was always `record start page == bib start page`, so the range
  that passes it is the same work's own span — `10.1111/jofi.12284` returns
  `2309-2346` against a bib holding `2309`. Written as `pages = {2309--2346}`.
  Four guards, and each blocks a different way of destroying a value that was
  already right: **`@article` only** (a `@misc` press release's `pages = {1}` is
  not an article span); **a bare start page only**, so a Bluebook pincite
  someone recorded there survives — on OPV `easterbrook1991` (`66-67`) and
  `jackson2019` (`849, 851--52`) are the only range-like values in 197 entries
  and BOTH are pincites, not spans; **never an `ARTICLE_NUMBER`**; and **the
  Crossref range must START at the bib's page**, re-checked at write time so the
  DOI test and the range test can never disagree. Measured on OPV: 55 of the 64
  bare start pages were eligible, **30 resolved**, and the 25 that did not are
  law reviews, which Crossref indexes thinly.

- **An end page turns `version` from one test into three.** With only a start
  page the derived span can be asked one question, `lo <= start <= hi`. With
  the end page it answers whether the span's BOTH endpoints fall inside, and
  whether the PDF's page count can hold the printed span at all — `n < span` is
  impossible for a version of record, and `n > span + 2` (beyond a cover sheet)
  is a different artifact. `aggarwal2015` is a 57-page PDF claiming a 38-page
  span, `ertimur2018` 64 pages for 21, `hayne2019` 59 for 43; each now fails on
  three counts instead of one, with no header parsing. Entries with no end page
  keep the start-only path unchanged — on OPV that is still most of them, and
  all 77 verdicts were byte-identical before and after the backfill.

- **`reconcile`'s precedence is Paperpile > Crossref > the extracted value, and
  it is implemented as source ORDER, not a merge.** An entry confidently matched
  in Paperpile is never queried against Crossref, so the stronger source cannot
  be contradicted by the weaker one. On OPV — a bib whose header reads
  `Auto-extracted from sources.md via Gemini Vertex Batch`, where every field was
  written by a model reading a markdown list and no entry carried a DOI —
  Paperpile covered **33** of 197, Crossref **24**, and **140** had neither.
  Every change prints as `citekey.field: old -> new  [source]`; `--dry-run`
  writes nothing and is byte-identical run to run.

- **A CONFIDENT Paperpile match needs the surname, the year AND the title, and
  an entry with no author needs the year EXACTLY.** Surname equal, |Δyear| ≤ 1,
  title ≥ 0.90 same-year / ≥ 0.95 across a year — the same asymmetry `link`
  uses. With NO author there is nothing to corroborate with, and 1.00-vs-0.97
  is not enough: `secproxyadvice2019` (the SEC's own 2019 release, 84 Fed. Reg.
  66,518) matched a **2020 COMMENT LETTER** about it at 0.98, whose title is the
  release's title with `RE: ` in front. Requiring Δyear == 0 there kills it; a
  document with no author has a fixed date and no working-paper drift to
  forgive. Two candidates within 0.02 of each other are AMBIGUOUS — reported,
  never picked, because a wrong library match rewrites author, title, journal
  and DOI at once.

- **Crossref's start-page verification is `@article` ONLY, because a pincite is
  shaped exactly like a page range.** Nothing in the VALUE `66-67` says whether
  it is pages 66 to 67 of an article or a Bluebook pincite into a book. Reading
  `easterbrook1991`'s 66 as a start page made Crossref accept
  `10.1111/j.1468-0319.1991.tb00155.x`, titled **"Discussion Papers"**, because
  it happens to begin on page 66 — a proposal to overwrite the title of *The
  Economic Structure of Corporate Law*. The entry TYPE is what separates them,
  and `range_blocked` already said so. This guard lives in `crossref_pick`, so
  `doi` gets it too.

- **A Paperpile record can be the SSRN PREPRINT of a published article, and
  taking its fields REGRESSES the citation.** `choi2009` (S. Cal. L. Rev. 82:649)
  and `bebchuk2019a` (B.U. L. Rev. 99:721) are both published; both library
  records carry `journal = SSRN Electron. J.` and a `10.2139/ssrn.*` DOI.
  Precedence orders sources by reliability — it does not authorise replacing a
  real journal name with a preprint server's placeholder. When the source record
  is SSRN-shaped and the entry ALREADY names a journal, `journal`, `volume`,
  `pages`, `year`, `publisher` and `doi` are all refused and reported. A genuine
  working paper has no journal to protect, so it is unaffected.

- **Precedence does not authorise a THINNER rendering of a name.** Paperpile
  answered `J Fisch and A Hamdani and S D Solomon` for `fisch2019`'s
  `Jill E. Fisch and Assaf Hamdani and Steven Davidoff Solomon`, and Crossref
  answered `VICENTE CUÑAT and MIREIA GINE and MARIA GUADALUPE` for `Vicente
  Cuñat and Mireia Giné and Maria Guadalupe` — initials for given names, and
  full caps with the accents gone. Both are refused and reported. Note that
  `str.isupper()` on the whole author string is ALWAYS False: the ` and `
  separators are lowercase, so the test must run on the names alone.

- **`reconcile` never touches `file` and never touches a citekey.** `file` is
  not in `RECONCILE_FIELDS` and is refused by name in `field_blocked` — the PDF
  mapping belongs to `link`, which owns the matcher and its thresholds. The keys
  are load-bearing for something outside this repo: `paper/typst/opv-body.typ`
  references entries through `#ref(<key>)` and that project's `scripts/resolve_refs.py` resolves
  supra numbers through them, so a renamed key silently breaks the manuscript.
  After writing, the file is re-parsed and the key LIST compared to what it was;
  a mismatch exits non-zero pointing at the `.bak`.

- **federalregister.gov bot-blocks every request** and lands on
  unblock.federalregister.gov. Fetch from govinfo's link service,
  `https://www.govinfo.gov/link/fr/<vol>/<page>?link-type=pdf`, into
  `--fedreg-dir` as `fedreg-<vol>-<page>.pdf`. Pre-2000 volumes return the WHOLE
  ISSUE, 200+ MB — trim with `qpdf --empty --pages IN a-b -- OUT`. The SEC's own
  release PDF of the same document has different pagination, so it is the wrong
  source for a Fed. Reg. pincite.

## Red flags — STOP

| About to | Why wrong | Do instead |
|---|---|---|
| Run pincite on a bib you have not audited | Entries with no `file` are skipped silently; here that was 118 of 197 | `audit` first |
| Lower the 0.95 cross-year threshold to map "just one more" PDF | At 0.55 `alexander2010` claims the wrong paper at 0.52 | Leave it unmapped and link it by hand |
| Hand-add a `file` to make an unmapped PDF go away | The unmapped list is the output, not a failure | Read the reason it prints first |
| Report a 6-digit `pages` entry as a preprint | It is an Elsevier article number; the PDF is the version of record | Trust the `article-number` skip |
| Check the version of record by finding the journal name on page 1 | Bluebook abbreviations never match mastheads — 46 of 61 flagged | Range-test the derived pages against the bib's start page |
| Accept a Crossref DOI because the title matched | Title-only returns the SSRN preprint; 6 of 7 test entries | Require the start page to equal the bib's `pages` |
| Write a page range over a `pages` that already holds one | It is a Bluebook pincite, not a span — both such values on OPV were | Leave it; `doi` reports it as SKIPPED |
| Give a `@misc` or `@book` entry an article span | `pages = {1}` on a press release is not page 1 of an article | The `@article` guard; read the SKIPPED list |
| Trust a freshly fetched publisher PDF | It can be an advance-access proof paginated 1–N | Re-run `version` on anything fetched |
| Use the SEC release PDF for a `Fed. Reg.` cite | Different pagination from the one the cite uses | `fedreg` via govinfo `link/fr/<vol>/<page>` |
| Run `link` without `--dry-run` on a bib you have not inspected | It writes into 197 entries | `--dry-run` first, then `--backup` |
| Run `reconcile` without reading the full `--dry-run` set | It rewrote 163 fields across 47 entries on OPV | Read every line, then `--backup`; `--fields` to scope |
| Take a Paperpile record's `journal` when the entry already names one and the record is SSRN | `SSRN Electron. J.` over `B.U. L. Rev.` is a regression, not a correction | The SSRN guard; read the CONFLICTS list |
| Accept a Paperpile match on a no-author entry a year apart | The SEC's 2019 release matched a 2020 comment letter at 0.98 | Δyear == 0 when there is no surname to corroborate |
| Let Crossref verify a non-`@article` by its start page | `66-67` is a pincite, and "Discussion Papers" also starts on page 66 | `@article` only — the type is what separates them |
| Add `file` to `RECONCILE_FIELDS` "since it is a field too" | The PDF mapping is `link`'s, matcher and thresholds included | Leave it; `field_blocked` refuses it by name |

Attribution

edwinhuedwinhu
View sourceMore from edwinhu →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Competitor Analysis

This skill provides comprehensive analysis of competitor SEO and GEO strategies, revealing what's working in your market and identifying opportunities to outperform the competition.

1823 votes

Deep Research

Universal deep research agent team. 13-agent pipeline for rigorous academic research on any topic. 7 modes: full research, quick brief, paper review, lit-review, fact-check, Socratic guided research dialogue, and systematic review with optional meta-analysis. Covers research question formulation, Socratic mentoring, methodology design, systematic literature search, source verification, cross-source synthesis, risk of bias assessment, meta-analysis, APA 7.0 report compilation, editorial review...

452202 votes

Paperclip Distill

Use when an operation issue is a Paperclip cursor-window, distill, or backfill — `operationType: "distill"` or `"backfill"` and the body references a Paperclip source bundle for a project or root issue. Turn raw Paperclip activity into a wiki-insightful project page, decisions log, and history note. This skill exists specifically to replace the stiff, datestamp-heavy templated output that the deterministic distiller produces.

798221 votes

Academic Pipeline

Orchestrator for the full academic research pipeline: research -> write -> integrity check -> review -> revise -> re-review -> re-revise -> final integrity check -> finalize. Coordinates deep-research, academic-paper, and academic-paper-reviewer into a seamless 10-stage workflow with mandatory integrity verification, two-stage peer review, and reproducible quality gates. Triggers on: academic pipeline, research to paper, full paper workflow, paper pipeline, end-to-end paper, research-to-publi...

452201 votes

Exa Search

Semantic search, similar content discovery, and structured research using Exa API

304951 votes
View all in research →