Skip to main content

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 (your tool.*, custom keys) sort alphabetically after the known ones.
  • Dependency blocks (dependencies, devDependencies, peerDependencies, …) are sorted A→Z — the part you actually want sorted.
  • scripts is left in your order, because script order is frequently meaningful (pretest → test → posttest, ordered build steps). Opt in with --sort-scripts if 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.json with 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)

Source distribution for keytidy 0.1.0
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)

Table of built distributions (wheels) for keytidy 0.1.0
File Interpreter ABI Platform Actions
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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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