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)
| File | Size | Uploaded | |
|---|---|---|---|
| toml_tidy-0.3.1.tar.gz | 14.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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}
|