Directory macros/latex/contrib/inspirehep
inspirehep-latex
Live INSPIRE-HEP citation counts, titles, references, and plots in LaTeX — for a CV, a proposal, or a paper.
Quick start
1. Put two files beside your .tex file.
BASE=https://raw.githubusercontent.com/lawrenceleejr/inspirehep-latex/main curl -O $BASE/inspirehep.sty # the package itself curl -O $BASE/inspirehep-fetch.py # what it runs to fetch (standard library only)
2. Load the package.
\usepackage{inspirehep}
3. Ask for something. Every command takes an INSPIRE id — either the number from the record's URL (inspirehep.net/literature/1701002) or its texkey (Lee:2018pag). The package tells the two apart by shape.
\inspirepub{1701002}
4. Compile twice, with -shell-escape.
pdflatex -shell-escape mydoc.tex pdflatex -shell-escape mydoc.tex
Collider Searches for Long-Lived Particles Beyond the Standard Model 245 citations
The first pass notices what the document asks for and fetches it; the second typesets it — the same two-pass shape as a table of contents, cross-references, or a bibliography. -shell-escape is what lets the package run the fetcher for you; without it LaTeX may not start another program.
After that the figures live in a generated file beside your document, so it compiles anywhere — offline, on a colleague's machine, with no -shell-escape at all. Nothing needs refetching until you want the numbers brought up to date.
If you cannot use -shell-escape
Overleaf disables it, and so do some locked-down TeX installations. Run the fetcher yourself, then compile normally — it writes the same file, so the document cannot tell the difference:
python3 inspirehep-fetch.py mydoc.tex pdflatex mydoc.tex
On Overleaf, where you cannot run it at all, see Overleaf below.
What you can ask for
A paper
\inspirepub is the one from step 3 — the title comes from INSPIRE, and the citation count follows it. Options choose what else appears: year adds the publication year, and title= supplies your own wording instead of INSPIRE's:
\inspirepub[year]{2642414} \inspirepub[title={A title in my own words}]{2642414}
Towards a muon collider 407 citations
>
A title in my own words 407 citations
For a full reference, as INSPIRE itself formats it:
\inspireref[cites=false]{1701002}
L. Lee, C. Ohm, A. Soffer and T. T. Yu, "Collider Searches for Long-Lived
Particles Beyond the Standard Model," Prog. Part. Nucl. Phys. 106 (2019),
210-255 doi:10.1016/j.ppnp.2019.02.006 arXiv:1810.12602 hep-ph.
Each piece is also a command of its own: \inspiretitle, \inspirecites, \inspireyear, \inspirekey.
A person
Author commands take the id of the person they ask about, so one document can discuss several:
Over \inspirepapers[round=100]{1071846} papers, over \inspirecitations[round=1000]{1071846} citations, $h$-index \inspirehindex{1071846}.
Over 1,400 papers, over 207,000 citations, h-index 211.
round= rounds down, so a claim of "over N" stays true as the real figure grows.
Citing a paper
\inspirecite is \cite by INSPIRE id. The fetcher collects INSPIRE's own BibTeX entry for everything you cite into inspirehep-refs.bib, so you never handle a citation key:
as shown in \inspirecite{1701002} ... \bibliographystyle{unsrt} \bibliography{inspirehep-refs}
as shown in 1
>
1 Lawrence Lee, Christian Ohm, Abner Soffer, and Tien-Tien Yu. Collider
Searches for Long-Lived Particles Beyond the Standard Model. Prog. Part.
Nucl. Phys., 106:210–255, 2019.
Run bibtex between the two pdflatex passes, as you would for any bibliography. The .bib file is written by the fetch, so it needs no editing — and \inspirekey{<id>} hands you the key if something else wants it.
A plot
Load with the plots option — it pulls in pgfplots, which a document that never plots should not pay for:
\usepackage[plots]{inspirehep} ... \inspireauthorplot{1071846}{citations}

{papers} instead of {citations} plots output rather than impact, and \inspireplot{<id>} is one paper's citation history. The style is deliberately spare — one line, axis lines only where they carry information, no grid, box, marks, or legend — and \inspireplotstyle takes any pgfplots axis keys if you want otherwise.
Install, other ways
Step 1 above is the whole package: inspirehep.sty is all LaTeX needs, and everything else in this repository is documentation, an example, and that helper. inspirehep.sty can equally live anywhere in your TEXINPUTS.
To track the package from a document's own repository, carry it as a submodule and point TEXINPUTS at it from your build script:
git submodule add https://github.com/lawrenceleejr/inspirehep-latex export TEXINPUTS=".:inspirehep-latex:${TEXINPUTS:-}"
That value ends in an empty entry, which is what keeps TeX searching its own trees as well; without it the package would be the only thing it could find.
Keep \usepackage{inspirehep} unqualified rather than writing the submodule path into it. The bare name resolves through TEXINPUTS locally and also finds the file when it sits beside the sources, which is what Overleaf needs — its Git sync does not fetch submodules, so there you upload inspirehep.sty to the project root. A path-qualified \usepackage finds neither, and warns that the name it was given is not the name the package provides.
Getting the numbers
The figures come from inspirehep-data.tex. There are two ways to produce it, and they write the same file — use whichever suits your setup.
Let the package do it. With unrestricted shell escape (and python3 on the path), the package refreshes at the end of the run and writes the file itself:
pdflatex -shell-escape cv.tex # fetches, writes inspirehep-data.tex pdflatex -shell-escape cv.tex # numbers appear
Two passes the first time, like a cross-reference. After that it only refetches when there is a reason: a publication you just added, or figures older than maxage. Commit inspirehep-data.tex and everyone else can compile normally.
Or run the helper. If you cannot enable shell escape — a locked-down machine, a CI policy, Overleaf — inspirehep-fetch.py does the same job from outside the compile. It needs only the Python standard library:
python3 inspirehep-fetch.py # writes inspirehep-data.tex
It finds your records and your author id by reading your sources, so it takes no arguments in the common case.
Overleaf
Overleaf disables shell escape and its compile containers have no network, so nothing can fetch there — but the CV renders correct numbers, because they are just an \input file. Two ways to keep that file current:
- Linked file. Upload
inspirehep.sty, then addinspirehep-data.texwith Add file → From external URL, pointed at the raw URL of the file in your CV's repository. Overleaf gives linked files a Refresh button, so you can pull fresh numbers without leaving the editor. Keep the repository copy current from CI or a local run, and refreshing is one click. - GitHub sync. If your project is linked to a repository, pull as usual. Note that Overleaf's sync does not fetch git submodules, so include
inspirehep.styas a file rather than a submodule.
Setting fetch=off on Overleaf silences the machinery entirely, though auto already degrades to exactly the same behaviour.
Commands
Records. Name a record either by its recid — the number in the INSPIRE URL, inspirehep.net/literature/2642414 — or by its INSPIRE texkey, Accettura:2023ked. Every command takes either; they are told apart by shape, so nothing has to be declared, and both link to the record by number.
\inspirepub{2642414} % by recid \inspirepub{Accettura:2023ked} % the same paper, by texkey
| Command | Result |
|---|---|
\inspirepub[<opts>]{<id>} |
the entry: title (fetched), linked, with its citation count |
\inspiretitle{<id>} |
the title alone |
\inspireref[<opts>]{<id>} |
the full reference, exactly as INSPIRE formats it |
\inspirecites{<id>} |
the citation count alone |
\inspireyear{<id>} |
the publication year |
\inspirekey{<id>} |
the BibTeX key |
\inspirecite{<id>} |
\cite with that key |
\inspireplot[<opts>]{<id>} |
citations per year, as a line |
\inspirepub takes options for exactly what it shows:
\inspirepub{2642414} % title + count \inspirepub[year]{2642414} % ... and the year \inspirepub[ref]{2642414} % the full reference instead of the title \inspirepub[cites=false]{2642414} % no count \inspirepub[link=false]{2642414} % no hyperlink \inspirepub[title={My own words}]{2642414} % your title, INSPIRE's count
People. The id is the number in a profile URL, inspirehep.net/authors/1071846, or a BAI such as J.Smith.1.
| Command | Result | |
|---|---|---|
\inspirepapers[<opts>]{<id>} |
publication count | |
\inspirecitations[<opts>]{<id>} |
citation count | |
\inspirehindex[<opts>]{<id>} |
h-index | |
\inspireauthorstat[<opts>]{<id>}{<key>} |
any of the three by name | |
\inspireauthorplot[<opts>]{<id>}{papers\ |
citations} |
that quantity per year, as a line |
All take round=<n> to round down to a multiple of n.
BibTeX. \inspirecite{<id>} cites by INSPIRE id: the fetcher writes inspirehep-refs.bib containing INSPIRE's own BibTeX entries for every record you cite, and \inspirecite expands to \cite{} with the right key. You never handle a BibTeX key yourself.
\bibliography{inspirehep-refs} ... as shown in \inspirecite{1701002}.
Fallback figures
Values used only until a real fetch arrives — handy for a repository's first build, and never overriding fetched data:
\inspiredefaultauthorstat{1071846}{papers}{1467} % per person \inspiredefaultstat{papers}{1467} % the helper's --author
Options
Every option is both a package option and a per-call option, so a document sets house style once and any one entry can depart from it.
| Option | Default | Meaning |
|---|---|---|
cites |
true |
show the citation count |
ref |
false |
show the full reference instead of the title |
year |
false |
append the publication year |
errata |
false |
include any erratum in a reference |
collab |
false |
credit a collaboration paper to the collaboration rather than its first author |
link |
true |
hyperlink the title |
title |
(none) | override the fetched title |
round |
1 |
round a figure down to a multiple of this |
sep |
comma |
thousands separator: comma, period, space, thin, underscore, none, or sepstring={...} for anything else |
style |
latex-eu |
INSPIRE reference format: latex-eu or latex-us |
plots |
false |
load pgfplots, needed for the plotting commands |
data |
inspirehep-data |
basename of the generated file |
bib |
inspirehep-refs |
basename of the generated .bib |
maxage |
120 |
days before the data is called stale; 0 never warns |
mincites |
1 |
counts below this print nothing |
script |
inspirehep-fetch.py |
where the self-fetch finds the helper (a submodule path, say) |
fetch |
auto |
auto, on, or off |
\inspiresetup{<options>} changes any of them mid-document.
Changing how it looks
Three hooks, each redefinable:
\renewcommand{\inspiretitleformat}[1]{\textbf{#1}} % the title \renewcommand{\inspirecitestext}[1]{#1~cites} % the words \renewcommand{\inspirecitesformat}[1]{\nobreakspace{\small[#1]}} % the wrapper \renewcommand{\inspireyearformat}[1]{\hfill #1} % the year \renewcommand{\inspireplotstyle}{ymajorgrids, blue} % plot axis keys \renewcommand{\inspireplotwidth}{10cm} \renewcommand{\inspireplotheight}{3cm}
To set the annotation in a muted grey, for instance:
\usepackage{xcolor} \definecolor{citegrey}{gray}{0.40} \renewcommand{\inspirecitesformat}[1]{\nobreakspace{\small\color{citegrey}[#1]}}
\inspirepub links through hyperref when your document loads it, and falls back to plain text when it does not, so load order does not matter.
How it works, and what it does not do
The package asks INSPIRE for four things: each record's metadata (title, citation count, BibTeX key), its reference as INSPIRE's own renderer formats it (?format=latex-eu or latex-us), its BibTeX entry verbatim (?format=bibtex), and the earliest_date facet for anything plotted. Author figures use the same citation-summary aggregation as INSPIRE's profile pages, so the numbers match what a reader sees there.
All of that lives in inspirehep-fetch.py. When the package refreshes itself through shell escape it runs that same helper, so there is exactly one implementation of the API handling rather than two that can disagree.
Known limits:
- Refreshing needs
python3(standard library only); the self-fetch additionally needs unrestricted shell escape. Neither is needed to typeset. - Both fetchers follow
\input,\include, and\subfilefrom the main file, resolving names as LaTeX does (relative to the main document) and then relative to the including file, assubfilesandimportdo.--no-followscans only the files named. - One unknown id degrades on its own: a warning, a visible
[? ...]marker in the output, and the rest of the document still refreshes. - Counts are whatever INSPIRE reports, including self-citations.
Developing
make check # everything CI runs: lint, unit, test, doc make lint # ruff, plus the checks a compiler cannot make make unit # the helper's pure parts -- no network, runs in a second make test # build the example and look for the numbers in the PDF make doc # the manual, as inspirehep.pdf make ctan # the archive to upload to CTAN
make unit is the one to run while editing: it covers the patterns that find records in a document, the \input walking, the TeX escaping, and the shape of the generated file, none of which touch the network.
make lint additionally asserts what a compiler cannot see — that every public command and option reached the manual, that inspirehep.sty and the Makefile agree on the version, and that a handful of traps this package has actually fallen into stay fixed (an unbalanced \ExplSyntaxOn, a colon used as a separator in a data file, pgfplots escaping its option).
CI runs all of it on every push, on three Python versions, and weekly so that a change at INSPIRE's end shows up here rather than in someone's document. Tagging vX.Y — matching the version in inspirehep.sty — builds the CTAN archive, checks its layout, and drafts a release with it attached.
Licence
LPPL 1.3c. See LICENSE.
Download the contents of this package in one zip archive (204.8k).
INSPIRE-HEP – An INSPIREHEP × LaTeX interface for automatic reference management
Live INSPIRE-HEP citation counts, titles, references, and plots in LaTeX – for a CV, a proposal, or a paper.
| Package | INSPIRE-HEP |
| Support | |
| Bug tracker | |
| Repository | |
| Version | 0.2 |
| Licenses | The LaTeX Project Public License 1.3c |
| Copyright | 2026 Lawrence Lee |
| Maintainer | Lawrence Lee |
| Contained in | TeX Live as inspirehep |
| Topics | External code Generate BibTeX CV Physics |