Skip to main content

toml-tidy

Sort TOML keys while preserving table hierarchy and source formatting where tomlkit supports it.

Install

Install from PyPI:

pip install toml-tidy

Or as a standalone tool with uv:

uv tool install toml-tidy

Or run it once without installing:

uvx toml-tidy pyproject.toml

For development from a local checkout, use uv tool install ..

Usage

toml-tidy pyproject.toml
toml-tidy pyproject.toml --check
toml-tidy pyproject.toml --in-place --order natural
toml-tidy config/*.toml --in-place --scope tables

The command accepts one or more file paths and processes each one, so it works directly as a pre-commit or trunk formatter target.

Without --in-place, sorted TOML is written to standard output; this mode takes exactly one path so separate documents never get concatenated.

--check writes nothing and exits with status 1 when any file requires sorting.

--in-place rewrites each file only when sorting changes it.

With multiple paths the worst exit code wins: 2 for any error, else 1 for any check difference, else 0; an error in one file does not stop the remaining files.

--scope limits what gets sorted: all (default) sorts everything, tables sorts only sibling table declarations, and keys sorts only direct key-value entries.

--blank-lines additionally normalizes blank lines to exactly one before every table header and none anywhere else; --no-blank-lines (the default) leaves every blank line where it was.

Configuration

Defaults can be set in the nearest pyproject.toml found walking up from each target file, under [tool.toml-tidy]. CLI flags always override the configuration.

[tool.toml-tidy]
order = "natural"   # or "alpha"
scope = "all"       # "tables" | "keys"
first = ["project", "build-system"]
blank-lines = false # true normalizes blank lines

first pins top-level entries by name, in the listed order, ahead of their sorted siblings; it never applies inside nested tables, and it has no CLI flag.

pre-commit

repos:
  - repo: https://github.com/AndrewDongminYoo/toml-tidy
    rev: v0.3.1 # pin the latest release; the hook ships from v0.2.0 onward
    hooks:
      - id: toml-tidy

The hook runs toml-tidy --in-place, and args are appended to it, so flags are set per repository without losing in-place rewriting:

hooks:
  - id: toml-tidy
    args: [--blank-lines, --order, alpha]
    exclude: ^uv\.lock$ # lockfiles are TOML too

Trunk

toml-tidy is available as an opt-in formatter through Trunk.

See the official Trunk plugin definition for setup and runtime requirements.

Ordering

natural is the default and compares digit runs numerically, so item2 precedes item10.

alpha uses case-insensitive lexical order.

Both modes compare TOML's parsed logical key, not source quoting.

Dotted keys such as b.a = 2 sort with their sibling direct keys by their parsed dotted path, segment by segment, so a precedes b.a, which precedes b.z.

For example, [plugins.omo] precedes [plugins."omo-kit"], while the quoted spelling remains unchanged in output.

Preservation

Direct keys and sibling explicit table declarations are sorted recursively within their parent table.

Array-of-tables declarations such as [[items]] sort by name among their sibling tables, while the element order inside each array of tables remains unchanged.

Parent-child hierarchy remains unchanged.

Standalone comments move with the following key or table declaration.

Whitespace between entries remains after the preceding entry, and trailing whitespace remains at its table boundary, unless --blank-lines is enabled.

Inline comments, value formatting, and key quoting remain attached to their parsed tomlkit items.

Keys inside inline tables are not reordered.

Blank lines

--blank-lines (config: blank-lines = true) is off by default and runs after sorting. It rewrites blank lines only, never comments or values:

  • Exactly one blank line precedes every table and array-of-tables header, above the comment run attached to that header rather than between the comment and the header.
  • No blank lines remain between key-value entries, inside a comment run, or at the end of the file.
  • The document's first rendered line never gains a blank line above it.
  • Blank lines inside multi-line string values belong to the value, not to the layout, and are untouched.

Given this input:

a = 1

b = 2
[x]
p = 1


[y]
q = 1

toml-tidy --blank-lines produces:

a = 1
b = 2

[x]
p = 1

[y]
q = 1

The result is stable, so --check reports a file once and reports it clean after --in-place fixes it.

Metadata

Release files for toml-tidy 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for toml-tidy 0.3.1
File Size Uploaded
toml_tidy-0.3.1.tar.gz 14.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for toml-tidy 0.3.1
File Interpreter ABI Platform
toml_tidy-0.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 29.0 kB

Release files / toml_tidy-0.3.1.tar.gz

Download URL toml_tidy-0.3.1.tar.gz
Size 14.0 kB
Tags Source
SHA-256 checksum
How to use checksums
f08ca2894945e508d00466023f8345d8a38667dc8b8acca01743793366ddfb08
BLAKE2b-256 checksum
How to use checksums
d7eb10293513d6f0eaec3292b38f6f983cde7778b01dca0cb8b87321e508f5ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / toml_tidy-0.3.1-py3-none-any.whl

Download URL toml_tidy-0.3.1-py3-none-any.whl
Size 15.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a279a06db1a86221446ab50538d2b33acb89ec49b0bdcfe2056d48d5e1fe8183
BLAKE2b-256 checksum
How to use checksums
5ceb3678ed30ef8fb386d253070061ea67403275ef94e33247f59d67b3256092
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.0 {"installer":{"name":"uv","version":"0.12.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.6.0

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

This release

0.3.1 This release

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page