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.0 # 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.0

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.0
File Size Uploaded
toml_tidy-0.3.0.tar.gz 13.5 kB Details

Built distribution (wheel)

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

Total release size: 28.1 kB

Release files / toml_tidy-0.3.0.tar.gz

Download URL toml_tidy-0.3.0.tar.gz
Size 13.5 kB
Tags Source
SHA-256 checksum
How to use checksums
7aa6f25de71961415a160cc7a244720356074016c8810a282c525ec1eec4023a
BLAKE2b-256 checksum
How to use checksums
acd3db96d4a6181b900fcb64852b5cfbdc75562c25b91d6c58daad1f9569bee9
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.0-py3-none-any.whl

Download URL toml_tidy-0.3.0-py3-none-any.whl
Size 14.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1f13449fd2e395a9a345d037bcb4e24e799fb1a1d860e90e9f84aac0c23dbae4
BLAKE2b-256 checksum
How to use checksums
ddfa8755c4010f72142c73b56fe74e0b48d1b9d7e8d2bcab643f0cb9a28a3228
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

0.3.1

2 release files

This release

0.3.0 This release

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