doi2bib (Version 2.0.0 as of 6 October (2026)) is a perl and jq script to generate the bibTeX entry, according to my own standard and with my own conventions, from the doi of a scientific reference.
More details on the script (including the genesis of its creation) can be found in this blog post.
Pass a valid doi to the script.
doi2bib 10.1103/PhysRevLett.80.3483
The above example returns:
@Article{saleh98a,
author = {B. E. A. Saleh and B. M. Jost and H.-B. Fei and M. C. Teich},
title = {Entangled-photon virtual-state spectroscopy},
journal = prl,
year = 1998,
volume = 80,
pages = 3483,
pdf = {sci/saleh98a},
url = {doi:10.1103/physrevlett.80.3483}
}
You may have to put the doi between quotes if there are escape characters:
doi2bib "10.1016/0030-4018(91)90618-N"
The flags, which may be written on either side of the doi:
doi2bib DOI # show the entry, write nothing
doi2bib -w DOI # write it, at its alphabetical place in sci.bib
doi2bib -a DOI # -w, then push Template:<Key> with bib2wiki -force
doi2bib -f DOI # do it anyway: a doi already on file is fetched again and
# rewritten in place, under the key it is cited by
doi2bib -a -f KEY # an entry knows its own doi, so its key is the short way
# of saying redo this one
doi2bib -d KEY ... # delete the entry (entries) with that key
doi2bib -j DOI # do not ask about an unknown journal, take the key proposed
doi2bib -t "TITLE" # what a title becomes, writing nothing; -t alone reads titles from stdin
doi2bib -h # this list
Since 9 August (2026), the whole journey of a new paper is three commands:
doi2bib -a 10.1103/... # the sci.bib entry + Template:<Key> on the local wiki
llw2lw --doit # the template reaches laussy.org
bib2wiki -uo # [[Scientific articles]] online, rebuilt now
The third command is only for impatience: the lists on both wikis otherwise refresh themselves at the daily lw-warm cron. A re-push of an existing key (doi2bib -a key) goes through bib2wiki -force, which since v4.0 keeps whatever {{pdf|File:...}} link the template already carries.
Of all the fields in an entry, the journal is the only one not written as it arrives. It has to be a bare @string key that sci.bib defines -- journal = prl, not journal = {Phys. Rev. Lett.} -- and the name the publisher sends is turned into that key by iso4, a sed script run over it twice.
When iso4 has no rule for a journal there is nothing to fall back on, and until 11 September (2026) the name went in raw. journal = J. Phys. F: Met. Phys., is not BibTeX at all: bibtex stops on it, skips the remainder of the entry, and the year, the volume and the pages go with it, while the template built from that entry renders an empty [[]] because an undefined string resolves to nothing and bib2wiki sends its own warnings to /dev/null.
doi2bib now checks, on every path, that the journal is a key and that sci.bib defines it, and offers j2bib for what it cannot resolve. That offer is made on a plain look-up too, since that is the moment one finds out; accepting it writes the iso4 rule and the @string line, never an entry, and only ever after showing both. Decline it, or be somewhere the question cannot be asked, and the name is written in braces, which bibtex at least accepts, with the j2bib line to run printed underneath. -j takes the proposed key without asking.
Since v°2.0.0 (6 October (2026)), the names and the title are written in the conventions of sci.bib rather than as the publisher sends them.
Every word of a given name gives an initial. Until then the given name was split on hyphens only, so CrossRef's T. B. came out as T.: Demonstration of nondeterministic quantum logic operations using linear optical elements. T. B. Pittman, B. C. Jacobs and J. D. Franson in Phys. Rev. Lett. 88:257902 (2002). had lost its middle initials, and so had 424 other entries, all mended the same day from CrossRef. A family name of two capitalised words is braced, J. C. {L\'opez Carre{\~n}o}, otherwise bibTeX takes its first word for a given name; a particle stays outside, E. del Valle. An accented initial is one braced character, {\'A}.: the style cuts a raw Ă. in the middle of its UTF-8 bytes, which stops LaTeX.
Titles are in sentence case with the names and acronyms bracedâClimbing the {Jaynes--Cummings} ladder and observing its $\sqrt{n}$ nonlinearity in a cavity {QED} systemâbecause naturemag.bst lowercases whatever is not braced: an unbraced QED prints as "qed". A Title Case title, as APS sends them, is brought down word by word, the titles already in sci.bib, its author surnames and the system dictionary deciding which words are names; a word that none of them knows is kept capitalised, braced, and named on the terminal. MathML in a title becomes TeX in the style of the file, {MgF$_{2}$} or {$N$}-photon, and a bare % is escaped (one of them, in Detecting telecom single photons with $99.5^{+0.5}_{-2.07}$% system detection efficiency and high time resolution. J. Chang, J. W. N. Los, J. O. Tenorio-Pearl, N. Noordzij, R. Gourgues, A. Guardiani, J. R. Zichi, S. F. Pereira, H. P. Urbach, V. Zwiller, S. N. Dorenbos and I. Esmaeil Zadeh in APL Photon. 6:036114 (2021)., cut every bibliography short at that entry). doi2bib -t shows what a title becomes without fetching anything; it was run over every title of sci.bib, which now goes through bibtex and LaTeX whole without a single error.
A page or a volume that is not a plain number (L061701, e1501143) is braced: bare, bibtex read it as an undefined @string and printed nothing.
curl -LH "Accept: application/json" "http://dx.doi.org/10.48550/arXiv.2305.15827"
Copy the chmod +x script in the local bin directory. Two additional files should be put somewhere, as defined by
(in my case, these files are in ~/bib/doi2bib/).