TOML Formatter
Tidy the file without throwing away what it says
TOML Input
Formatted TOML
Why most TOML formatters quietly ruin your file
Formatting TOML sounds like the easy case. Parse the document, print it back out with consistent spacing, done — that is how the JSON, XML and YAML formatters on this site work, and it is fine for all three. Run it on TOML and you get a tidy file with every comment deleted.
It is not a bug in any particular library. A parser's job is to produce a value, and a comment is not part of the value, so it never reaches the other side. But TOML is the format people comment most heavily: a Cargo.toml or a pyproject.toml is half explanation — why a version is pinned, what to delete after a migration, which ticket a setting came from. port = 5432 # non-default, see INFRA-118 is the line that stops the next person changing it back.
So this one never parses your file to reformat it. It rewrites the source text, adjusting only what is safe to adjust: the spaces around =, whitespace inside table headers and dotted keys, the interior of single-line arrays and inline tables, blank lines between tables, indentation, and trailing whitespace. Comments stay exactly where you put them, including the ones at the end of a line, and the count is shown beside the output so you can see it rather than take it on faith.
The result is then checked. Both documents are parsed and compared key by key, and if they differ in any way the formatted version is not offered at all. A formatter may change how a file looks; it must never change what it means. That check is also why the tidying can be as thorough as it is — anything it got wrong would be caught before you saw it.
One thing worth saying plainly: taplo is the established TOML toolchain and it preserves comments too. If you are already running it in CI, keep doing that. This is for the times you have a file in front of you, in a browser, and want it readable now.
Tidying a file
- Paste the TOML – A whole
Cargo.toml, apyproject.toml, a Netlify or Hugo config, or a fragment. If it does not parse you get the line and column from the parser rather than a vague complaint, so you can fix it first. - Choose how it should sit – Flat leaves every entry against the left margin, which is what almost every published TOML file looks like. Indented puts entries two spaces under their table header, which some people prefer for deeply nested configuration. Neither changes meaning — TOML ignores indentation entirely.
- Turn on alignment if you want it – Pads the keys in each run of consecutive entries so the
=line up in a column. It reads well in a short table of settings and gets silly in a long one, which is why it is a choice rather than the default. - Check the comment count, then copy – The chip beside the output says how many comments came through. It is counted from the output text, not assumed — a hash inside a string like
"https://x/#install"is not counted, because it is not a comment.
TOML gives you no way to say "these keys belong to this table" through indentation — the table header does that, and leading whitespace is discarded. So indenting is purely for the reader, and it is worth knowing that most tooling, taplo included, leaves files flat. If a file is going into a repository where others will run a formatter over it, flat is the choice that will not produce a diff on somebody else's machine.
A Cargo.toml that has been edited by four people
Nothing here is wrong — every line is valid TOML and the file builds. It has just drifted, the way a config file does when it is edited in a hurry over two years. Note in particular the two dependency lines: they say the same kind of thing and look nothing alike.
# Pinned deliberately - see INFRA-118 [ package ] name = "subscriber-provisioning" version = "2.4.1" # bump on release edition="2021" [dependencies] serde = { version = "1.0" } tokio = { version="1",features=["rt"] }
# Pinned deliberately - see INFRA-118 [package] name = "subscriber-provisioning" version = "2.4.1" # bump on release edition = "2021" [dependencies] serde = { version = "1.0" } tokio = { version = "1", features = ["rt"] }
What people use it for
Making a manifest readable before a review
A Cargo.toml that four people have touched has four spacing conventions in it. Tidying it before you open the pull request means the diff is about the dependency you added rather than about whitespace, and the comments explaining the existing pins are all still there to be read.
Settling an argument about a config file
Someone reformatted pyproject.toml and now nobody is sure whether the change was cosmetic. Run both versions through here with the same settings and compare: if the formatted forms match, the difference was whitespace. TOML to JSON is the other way to check — two files that produce identical JSON say the same thing whatever they look like.
Reading a config you did not write
Configuration for Ruff, Hugo, Netlify or Poetry arrives as a wall of settings with inconsistent spacing and no blank lines between sections. Formatting it is the cheapest way to see the shape of it, and TOML to Table will show the array-of-tables parts as a grid.
Tidying generated TOML
Anything written out by a script tends to be correct and unreadable — no blank lines, inline tables jammed together, keys in whatever order the serialiser produced. This gives it the spacing a hand-written file would have had, without you editing it by hand and risking a typo in something that was already right.
What it does
- Keeps every comment, including trailing ones on the same line as a value, because the file is never round-tripped through a parser.
- Verifies its own output. Both versions are parsed and compared before anything is shown. If they differ in any way, the formatted version is withheld.
- Normalises what should be normalised. Spacing around
=, dotted keys such asa . b . c, table headers like[ server . http ], and the interior of single-line arrays and inline tables. - Leaves multi-line values alone. An array spread over several lines often carries comments between its elements and a layout somebody chose; only its
key =prefix is touched. - Long integers stay exact. A 19-digit ICCID or an int64 maximum keeps every digit — nothing is converted to a JavaScript number along the way.
- Optional alignment and indentation, plus collapsed blank-line runs and one blank line between tables.
- Nothing is uploaded. Config files hold registry tokens and credentials, so the file stays in this tab.
Questions that come up
Will it really keep my comments?
Yes, and the page shows you the count rather than asking you to trust it. The reason it can is that the file is never parsed and re-printed — the source text is edited in place. To see why that matters, run a Cargo.toml through any parse-and-print formatter: the file comes back tidy and every # line is gone.
Does indentation mean anything in TOML?
No, and this is the difference that catches people coming from YAML. In YAML indentation is the structure and getting it wrong changes the document. In TOML whitespace before a key is discarded — the [table] header alone decides what a key belongs to. The specification says so directly, which is why indenting here is a matter of taste rather than correctness.
Why is my multi-line array left as it was?
Because re-flowing it can only lose things. A dependency list spread over several lines usually has comments against individual entries and a deliberate one-per-line shape; rewriting it would be a lot of risk to save a few characters. The key = part is tidied and the rest is copied exactly.
It says the check failed and gave me nothing.
That is the guard working. The formatted text is parsed and compared against the original, and if the two documents are not identical the result is thrown away rather than shown — a formatter handing back something that means something different is a far worse outcome than one that declines. If you hit it, the input is worth keeping: it is a case the formatter does not handle, and it should.
Should I use this or taplo?
Both, for different moments. taplo belongs in your editor and your CI, where it formats on save and keeps a repository consistent. This page is for the file that is in front of you right now — one you were sent, one from a container, one you are reading before deciding whether to change it — where installing a toolchain to make it readable is not a reasonable price.
Does formatting change my version numbers?
No, and the more interesting version of that question is about long integers. A 19-digit value in a config file — an ICCID, an account reference, a snowflake ID — is where most tools lose digits silently, because a JavaScript number cannot hold one. Nothing here is converted to a number at all: the text is rewritten as text, and the verification step reads both documents with a parser that keeps the digits exact.
Related tools
Worth reading
- TOML v1.0.0 — the specification – Short enough to read in one sitting, and the section on keys settles most arguments
- The Cargo manifest reference – What every key in a Cargo.toml means, from the people who defined them