keytidy
Tidy JSON key order — and sort package.json the way it's actually meant to
look. Inconsistent key order is pure diff noise: one teammate's editor writes
name first, another's tool writes it last, and every PR churns lines that
didn't really change. keytidy gives every JSON file one deterministic order.
Zero dependencies (pure standard library).
pip install keytidy
keytidy # sort ./package.json in place
keytidy --check # CI gate: exit 1 if anything isn't sorted
It's not just "sort all the keys"
Sorting package.json alphabetically would be wrong — name belongs at the
top, not wedged between module and optionalDependencies. So keytidy treats
package.json specially:
- Top-level fields follow the conventional order (
name,version,description, …,scripts,dependencies,devDependencies, …). Unknown fields (yourtool.*, custom keys) sort alphabetically after the known ones. - Dependency blocks (
dependencies,devDependencies,peerDependencies, …) are sorted A→Z — the part you actually want sorted. scriptsis left in your order, because script order is frequently meaningful (pretest→test→posttest, ordered build steps). Opt in with--sort-scriptsif you disagree.
Every other .json file just gets a clean recursive alphabetical sort, with
arrays left in their original order (an array is data, not config).
Example
// before
{ "version": "1.0.0", "scripts": { "test": "…", "build": "…" },
"name": "demo", "dependencies": { "zod": "…", "axios": "…" } }
// after → keytidy
{
"name": "demo",
"version": "1.0.0",
"scripts": { "test": "…", "build": "…" }, // order preserved
"dependencies": { "axios": "…", "zod": "…" } // sorted A→Z
}
Usage
keytidy # sort ./package.json in place
keytidy package.json tsconfig.json
keytidy *.json # your shell expands the glob
keytidy --check # don't write; exit 1 if any file isn't sorted
keytidy --stdout pkg.json # print the sorted result instead of writing
keytidy --indent 4 # force 4-space indent (default: detected, else 2)
keytidy --sort-scripts # also sort the package.json scripts block
keytidy --all-keys # ignore the conventional order, sort A→Z
You can also run it as a module: python -m keytidy.
Indentation is detected from the file and preserved, so keytidy doesn't fight your existing 2-space / 4-space / tab style. The trailing newline is kept as-is.
As a CI / pre-commit gate
# .pre-commit-config.yaml
- repo: local
hooks:
- id: keytidy
name: keytidy
entry: keytidy --check
language: system
files: package\.json$
Exit codes
| Code | Meaning |
|---|---|
0 |
sorted (write mode) or everything already sorted (--check) |
1 |
a file needs sorting (--check only) |
2 |
invalid JSON, or a file couldn't be read/written |
Notes
- It rewrites by parsing and re-serializing, so it normalizes JSON formatting.
It does not support comments or trailing commas (JSONC /
tsconfig.jsonwith comments will report invalid JSON rather than mangle them). - The sort itself is pure and deterministic, shared with the Node port — for typical config files the two produce identical output.
Also available for Node
Same behavior, same flags: npx keytidy
(source: keytidy).
License
MIT
Metadata
Release files for keytidy 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| keytidy-0.1.0.tar.gz | 9.8 kB | Without provenance | Details for keytidy-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| keytidy-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for keytidy-0.1.0-py3-none-any.whl |
Total release size: 18.3 kB
Release files / keytidy-0.1.0.tar.gz
| Download URL | keytidy-0.1.0.tar.gz |
|---|---|
| Size | 9.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1700cc718285236bbcd934f8c9e222e4a9c5d641ad917c7d61b5a61b0a7462fa
|
|
BLAKE2b-256 checksum How to use checksums |
04d98fc8dfb5a9ed0448e59f93e636bad1f76ae522471a82fa8ce88f46b4c86c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.7
|
Release files / keytidy-0.1.0-py3-none-any.whl
| Download URL | keytidy-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
659ab9bb94cdb653ccd795a2f06c9bc2836c2f0350fc5cbeda040953d2c5f529
|
|
BLAKE2b-256 checksum How to use checksums |
d4768ad9154330b82767d83c7d56daf32eb9cc44c65abf310affb7fb2bacec91
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.7
|
Security for keytidy 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.