tomlkit: a TOML parser that keeps your comments and your whitespace
Style-preserving TOML library for Python
At a glance
- What is it?
- tomlkit is a Python TOML library whose whole reason to exist is that a document parsed and written back should look the way it did before. It preserves comments, indentation, whitespace and element order, and the README is candid about the one case where that promise does not hold.
- Who is it for?
- Adopt tomlkit when a program has to modify a configuration file that a human also edits, because preserving comments, blank lines and ordering is the difference between a readable diff and a rewrite of the file. Do not adopt it when you only need to read values, since a plain parser is simpler and faster for that, and do not assume layout is preserved in every case, because the README documents one normalisation of an out-of-order sub-table inside an array of tables.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Why a TOML library needs to remember the file
TOML is the configuration format of pyproject.toml, and a great many tools are asked to read one, change one value and write it back. A conventional parser hands you a dictionary and forgets everything else: the comment explaining why a dependency is pinned, the blank line that groups the sections, the order the sections were written in.
tomlkit exists to fix exactly that. The README describes it as a 1.1.0-compliant TOML library whose parser preserves all comments, indentations, whitespace and internal element ordering, and makes them accessible and editable via an intuitive API. It can also create new TOML documents from scratch with the provided helpers, so it is a full document model rather than only a patch tool.
That distinction is what makes it useful in tooling. A tool that adds a dependency to a pyproject.toml with a conventional parser will produce a file where the human comments are gone and the ordering is whatever the dict produced. With tomlkit the same operation leaves the file looking hand-written, with only the intended line changed, which is what makes the resulting diff reviewable.
There is a lineage note in the README as well: part of the implementation was adapted, improved and fixed from Molten, a project by the same author. It is a small reminder that this kind of library is the product of one person's careful work rather than a specification-driven component.
The project lives under the python-poetry organisation, is MIT licensed, and the documentation is on readthedocs. The releases are regular: 0.15.0 on 2026-05-10, 0.15.1 on 2026-07-17 and 0.15.2 on 2026-10-16, with the last push on 2026-10-19.
The one case where the layout does not survive
The README has a Limitations section, and it is short and specific, which is the kind of limitation note that builds trust.
tomlkit preserves the original layout of a document with one exception. A sub-table that extends an array of tables out of order is normalised into the array's last element when the document is re-serialised, rather than being kept at its original position. The example given is a header such as a fruit apple texture table that appears after a fruit array of tables with an unrelated table in between.
The last sentence of that paragraph is the important one: the data is preserved, only the physical placement of that sub-table changes.
So the failure mode is a reordering, not a data loss. If your file has a sub-table that logically belongs to an element of an array of tables but is written somewhere else, a round trip through tomlkit will move it into the last element of that array. The values survive, and the file remains valid TOML, but the diff will show a moved block.
That is an unusual corner of the format, and the fact that the library documents it rather than leaving users to discover it is worth noting. For a tool that edits configuration files, the general promise holds and there is one known, well-described exception, which is a much better position than a vague claim that formatting is preserved.
For a project that rewrites a pyproject.toml with such structures, the advice is simple: keep the file in a form you are happy to have reorganised, or patch the text directly when the placement matters.
Three ways to install, and two lock files in the repository
The installation section leads with uv, which is a small sign of where the project is aimed.
uv add tomlkitThat adds the dependency to your pyproject.toml and updates the lock file in one step. If you only want it in the current environment, there is a pip equivalent:
uv pip install tomlkitAnd for everyone else:
pip install tomlkitThe package requires Python 3.9 or newer, and the project metadata lists two authors, Sébastien Eustace and Frost Ming.
The repository itself carries an unusual pair of lock files, poetry.lock and uv.lock, side by side. That is a project that supports both ecosystems rather than having migrated from one to the other, and it means the dependency versions used for development can be resolved either way.
The rest of the tooling is visible in the root listing. There is a tox.ini for running the test matrix across environments, a .coveragerc for coverage measurement, a .pre-commit-config.yaml for the checks that run before a commit, a .readthedocs.yaml for the documentation build, and a .gitmodules file, which points to the one dependency of the test suite.
The build backend is poetry-core at 2.2.0 or newer, and the distribution includes a py.typed marker in the package, which is what tells type checkers that the library ships inline annotations.
The test suite needs a submodule, and that is stated plainly
The Running tests section is three sentences and one command, and it contains a detail that saves a confusing failure.
The repository has to be cloned with submodules:
git clone --recurse-submodules https://github.com/python-poetry/tomlkit.gitThe reason is given next: the toml-test submodule is required for running the tests. That is the compliance suite for TOML implementations, so a library that claims 1.1.0 compliance is expected to run it, and a clone without the submodules will fail in a way that looks like a broken library rather than a missing checkout step.
With that in place, the tests run through the Poetry environment:
poetry run pytest -q testsThe use of poetry run rather than a bare pytest is worth noticing, because it means the tests are executed against the pinned development dependency group rather than whatever happens to be importable in the ambient environment. The dependency group is defined in the project file and holds pytest at 7.2, pytest-cov at 4.0, PyYAML at 6.0, pre-commit, mypy pinned to exactly 1.19.1, and the documentation stack with Sphinx and the furo theme.
So the test story is coherent: a compliance suite as a submodule, a pinned test environment, coverage measurement configured in the root, and a pre-commit hook that runs the same checks before a change is ever proposed.
Linting and typing are pinned with reasons attached
The tool configuration in the project file is unusually explicit, and the comments make it clear that it is a deliberate choice rather than an accident.
The ruff section starts with a note that the base rule set is pinned because ruff 0.16 expanded its default selection. The selected rules are the import, bugbear, comprehension, pygrep-hooks, ruff, pycodestyle and 2020 rule sets, with three specific codes ignored, and the McCabe complexity limit set to 10. The isort configuration is unusually strict as well: every import on its own line, two lines after the import block and one line between types, with tomlkit marked as first party and pytest as third party.
The mypy configuration is strict, applied to the package and the tests, with three extra error codes enabled, one of which, ignore-without-code, exists specifically to stop a type ignore comment from being left without a reason.
The reasons are visible in the pins themselves. mypy is pinned to an exact version while the other tools use compatible ranges, which is the tell that the type checker is the one whose new releases change the result of a run. Sphinx is capped below 5.0 and the theme below 2023, which suggests the documentation build is the other fragile spot.
None of this is glamorous, and all of it is the difference between a library whose checks are reproducible and one whose checks change under you. For a project whose entire value proposition is not surprising you with output, stable tooling is a fair match.
Where to use it, and where a plain parser is enough
The decision is about who else reads the file.
If a human maintains the file, a tool that rewrites it, and a script that reads it, then tomlkit is the right choice. The typical case is a tool that adds a dependency, bumps a version or inserts a configuration block into a pyproject.toml, and the human's comments and section ordering are part of the document's meaning. A plain parser returns a dictionary and a writer produces a canonical file, and the human's intent goes with it.
If nothing else touches the file, tomlkit is unnecessary. Reading a value, validating a config or loading a settings file is a job for a simpler library, and a style-preserving parser does more work than the task needs.
The middle case is worth thinking about: a tool that writes a file it also generated, with no human comments to lose. The style preservation is then mostly wasted, but it is not harmful, and the same code path can serve both cases if a tool handles both generated and hand-edited files.
The practical constraints to remember are the library's own. The one documented normalisation of an out-of-order sub-table in an array of tables, the version still below 1.0 at 0.15.2, and the fact that the last push was on 2026-10-19 with three releases during 2026. None of that is a red flag for a stable internal utility, and pinning the version removes most of the concern.
What the library does not do is worth stating as well: it is not a validator, not a schema tool and not a formatter. It is a document model that remembers where things were, and its value is entirely in that remembering.
Editorial conclusion
Adopt tomlkit when a program has to modify a configuration file that a human also edits, because preserving comments, blank lines and ordering is the difference between a readable diff and a rewrite of the file. Do not adopt it when you only need to read values, since a plain parser is simpler and faster for that, and do not assume layout is preserved in every case, because the README documents one normalisation of an out-of-order sub-table inside an array of tables. Before you ship it, check that special case against your own files, and remember the project is at version 0.15.2 with the last push on 2026-10-19, so pin the version you tested.
Frequently asked questions
What does tomlkit do that a normal TOML parser does not?
Its parser preserves all comments, indentations, whitespace and internal element ordering, and makes them accessible and editable through an API, so a document can be parsed, modified and written back with the original layout intact. It can also create new TOML documents from scratch with the provided helpers.
Are there cases where tomlkit does not preserve the original layout?
One, and the README documents it. A sub-table that extends an array of tables out of order, such as a texture table appearing after an array of tables with an unrelated table in between, is normalised into the array's last element when the document is re-serialised. The data is preserved, only the placement of that sub-table changes.
How do I install tomlkit?
The README leads with uv add tomlkit, which adds the dependency to your pyproject.toml, and also gives uv pip install tomlkit for an environment-only install, plus pip install tomlkit for everyone else. The package requires Python 3.9 or newer.
How do I run the tomlkit test suite?
Clone the repository with submodules, because the toml-test submodule is required for running the tests, and then run poetry run pytest -q tests. The repository also carries a tox.ini, a .coveragerc and a pre-commit configuration.
Is tomlkit still maintained?
The last push to the repository was on 2026-10-19, and the releases are 0.15.0 on 2026-05-10, 0.15.1 on 2026-07-17 and 0.15.2 on 2026-10-16. The project is MIT licensed, and the version is still below 1.0, so pin the version you test against.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/python-poetry-tomlkit)Was this useful?