Edit config files without reflowing them.
edikt is a lossless, format-preserving config editor: jq-flavored expressions, sed-shaped execution, seven formats. It changes only the bytes you point at - every comment, indent, quote style, and trailing comma you didn't touch survives byte-for-byte.
curl -fsSL https://heider.cc/edikt.sh | bash
brew install jhheider/tap/edikt
cargo install edikt
pkgx install edikt
Or grab a prebuilt binary - Linux, macOS, Windows; x86_64 and arm64. MIT or Apache-2.0.
One value changes. Nothing else moves.
Your tsconfig.json has comments,
hand-alignment, and trailing commas - the things most
tools destroy on the way through a parser. edikt edits
the tree but writes back the file.
$ edikt -i '.compilerOptions.target = "ES2022"' tsconfig.json $ git diff --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { // Keep this in sync with the deploy image! - "target": "ES2020", + "target": "ES2022", "strict": true, /* non-negotiable */ "outDir": "./dist",
A one-line diff, comments intact - instead of "the tool reformatted the whole file."
# query, jq-style - any supported format $ edikt '.compilerOptions.strict' tsconfig.json true # compute in place, chain edits, delete keys $ edikt -i '.version |= . + "-dev"' package.jsonc $ cat settings.jsonc | edikt -t jsonc 'del(.telemetry) | .theme = "dark"' # convert between formats - comments carried across $ edikt -T yaml tsconfig.jsonc # bump every crate in a Cargo workspace $ for c in crates/*/Cargo.toml; do > edikt -i '.package.version = "0.2.0"' "$c" > done
Seven formats, one grammar
The same expression works on the whole pile of config a
project accumulates. Format detected by extension;
each format is backed by the best lossless substrate for
the job (toml_edit, kdl-rs, a
rowan CST for the rest).
Comments are data here
Every other tool treats comments as debris to preserve at best. edikt makes them addressable, queryable, and editable - a dimension of the document, with their own sigil.
# read the comment above a key $ edikt '.compilerOptions.target.#' tsconfig.json Keep this in sync with the deploy image! # set an inline comment $ edikt -i '.database.pool.#.inline = "tuned 2026-07"' app.toml # stream every comment in the file, with its path $ edikt 'comments' compose.yaml
Losslessly bulk-editing the comments themselves is something no other config tool does.
The fine print, by design
-
sed-shaped exit codes. A query
matching nothing is a silent no-op - safe under
set -e.--exit-statusopts into jq's behavior when you want it. -
YAML without the Norway trap.
Scalars resolve per the YAML 1.2 core schema:
on,no, andyesare strings, and value types are preserved across round-trips. -
Real jq idioms.
//defaults,|=update-assign,del(), regextest/sub/gsub,split/join- a curated v1 surface, not a dialect that surprises you. -
Scripts welcome. Multiple
-eexpressions per run, or a whole edit script from a file with-f release.edk. -
A library, too. The CLI sits on
independently published crates -
edikt-coreplus a losslessDocumentimplementation per format - if you'd rather do this from Rust. See the crates.
Why it exists
The problem crystallized reading "Respectful" YAML Patching in Rust, which surveys the ecosystem and lands on the gap in one line: none of the tools preserve both the formatting and the comments.
Surgically change one value - or one comment - and leave every other byte alone. Not just for YAML, but for the whole pile of config formats a project accumulates.
The good tools each own their corner: jq and
yq for querying, taplo and
prettier for formatting, and the excellent
toml_edit and kdl-rs for
lossless edits (edikt is built on those last
two). edikt isn't trying to replace them - it's the piece
that wasn't on the shelf: one tool that edits
and queries and
converts, across all of these, touching only the bytes
you point at.