A serious YAML tool in one delightfully questionable medium.
Website · Docs · Recipes · YAML support
YAML.sh queries, transforms, validates, and edits YAML in one readable POSIX shell file with portable AWK inside. It can change exactly what you asked for without rewriting the comments and formatting around it.
$ ysh '.books[] | select(.read) | .title' reading.yml
Piranesi
The Left Hand of Darkness
$ ysh --preserve-only --diff '.theme = "midnight"' settings.yml
--- a/settings.yml
+++ b/settings.yml
@@ -1 +1 @@
-theme: light # terminal colours
+theme: midnight # terminal coloursNo extra runtime or package manager. The constraint is the fun part.
brew install azohra/tools/yshOr install the checksum-pinned release artifact:
curl -fsSL https://yaml.azohra.com/install | shChoose another directory with YSH_INSTALL_DIR="$HOME/.local/bin".
Read-only queries require /bin/sh and AWK. --check, --diff, and -i also use mktemp, cp, cmp, mv, rm, and wc from the host.
Use paths, pipes, filters, reducers, construction, and updates without flattening away YAML types, anchors, aliases, or merge keys.
ysh '.albums | map(select(.rating >= 9)) | map(.title)' music.yml
ysh -n -o yaml '{name: "Ada", tags: [awk, yaml]}'
ysh -o yaml '.count += 1 | del(.draft)' notes.yml
ysh eval-all '. as $doc ireduce ({}; . * $doc)' defaults.yml local.ymlysh --check '.image.tag = "stable"' services/*.yml
ysh --diff '.image.tag = "stable"' services/*.yml
ysh --preserve-only -i '.image.tag = "stable"' services/*.ymlYAML.sh can update scalars, collections, block scalars, comments, and ordering while leaving unrelated text alone. --preserve-only refuses a change when it cannot keep that promise.
--check and --diff write nothing and return 0 when clean, 1 when files would change, and 2 on error. Multi-file writes are fully prepared before the first replacement, skip unchanged files, stop if a file changes after YAML.sh reads it, and roll back a failed write.
ysh --schema service.schema.json '.' service.yml
ysh --apply-patch change.json --preserve-only --diff service.yml
ysh --merge-patch production.json -i service.yml
ysh --json --generate-patch desired.yml '.' current.yml > change.jsonJSON Pointer, JSON Patch, Merge Patch, and a documented JSON Schema profile are built in. YAML.sh reads and writes JSON, YAML, TOML, INI, and XML; expression codecs cover properties, CSV, TSV, Base64, URI, and shell quoting.
ysh --type '.release.created' config.yml
ysh '[.services[0].port | line, .services[0].port | column]' config.yml
ysh --events config.yml
ysh --ast config.yml
ysh --explain=json --diff '.image.tag = "stable"' deploy.yml 2>changes.jsonlEvents and AST output show how YAML.sh understood a document. Explain mode reports selected paths, changes, and formatting decisions without logging values.
YAML files are data; queries are programs. Queries cannot execute commands or open network connections, but they can explicitly read environment variables or local files, and eval can compile a dynamically supplied expression. Those capabilities can be disabled independently. Read security and limits before running untrusted input.
YAML.sh documents what it supports:
- YAML support records accepted and rejected syntax.
- Query guide defines the expression language.
- Validate, patch, and convert defines schemas, patches, and non-YAML formats.
- Security and limits explains capabilities and resource ceilings.
Unsupported syntax fails clearly rather than returning a plausible result.
make allDevelopment source is modular under src/awk/; the build assembles the single ysh artifact. Start with DESIGN.md, then read the internals and development guides.