Use this skill for any request to validate, check, clean up, or fix a BibTeX .bib file.
If the request includes a .bib path, operate on it. If the path is missing or does not exist, ask for it.
Assumptions:
- Process entries one by one.
- Only brace-style BibTeX like
@article{...} is supported; reject parenthesized @article(...).
- Preserve
@string, @preamble, and @comment blocks verbatim.
Resolve Tools
All bundled scripts live in tools/ next to this file. Resolve TOOLS_DIR once:
for d in \
"${CODEX_HOME:-$HOME/.codex}/skills/bibtidy/tools" \
"$HOME/.claude/skills/bibtidy/tools" \
"${CLAUDE_PLUGIN_ROOT:-/dev/null}/skills/bibtidy/tools"; do
[ -f "$d/crossref.py" ] && TOOLS_DIR="$d" && break
done
Useful commands:
python3 $TOOLS_DIR/compare.py <file.bib> [--key KEY]
python3 $TOOLS_DIR/crossref.py doi <DOI>
python3 $TOOLS_DIR/crossref.py search "<title>"
python3 $TOOLS_DIR/crossref.py bibliographic "<query>"
python3 $TOOLS_DIR/duplicates.py <file.bib>
python3 $TOOLS_DIR/edit.py <file.bib> <patches.json>
Patch Rules
Use edit.py for all actual .bib changes. Do not edit the file directly with agent editing tools and do not rewrite the whole file.
fix patch: include key, action, urls, explanation, and fields; entry_type is optional.
- In
fields, set a field to null to remove it; omit a field to leave it unchanged.
not_found: comment out the original entry; do not add URL lines.
duplicate: add % bibtidy: DUPLICATE of <other_key> — consider removing above the original entry; no URL lines.
review: add one or more % bibtidy: <URL> lines plus % bibtidy: REVIEW, <reason> above the unchanged entry.
- Clean entries get no comments.
For fix patches, edit.py should produce:
- fully commented original entry
- one
% bibtidy: <URL> line per source
- one
% bibtidy: <explanation> line
- corrected entry
Use source values verbatim. If the bib entry uses and others and a verified source provides the full author list, replace it with the full list.
Workflow
Each entry has a web-search budget of 1 total, used in at most one of Wave A or Wave B.
- Read the file and note the path.
- Clear the platform log:
> <file>.bib.cc.log in Claude Code or > <file>.bib.codex.log in Codex.
- Back up the file:
cp <file>.bib <file>.bib.orig
- Run
python3 $TOOLS_DIR/duplicates.py <file.bib> before metadata fixes.
- Run
python3 $TOOLS_DIR/compare.py <file.bib> for CrossRef candidates.
- Wave A web search: every entry with
error set or no candidates must be web-verified. Those entries have spent their budget.
- After each wave, classify every entry as one of:
Clean: confirmed, no changes
Fix: confident correction
Escalate: still ambiguous and budget unused
Not found: no paper found after required search
Review: budget spent and still uncertain
- Wave B web search: only entries marked
Escalate and not yet searched. After Wave B, final outcomes are only Clean, Fix, Not found, or Review.
- Write a real
patches.json file and apply fixes with python3 $TOOLS_DIR/edit.py <file.bib> patches.json.
- Run
python3 $TOOLS_DIR/duplicates.py <file.bib> again. Resolve every unresolved same-key collisions warning and rerun until the warning is gone.
- Manually review likely related entries after fixes. Strong clues: repeated citation keys, repeated DOIs, same normalized title with overlapping authors, obvious preprint→published pairs. If two entries should be linked but not auto-removed, apply a
duplicate patch.
- Validate format, delete the backup, and print a summary table with rows: total entries, verified, fixed, not found, needs review, exact duplicates removed, near-duplicates flagged.
For files with more than 30 entries, work in batches of about 15 and report progress. Entry count must match before and after.
Compare Carefully
compare.py returns raw CrossRef candidates plus discrepancies. Treat them as hints, not truth.
- A missing candidate field is not evidence that the bib field should be removed.
- If a verified candidate supplies a missing standard venue field such as volume, issue, or pages, add it.
- Never add a
doi field when the bib entry currently lacks one.
- Treat
author vs authors and journal vs booktitle as schema mismatches until verified.
- If a preprint has a verified published version, update title, venue, year, volume, number, and pages together.
- When the published title differs, replace the title verbatim; do not partially edit it.
- Use
-- for BibTeX page ranges.
- Missing
pages is not automatically an error for venues that do not publish page numbers.
Web Verification
Use subagents when available; otherwise do the same work sequentially. Cap at 6 subagents per wave and distribute entries evenly.
Each web-search subagent should return only JSON with:
key
source_urls
fields
notes
Rules for subagents:
fields is either a fix-patch dict or null.
- Use
null inside fields to remove a stale field.
- Verify against authoritative pages when possible: DOI page, publisher page, venue page, arXiv, OpenReview, etc.
- Check title, full author list, year, journal/booktitle, volume, number/issue, pages, and DOI.
- Put a value in
fields when the verified source disagrees with the bib entry or when the bib entry is missing a standard field that the venue publishes.
- Do not add a missing
doi field just because you found one; mention it in notes if useful.
- If a standard field is genuinely unavailable, say so in
notes.
Preserve
- Entry order
- All unchanged fields
- Empty lines between entries
- User
% comments that are not % bibtidy:
@string, @preamble, and @comment blocks
- LaTeX macros and brace-protected capitalization in titles
If rate-limited, note it and continue with the next entry.
1---2name: bibtidy3description: Use when the user wants to validate, check, or fix a BibTeX (.bib) reference file, wrong authors, stale arXiv preprints, incorrect metadata, duplicate entries, formatting issues4---56Use this skill for any request to validate, check, clean up, or fix a BibTeX `.bib` file.78If the request includes a `.bib` path, operate on it. If the path is missing or does not exist, ask for it.910Assumptions:11- Process entries one by one.12- Only brace-style BibTeX like `@article{...}` is supported; reject parenthesized `@article(...)`.13- Preserve `@string`, `@preamble`, and `@comment` blocks verbatim.1415## Resolve Tools1617All bundled scripts live in `tools/` next to this file. Resolve `TOOLS_DIR` once:1819```bash20for d in \21 "${CODEX_HOME:-$HOME/.codex}/skills/bibtidy/tools" \22 "$HOME/.claude/skills/bibtidy/tools" \23 "${CLAUDE_PLUGIN_ROOT:-/dev/null}/skills/bibtidy/tools"; do24 [ -f "$d/crossref.py" ] && TOOLS_DIR="$d" && break25done26```2728Useful commands:29- `python3 $TOOLS_DIR/compare.py <file.bib> [--key KEY]`30- `python3 $TOOLS_DIR/crossref.py doi <DOI>`31- `python3 $TOOLS_DIR/crossref.py search "<title>"`32- `python3 $TOOLS_DIR/crossref.py bibliographic "<query>"`33- `python3 $TOOLS_DIR/duplicates.py <file.bib>`34- `python3 $TOOLS_DIR/edit.py <file.bib> <patches.json>`3536## Patch Rules3738Use `edit.py` for all actual `.bib` changes. Do not edit the file directly with agent editing tools and do not rewrite the whole file.3940- `fix` patch: include `key`, `action`, `urls`, `explanation`, and `fields`; `entry_type` is optional.41- In `fields`, set a field to `null` to remove it; omit a field to leave it unchanged.42- `not_found`: comment out the original entry; do not add URL lines.43- `duplicate`: add `% bibtidy: DUPLICATE of <other_key> — consider removing` above the original entry; no URL lines.44- `review`: add one or more `% bibtidy: <URL>` lines plus `% bibtidy: REVIEW, <reason>` above the unchanged entry.45- Clean entries get no comments.4647For `fix` patches, `edit.py` should produce:48- fully commented original entry49- one `% bibtidy: <URL>` line per source50- one `% bibtidy: <explanation>` line51- corrected entry5253Use source values verbatim. If the bib entry uses `and others` and a verified source provides the full author list, replace it with the full list.5455## Workflow5657Each entry has a web-search budget of 1 total, used in at most one of Wave A or Wave B.58591. Read the file and note the path.602. Clear the platform log: `> <file>.bib.cc.log` in Claude Code or `> <file>.bib.codex.log` in Codex.613. Back up the file: `cp <file>.bib <file>.bib.orig`624. Run `python3 $TOOLS_DIR/duplicates.py <file.bib>` before metadata fixes.635. Run `python3 $TOOLS_DIR/compare.py <file.bib>` for CrossRef candidates.646. Wave A web search: every entry with `error` set or no `candidates` must be web-verified. Those entries have spent their budget.657. After each wave, classify every entry as one of:66 - `Clean`: confirmed, no changes67 - `Fix`: confident correction68 - `Escalate`: still ambiguous and budget unused69 - `Not found`: no paper found after required search70 - `Review`: budget spent and still uncertain718. Wave B web search: only entries marked `Escalate` and not yet searched. After Wave B, final outcomes are only `Clean`, `Fix`, `Not found`, or `Review`.729. Write a real `patches.json` file and apply fixes with `python3 $TOOLS_DIR/edit.py <file.bib> patches.json`.7310. Run `python3 $TOOLS_DIR/duplicates.py <file.bib>` again. Resolve every `unresolved same-key collisions` warning and rerun until the warning is gone.7411. Manually review likely related entries after fixes. Strong clues: repeated citation keys, repeated DOIs, same normalized title with overlapping authors, obvious preprint→published pairs. If two entries should be linked but not auto-removed, apply a `duplicate` patch.7512. Validate format, delete the backup, and print a summary table with rows: total entries, verified, fixed, not found, needs review, exact duplicates removed, near-duplicates flagged.7677For files with more than 30 entries, work in batches of about 15 and report progress. Entry count must match before and after.7879## Compare Carefully8081`compare.py` returns raw CrossRef candidates plus `discrepancies`. Treat them as hints, not truth.8283- A missing candidate field is not evidence that the bib field should be removed.84- If a verified candidate supplies a missing standard venue field such as volume, issue, or pages, add it.85- Never add a `doi` field when the bib entry currently lacks one.86- Treat `author` vs `authors` and `journal` vs `booktitle` as schema mismatches until verified.87- If a preprint has a verified published version, update title, venue, year, volume, number, and pages together.88- When the published title differs, replace the title verbatim; do not partially edit it.89- Use `--` for BibTeX page ranges.90- Missing `pages` is not automatically an error for venues that do not publish page numbers.9192## Web Verification9394Use subagents when available; otherwise do the same work sequentially. Cap at 6 subagents per wave and distribute entries evenly.9596Each web-search subagent should return only JSON with:97- `key`98- `source_urls`99- `fields`100- `notes`101102Rules for subagents:103- `fields` is either a fix-patch dict or `null`.104- Use `null` inside `fields` to remove a stale field.105- Verify against authoritative pages when possible: DOI page, publisher page, venue page, arXiv, OpenReview, etc.106- Check title, full author list, year, journal/booktitle, volume, number/issue, pages, and DOI.107- Put a value in `fields` when the verified source disagrees with the bib entry or when the bib entry is missing a standard field that the venue publishes.108- Do not add a missing `doi` field just because you found one; mention it in `notes` if useful.109- If a standard field is genuinely unavailable, say so in `notes`.110111## Preserve112113- Entry order114- All unchanged fields115- Empty lines between entries116- User `%` comments that are not `% bibtidy:`117- `@string`, `@preamble`, and `@comment` blocks118- LaTeX macros and brace-protected capitalization in titles119120If rate-limited, note it and continue with the next entry.