bxc (Bibliographic Reference Formatter)
A lightweight Python library and Command Line Interface (CLI) tool designed to format BibTeX bibliography records into academic styles (like IEEE, ABNT, ACM) using Citation Style Language (CSL). It natively outputs to Markdown, HTML, and Plain Text, making it perfect for static blogs, documentation websites, and automated citation pipelines.
Key Features
- Zero-Configuration UX: Automatically resolves, downloads, and caches standard academic styles (e.g.,
ieee,nature,abnt) on demand from the official CSL repositories. - Offline-First Style Resolution: Ships with a bundled, compressed snapshot of the entire CSL styles repository (10,000+ styles, ~2 MB). Style lookups check this local archive before ever touching the network, so
bxc formatworks instantly and fully offline for any standard style - the CDN is only used for brand-new styles not yet in the bundle, or when explicitly syncing (bxc cache update/bxc cache rebuild). - LaTeX to Unicode Normalization: Seamlessly cleans and converts LaTeX accent escape codes (like
{\e},\c{c}) to standard Unicode (e.g.,è,ç`) prior to formatting. - Multiple Output Targets: Renders styled reference lists natively to Markdown, HTML, and Plain Text.
- Local Cross-Platform Caching: Caches downloaded styles locally according to OS-native standards (
~/.cache/bxc/on Linux,~/Library/Caches/bxc/on macOS,%LOCALAPPDATA%\\bxc\\Cacheon Windows; runbxc cache statusto see yours). - Flexible Interface: Use it as a terminal CLI tool or import it as a standard Python library.
Installation
Requires Python 3.11 or newer.
pip / pipx (any platform):
pipx install bxc # or: pip install bxc
bxc works with bibtexparser 1.4.3+ and 2.x: pip installs the newest one, and an application that already depends on either major can install bxc next to it. The two give the same result: bxc reads values itself (macros, # concatenation, quoting, multi-line text), skips the same malformed entries and decodes LaTeX with the same code on both. One known difference: bibtexparser 2.x does not accept whitespace between the @ and the entry type (@ article{...}), so such an entry is rejected with a parse error there.
Native installers are attached to each release on the project page, with a SHA256SUMS file to verify them:
| Platform | Package | Install |
|---|---|---|
| Debian 12+, Ubuntu 24.04+ | bxc_<version>_all.deb |
sudo apt install ./bxc_<version>_all.deb |
| Fedora 40+, RHEL / AlmaLinux 10+ | bxc-<version>-1.noarch.rpm |
sudo dnf install ./bxc-<version>-1.noarch.rpm |
| Windows 10+ (x64) | bxc-<version>-x64.msi |
double-click, or msiexec /i bxc-<version>-x64.msi |
The deb and rpm bundle bxc's pure-Python dependencies and use your distribution's python3 and python3-lxml; the package manager installs them for you. They need Python 3.11+, so older distributions (Ubuntu 22.04, RHEL 9) should use pipx with a newer Python instead. The Windows installer is self-contained (it ships its own Python) and adds bxc to the system PATH; it is not code-signed, so Windows SmartScreen may warn on first run. Open a new terminal after installing.
Quick Start
Command Line Interface (CLI)
Format a .bib file to Markdown using IEEE style:
bxc format citations.bib --style ieee --output markdown
Search for a citation style:
bxc search "ABNT"
Clear, sync, or inspect the local cache:
bxc cache update # refresh the style search index from the CDN
bxc cache rebuild # re-download every cached style from the CDN (sync with CDN)
bxc cache status # show cache location and stats
bxc cache clear # remove all cached styles and the index
bxc cache update and bxc cache rebuild are the commands that talk to the CDN on purpose - they're how you get styles fresher than the bundled snapshot. Everyday bxc format calls never need them: they resolve styles from the bundled local archive first (see Offline-First Style Resolution above), which is why bxc works out of the box without a network connection.
Maintainers can refresh that bundled archive itself (a periodic task, not something end users run) with:
python build_styles_bundle.py
Offline mode
Style lookup is already offline-first, but a style that is not in the bundle makes bxc try the network. To forbid that completely, pass offline=True, use bxc --offline ..., or set BXC_OFFLINE=1 (also true, yes, on):
bxc.format_bibtex(source, style="ieee", offline=True)
Offline, styles come from the bundle, the local cache or a local .csl path. A style that is none of these raises StyleNotFoundError ("... is not in the bundled styles or the local cache, and offline mode is on") without any connection attempt; bxc cache update and bxc cache rebuild refuse to run; bxc search uses the bundled index. An explicit offline=True/False argument wins over the variable.
Network safety
Remote styles and the style index are downloaded over https by default. A private mirror set with BXC_REMOTE_URL may still use http or ftp (it works, with a warning unless the host is loopback), or file: for a local folder. A download is refused if it is larger than 5 MB (20 MB for the index), if an https request is redirected to a non-https URL, or if it is not a CSL style (well-formed XML with a <style> root), so a bad response is never cached. Style files you pass by path are limited to 5 MB and BibTeX input to 100 MB. New cache directories are created readable only by you.
Using bxc without side effects
By default a style is written to the per-user cache on first use. To keep a call free of filesystem writes (unit tests, read-only or sandboxed environments, a library embedded in another tool), pass cache=False or set BXC_CACHE=off:
bxc.format_bibtex(source, style="ieee", cache=False) # nothing is written; the style is read from the bundle
With caching off, the style comes from an existing cache file, the bundled styles, or (for a style not in the bundle) the remote, and is kept in memory. BXC_CACHE=off (also 0, false, no) does the same without changing code and also stops bxc search from writing the style index; an explicit cache=True/False argument wins over the variable. If the cache directory cannot be created or written, a normal call falls back to the same in-memory path instead of failing.
Bundling with PyInstaller
bxc works inside PyInstaller apps (one-dir and one-file) with no extra options: it registers a PyInstaller hook through the pyinstaller40 entry point, which adds the bundled style snapshot and style index, and the locale and schema data of its citeproc-py dependency (PyInstaller does not collect package data files on its own, so without this a frozen app fails at start). Install bxc into the environment you freeze from, then:
pyinstaller --onefile myapp.py
If your build does not pick up installed hooks, add --collect-data bxc --collect-data citeproc. For a frozen app that must never touch the network or the disk, use offline=True, cache=False (see above). packaging/frozen_smoke.py is the script CI freezes and runs with every network call blocked; it is a good starting point for your own check. Verified on Linux with PyInstaller 6; the Windows build is expected to work the same way but is not covered by CI.
Python API
import bxc
# Parses, converts LaTeX escapes, fetches CSL, and formats citation
markdown_ref = bxc.format_bibtex(
bibtex_source="@article{smith2026, ...}",
style="ieee",
output_format="markdown"
)
print(markdown_ref)
CLI reference
bxc format [BIB] --style STYLE [--output plain|markdown|html] [--mode bibliography|citation] [--cite KEYS] [--out-file PATH]
BIB(or--bib/-b): path to a.bibfile; use-to read from stdin.--style/-s: a CSL style name (e.g.ieee,apa) or the path to a local.cslfile.--cite/-c: comma-separated citation keys to format.- Exit codes:
0success,1error (parse failure, style not found, ...),2invalid usage,130interrupted.
bxc search [QUERY] [--category CATEGORY] searches the style registry; bxc cache {status,update,rebuild,clear} manages the local cache.
Public API and versioning
bxc follows Semantic Versioning: a major release may break the public API, a minor release only adds to it, and a patch release only fixes bugs.
What is public (covered by that promise):
bxc.format_bibtexbxc.parse_bibtexbxc.search_stylesbxc.resolve_stylebxc.get_cache_dirbxc.get_cache_statusbxc.update_cachebxc.rebuild_cachebxc.clear_cachebxc.BxcErrorbxc.BibTeXParseErrorbxc.StyleNotFoundError
Also public: the bxc command-line interface (subcommands, options and the exit codes above) and the environment variables BXC_CACHE_DIR, BXC_REMOTE_URL, BXC_CACHE and BXC_OFFLINE. BibTeXParseError and StyleNotFoundError are subclasses of BxcError; parse_bibtex returns a list of dicts with the keys ID and ENTRYTYPE plus one lower-case key per BibTeX field.
What is not public: anything not listed above, including every submodule (bxc.cache, bxc.formatter, bxc.parser, bxc.latex, bxc.author, bxc.registry) and its classes, helpers and constants, the visited argument of resolve_style, and the layout and file names of the bundled style data. Do not import from them; they can change in any release. The exact text a style renders is not byte-stable either: bug fixes and updated bundled styles can change it in a minor or patch release.
Breaking changes (major release only): removing or renaming a public name; removing a parameter, changing the order of positional parameters or making an optional one required; changing what an existing call returns or which exception it raises; removing or changing the meaning of a command-line option, exit code or environment variable; raising the minimum Python version; dropping support for a supported major version of a dependency (for example bibtexparser 1.x).
Not breaking (minor or patch release): new functions, new optional parameters, new subcommands, options and environment variables, new BxcError subclasses, supporting more Python or dependency versions, bug fixes, and internal changes. Optional parameters added after 1.1.0 are keyword-only, so adding more never changes how an existing call is written.
Deprecation: something public is first marked deprecated (a DeprecationWarning and a note under "Deprecated" in the changelog) for at least one minor release before it is removed in the next major release.
License
Apache License 2.0. The bundled CSL styles are from the Citation Style Language styles repository and are licensed under CC BY-SA 3.0; see NOTICE.
Metadata
Release files for bxc 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| bxc-1.2.0.tar.gz | 2.4 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bxc-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 4.8 MB
Release files / bxc-1.2.0.tar.gz
| Download URL | bxc-1.2.0.tar.gz |
|---|---|
| Size | 2.4 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e11c2062382a41b86d1fbdc1e276324ee6794b71c8fe698f40c2612d4f6f712c
|
|
BLAKE2b-256 checksum How to use checksums |
6b947e4f5e3e869b6209fcd7758fe6a93d2bca223427bda9c8385e424021ab97
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|
Release files / bxc-1.2.0-py3-none-any.whl
| Download URL | bxc-1.2.0-py3-none-any.whl |
|---|---|
| Size | 2.4 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cc74cecaf9ba97eb0d5434cd25cb4f4433a4beb94377c1bce6acb382ddfb98c4
|
|
BLAKE2b-256 checksum How to use checksums |
c758a0440e40000063ff08a4caea27254160dd617eeee9f4a85e82fdb1609406
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.14
|