Badness 
Badness is a language server, formatter, and linter for LaTeX. It is designed to be fast, robust, and memory efficient. It bundles three tools in one:
- Formatter (
badness format): opinionated, deterministic, and rule-based layout. - Linter (
badness lint): syntax errors and best practices. - Language server (
badness lsp): both of the above, plus information on hovering, symbol outlines, go-to-definitions, code actions, and much more.
The architecture is modeled after rust-analyzer, relying on a incremental parser that forms a full concrete syntax tree of the document, and then using that tree to provide formatting, linting, and language server features. It is designed to used both inside your editor and on the command line, and is fast enough to provide real-time analysis after every keystroke and formatting on save, even for large documents and complex projects.
The audience for Badness is both authors who write LaTeX documents (.tex and
.bib files) and developers who write LaTeX packages (.sty, .cls, .dtx,
and .ins files), and provides support both for the newer LaTeX3 programming
layer and the older LaTeX2e layer.
Installation
Badness is available from several sources:
- crates.io:
cargo install badness - Homebrew:
brew install jolars/tap/badness - npm:
npm install -g badness(bundles a prebuilt binary) - PyPI:
uv tool install badness/pipx install badness - Aqua:
aqua install jolars/badness - Prebuilt binaries: from the releases page
- VS Code/Open VSX: the Badness extension (also works in Positron and Cursor)
- NixOS: the
badnesspackage on Nixpkgs - From source:
cargo install --path .in a checkout
Install Script
The installer scripts pick the right release artifact for your platform and install to a user-local directory by default. They download the matching Badness CLI release asset and verify its checksum. If you prefer, download and inspect the script before running it.
For macOS and Linux:
curl --proto '=https' --tlsv1.2 -sSf https://badness.dev/install | sh
For Windows PowerShell:
powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://badness.dev/install.ps1 | iex"
The VS Code/Open VSX extension bundles the badness binary and starts the
language server automatically when you open a supported LaTeX or BibTeX file:
.tex, .sty, .cls, .dtx, .ins, or .bib.
Usage
# Format a file in place (or `badness format -` for stdin → stdout)
badness format paper.tex
# Verify formatting without writing, showing diffs
badness format --check bibliography.bib
# Lint, reporting parse diagnostics
badness lint paper.tex
# Fix lint issues in place
badness lint --fix paper.tex
Formatting is configurable via a TOML file named badness.toml. See the
documentation for the full reference.
Editor Integration
The language server runs over stdio (badness lsp); see the editor setup
guide for instructions on how to
integrate with your editor.
Pre-Commit Hook
badness-pre-commit provides pre-commit hooks for linting and formatting. It installs a prebuilt binary wheel from PyPI, so no Rust toolchain or LaTeX distribution is required:
repos:
- repo: https://github.com/jolars/badness-pre-commit
# badness version
rev: v0.11.0
hooks:
# Lint .tex, .sty, .cls, .dtx, .ins, and .bib files
- id: badness-lint
# Format the same files in place
- id: badness-format
GitHub Actions
badness-action installs badness and runs format and lint checks in CI:
jobs:
badness:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: jolars/badness-action@v1
Documentation
See https://badness.dev/ for the full documentation, including a user guide, reference, and developer guide.
Contributing
See CONTRIBUTING.md.
Funding
I am grateful for the financial support offered by the TeX Users Group through the TeX Development Fund.
License
Metadata
Release files for badness 0.26.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 | |
|---|---|---|---|
| badness-0.26.0.tar.gz | 1.3 MB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| badness-0.26.0-py3-none-win_arm64.whl | Python 3 | none | Windows ARM64 | Details |
| badness-0.26.0-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| badness-0.26.0-py3-none-musllinux_1_2_x86_64.whl | Python 3 | none | Linux musl 1.2+ x86-64 | Details |
| badness-0.26.0-py3-none-musllinux_1_2_aarch64.whl | Python 3 | none | Linux musl 1.2+ ARM64 | Details |
| badness-0.26.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
| badness-0.26.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | Python 3 | none | Linux glibc 2.17+ ARM64 | Details |
| badness-0.26.0-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
| badness-0.26.0-py3-none-macosx_10_12_x86_64.whl | Python 3 | none | macOS 10.12+ x86-64 | Details |
Total release size: 33.6 MB
Release files / badness-0.26.0.tar.gz
| Download URL | badness-0.26.0.tar.gz |
|---|---|
| Size | 1.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
63f938173933cbc0c2fbc6c0754b3765562d14ec762a7551e4c29dec1a7908c6
|
|
BLAKE2b-256 checksum How to use checksums |
efd6a57efda2d33b255c8bd23cf75b923325ddda97f1961c79d548c13e4e648d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / badness-0.26.0-py3-none-win_arm64.whl
| Download URL | badness-0.26.0-py3-none-win_arm64.whl |
|---|---|
| Size | 3.9 MB |
| Tags | Python 3 Windows ARM64 |
|
SHA-256 checksum How to use checksums |
4dd268f800d8a874b509b075c6f27b747697725afc7e9fa2ba5a37d012e36150
|
|
BLAKE2b-256 checksum How to use checksums |
4950459ad612d1e61ae5278a7ac4831a72d93c9e4cb8baf0958807898db04756
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / badness-0.26.0-py3-none-win_amd64.whl
| Download URL | badness-0.26.0-py3-none-win_amd64.whl |
|---|---|
| Size | 4.3 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
97471dd24f4d0dac18ca296ae0ecc1da680b538660206c7f605a7413ca6ca544
|
|
BLAKE2b-256 checksum How to use checksums |
c2b064b88331de026313ffd67625ac4b29dc7d522d4a1433101a88653b4d7ee6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / badness-0.26.0-py3-none-musllinux_1_2_x86_64.whl
| Download URL | badness-0.26.0-py3-none-musllinux_1_2_x86_64.whl |
|---|---|
| Size | 4.3 MB |
| Tags | Linux musl 1.2+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
6a984159ea2a21d793878551ee94468414c8ba4f260d47325f4a313f7e48b2a1
|
|
BLAKE2b-256 checksum How to use checksums |
3886d6dc56493c674f9ff8dff869d0836c691ad358ffa15b1d9a4f7d79e04832
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / badness-0.26.0-py3-none-musllinux_1_2_aarch64.whl
| Download URL | badness-0.26.0-py3-none-musllinux_1_2_aarch64.whl |
|---|---|
| Size | 3.8 MB |
| Tags | Linux musl 1.2+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
72b2a82bf2d96792d7e192258b84bd959e59b4b6651e017613fd1d4dbd29edad
|
|
BLAKE2b-256 checksum How to use checksums |
b8f80ecd884dc7333b9277d834aff61f58169a49654f70a6242b34b8b711f1f1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / badness-0.26.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | badness-0.26.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 4.2 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
2c6416c031f963c9f53ed6e7f6e48f2f9f5ad8a0946f6e1a13f1c23e361ce100
|
|
BLAKE2b-256 checksum How to use checksums |
2f6fecafc5bc1e43be7b3328c60b8a00d640287f7674c0c5d61524fe2258d151
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / badness-0.26.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | badness-0.26.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 4.0 MB |
| Tags | Linux glibc 2.17+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
ef3f465f20ff0dd9092a867ae40bd481e30bb6e51e44be254b39787cadc9538f
|
|
BLAKE2b-256 checksum How to use checksums |
dea519a14471e2f5d048b8fbccc7737185dca72d6c66f4819dd02d1ffc77d974
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / badness-0.26.0-py3-none-macosx_11_0_arm64.whl
| Download URL | badness-0.26.0-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 3.8 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
3a83e9472988114ce25b76f057b50b07eb340cd7ba728bb5681e0bbc4ccc7f0f
|
|
BLAKE2b-256 checksum How to use checksums |
207c0630b42ffcf3f349a30d05d304446a0ddcf6dba144e234e184e5d550642e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / badness-0.26.0-py3-none-macosx_10_12_x86_64.whl
| Download URL | badness-0.26.0-py3-none-macosx_10_12_x86_64.whl |
|---|---|
| Size | 4.0 MB |
| Tags | Python 3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
91f3baaa7c0e9ecd8521cd14f8cec241cac37f701c43c06c38e0ac1caf38ab03
|
|
BLAKE2b-256 checksum How to use checksums |
914443e14416df3d90aecd405c7dac979802372add21b95fd768eaff0a73e8a6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency log