To review a Cargo.toml or pyproject.toml change without formatting noise, compare the two files by parsed value instead of by line. FindUtils TOML Diff parses both versions and reports each real difference at its TOML path, such as dependencies.serde or project.version, so reordered keys, comments, whitespace and table style do not show up. The files are compared in your browser and are not uploaded.

This guide explains why line diffs of TOML are noisy, how to read the path report, how arrays behave, and which changes the comparison cannot hide or explain.

Why a Line Diff of TOML Is Noisy

TOML lets you write the same data several ways. The TOML 1.0 specification says dotted keys "create and define a table for each key part before the last one", so fruit.apple.color = "red" builds the same tables as [fruit] and [fruit.apple] headers. Inline tables in curly braces are a third spelling of the same thing.

These three blocks hold identical data:

1
2
3
[dependencies.tokio]
version = "1"
features = ["full"]
1
2
3
[dependencies]
tokio.version = "1"
tokio.features = ["full"]
[dependencies]
tokio = { version = "1", features = ["full"] }

A line diff reports every line of that change. A value comparison reports nothing, because nothing changed. The same applies to keys moved to a different position in a table, blank lines, alignment spaces and comments.

How to Compare Two Versions

Step 1: Get the before and after

Copy the old file from the base branch and the new one from the pull request, or save both from your editor. Any TOML document works: Cargo.toml, pyproject.toml, rustfmt.toml, ruff.toml, netlify.toml and so on.

Step 2: Paste or drop them

Open TOML Diff and put the old version in the Before (A) pane and the new one in After (B). Rename the panes if you want the report to say main and feature-branch.

Step 3: Compare

Press Compare. The summary counts added, removed and changed paths. Turn on Show unchanged paths to list every leaf that matched as well.

Step 4: Keep the report

Copy it, or download toml-diff-report.txt or toml-diff-report.json for the review thread.

How to Read the Paths

Each line of the report is one path in the parsed document:

Report lineMeaning
~ package.version: "0.1.0" → "0.2.0"The value at that path changed
- dependencies.serde = "1.0"The key exists only in the old file
+ dependencies.anyhow = "1"The key exists only in the new file
+ tool = {"ruff":{"line-length":100}}A whole new table; it appears once, with its contents
~ a[1]: 2 → 3The second element of the array a changed
~ "my key": 1 → 2A key that is not a bare key is shown in quotes

A table that is new in B is reported as one added path holding the whole table, not as one line per key inside it. The same goes for a table that was removed.

Arrays Compare by Position

TOML arrays are ordered, so TOML Diff compares them element by element: index 0 with index 0, index 1 with index 1. That keeps the report exact, but it has a consequence when an item is inserted at the front or in the middle.

Changing features = ["derive"] to features = ["std", "derive"] reports features[0] changed from "derive" to "std" and features[1] added as "derive". Nothing was lost, but every element after the insertion point looks changed. When a report shows a run of changed indexes, read the old and new arrays side by side before concluding that items were replaced.

This matters most in files built from arrays of tables. Cargo.lock is TOML, and its [[package]] entries are one array: a package added near the top shifts the index of every package after it.

What Still Counts as a Change

The comparison ignores formatting, not meaning. These do show up:

  • A type change. version = 1 and version = "1" are an integer and a string, so the path is reported as changed.
  • A table replacing a value. When serde = "1.0" becomes serde = { version = "1.0", features = ["derive"] }, the path dependencies.serde is reported as changed from a string to a table.
  • A date. Dates and times are compared by their TOML text, so 2024-01-01 and 2024-01-02 differ.

One distinction is not kept: an integer and a float with the same value, such as 1 and 1.0, compare as equal, although the TOML specification treats integers and floats as separate types.

When a File Does Not Parse

If either side is not valid TOML, the comparison stops and names the side that failed, with the line and column. A common cause is a key defined twice, which the specification forbids outright ("Defining a key multiple times is invalid"), so a bad merge that leaves two version lines in one table fails here instead of passing silently. Fix the file, then compare again.

Where the Formats Are Defined

The layout of these files is set by their own specifications, which say what each table means:

TOML Diff checks structure and values, not whether a key is allowed by Cargo or by a Python build backend. It does not look up package versions either, so a bumped version is reported without any statement about what the new release contains.

Common Mistakes

Expecting a merged file. TOML Diff only reports differences. To move a config between formats, use YAML TOML Converter or JSON TOML Converter.

Reading an array shift as many edits. An insertion early in an array makes later indexes look changed. Check the arrays before reverting anything.

Comparing a partial copy. If you paste only the [dependencies] block from one side and the whole file from the other, everything outside that block is reported as added or removed.

Tools Used in This Guide

ToolUse
TOML DiffCompare two TOML files by parsed value and path
YAML TOML ConverterConvert between YAML and TOML
JSON TOML ConverterConvert between JSON and TOML
JSON DiffThe same kind of path comparison for JSON files
Env DiffCompare two .env files by key

FAQ

How do I see only the real changes in a Cargo.toml pull request?

Paste the old and new Cargo.toml into TOML Diff. Only paths whose values were added, removed or changed are listed, so key reordering, comments, spacing and switches between [table], dotted keys and inline tables disappear from the report.

Does switching a dependency to an inline table count as a change?

No, when the keys and values stay the same. [dependencies.tokio] with version = "1" and tokio = { version = "1" } parse to the same table, so no difference is reported.

Why does one inserted array item show several changes?

Arrays are compared by position. Inserting an item shifts every later element to the next index, so each shifted index is reported as changed and the last one as added.

Can I compare Cargo.lock files?

Yes, Cargo.lock is TOML. Its [[package]] entries form one array, so an added or removed package shifts the indexes of the entries after it and the report grows accordingly. For lock files, read the added and removed entries rather than counting changed indexes.

Next Steps

Paste your before and after manifests into TOML Diff. For configuration kept in dotenv files, compare them with Env Diff.