The practical answer to YAML in shell scripts
yq exists because configuration files are structured data, while the usual shell text tools do not understand structure. A sed replacement can hit the wrong key, damage indentation, or turn a value into the wrong type. yq gives YAML and several neighboring formats an expression language modeled on jq. Reading a nested value is short, updating a selected array item is possible, and -i writes the result back to the file.
The project has grown well beyond a YAML lookup command. It can merge documents, load other files, update from environment variables, sort keys, manipulate dates, encode data, and convert among YAML, JSON, XML, CSV, TSV, TOML, HCL, INI, properties, Lua, and shell output. It understands multi-document YAML, front matter, comments, anchors, aliases, tags, and styles. That breadth makes it useful in CI pipelines, Kubernetes release scripts, repository maintenance, and one-off debugging.
The MIT-licensed Go implementation is distributed as a dependency-free binary for common operating systems and architectures.
Easy installation, with a real learning curve
The first five minutes are excellent. Homebrew users run one command, Windows users have Winget, Chocolatey, and Scoop options, and Linux users can take an official binary or use several package managers. Docker and Podman images cover environments where installing a binary is undesirable. A GitHub Action and go install route are documented too.
Using yq safely in repeatable automation takes more care. The expression language resembles jq, but the README plainly says support is not complete. Missing jq object shorthand remains an open enhancement request. A filter copied from a jq answer may work, fail, or differ at an edge, so test it rather than treating the syntax claim as compatibility certification.
Evaluation mode matters as well. Normal evaluation processes documents in sequence; eval-all loads every document from every file before evaluating once. The latter is useful for deep merges, but memory use grows with the total input. Input format is inferred from extensions and otherwise defaults to YAML. Reliable scripts should pass explicit formats when filenames or standard input make the type unclear.
Shell quoting is another source of friction, especially in PowerShell. The README gives platform-specific advice because quotes belong to both the shell and the yq expression. This is documentation doing useful work, but it means a command tested in Bash should not be dropped unchanged into every runner.
Format preservation is good, not exact
yq's strongest advantage over piping YAML through a JSON-only tool is that it tries to retain YAML-specific material. Comments, tags, anchors, aliases, scalar styles, and document separators can matter to humans and downstream systems. Operators can even change comments or styles deliberately.
The limit is stated in the README: comment positions and whitespace cannot be preserved in every scenario because of constraints in the underlying YAML library. That rules out yq as a byte-for-byte round-trip editor. A current bug report adds a narrower example: loading text containing one tested UTF-8 symbol caused a multiline value to be emitted as a quoted single-line scalar with escaped newlines, while another symbol retained block style. The data remains representable, but the human-facing form changes.
Conversion deserves the same caution. Moving between formats with different type systems and syntax cannot be lossless in all cases. One open CSV-to-JSON report shows leading-zero values such as 040 and 035 becoming 32 and 29, consistent with octal interpretation. Identifiers, postal codes, account fragments, and similar columns should be forced or checked as strings. Recent release notes show continued fixes for TOML scope, null handling, INI state, properties arrays, YAML merge behavior, and float preservation. The breadth is valuable, but every extra decoder and encoder creates its own edges.
Operational and security boundaries
In-place editing is convenient enough to become infrastructure. That makes exit handling and validation important. Use --exit-status when a missing or false result should fail a job, keep source files under version control, and inspect generated configuration before deployment. For complex expressions, --from-file is easier to review than a long quoted command.
The expression language can read environment variables and load files. Those are useful features in trusted scripts and risky capabilities in a service that accepts expressions from users. Current builds expose --security-disable-env-ops and --security-disable-file-ops; wrappers should apply them when the expression is not entirely controlled by the operator. Container instructions also show restricted capabilities and no network access, which is a sensible baseline for isolated transformations.
Large batches have a current caveat. An August 2026 report reproduces file descriptors remaining open across multi-file evaluation, eventually producing a too-many-open-files error under a deliberately low limit. Most everyday invocations will never notice, but jobs expanding thousands of paths should test their limits or split work until the behavior is fixed. HCL users should also note an open panic on object keys that are not strings, even though the HCL specification expects string keys.
Healthy, mature, and still changing
The repository was pushed on August 6, 2026, and release 4.53.3 shipped on June 6. Current issues were opened and updated in August, while the latest release credits several outside contributors. GitHub's open count of 279 includes both issues and pull requests, so it is evidence of a sizable working queue, not 279 confirmed defects. Active fixes across less common formats show maintenance rather than neglect.
Documentation is unusually strong for a command-line utility. The README covers quick operations, installation routes, containers, security, flags, known limitations, and troubleshooting. A separate documentation site supplies operator-by-operator examples and recipes. The main weakness is discoverability through sheer volume: newcomers may need several passes to understand value flow, document context, and merge semantics.
yq earns its place in a developer toolbox. Use jq for JSON-only work that needs exact jq behavior, and use a programming language when transformation logic becomes application code. For configuration edits that belong in a shell script, yq is usually the best first choice, provided tests cover the exact formats and formatting your pipeline cares about.