Skip to content

YQ: Wrangling YAML Configs๐Ÿ”—

Consult the map

Kubernetes manifests, Ansible playbooks, GitHub Actions, Docker Compose โ€” in modern platform engineering, YAML is everywhere. But YAML's indentation-sensitive nature makes it notoriously difficult to edit with standard text tools like sed or awk.

yq is a portable command-line YAML processor. It's essentially jq for YAML, allowing you to slice, dice, and transform configuration files with precision and safety.

Installation๐Ÿ”—

Install yq on Linux
1
2
3
4
5
6
# Debian/Ubuntu (snap)
sudo snap install yq

# Or download the binary directly
sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq
sudo chmod +x /usr/bin/yq
Install yq on macOS
brew install yq
Install yq on Windows
1
2
3
choco install yq
# or
scoop install yq

Verify installation and confirm you have the mikefarah/yq implementation (there are several unrelated tools sharing the name):

Check yq Version
yq --version
# Output: yq (https://github.com/mikefarah/yq/) version v4.x.x

Quick Start: Get Productive in 5 Minutes๐Ÿ”—

yq syntax is intentionally similar to jq. If you know one, you're halfway to knowing the other.

Common YQ Operations
# Read a specific value from a K8s manifest
yq '.metadata.name' pod.yaml

# Update a value in-place
yq -i '.spec.replicas = 3' deployment.yaml

# Convert YAML to JSON (perfect for piping to jq)
yq -o=json '.' config.yaml

# Merge two YAML files
yq eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' base.yaml overlay.yaml

Reading a Deployment's replica count with yq, editing it in place with -i, then reading it back to confirm the change stuck

That last one is the pattern worth internalizing โ€” a base config and an environment-specific overlay merge into one result, the same shape whether you're reconciling two files by hand or reading how a templating tool does it for you:

graph LR
    Base["base.yaml"] --> Merge{{"eval-all<br/>select(0) * select(1)"}}
    Overlay["overlay.yaml"] --> Merge
    Merge --> Result["Merged config"]

    style Base fill:#2d3748,stroke:#cbd5e0,stroke-width:2px,color:#fff
    style Overlay fill:#2d3748,stroke:#cbd5e0,stroke-width:2px,color:#fff
    style Merge fill:#d69e2e,stroke:#cbd5e0,stroke-width:2px,color:#000
    style Result fill:#2f855a,stroke:#cbd5e0,stroke-width:2px,color:#fff

Why YQ Matters for Platform Work๐Ÿ”—

YAML is the backbone of Infrastructure as Code (IaC). One wrong indentation can break a production deployment. yq removes this friction by treating YAML as a structured data format rather than a text file.

Common Scenarios๐Ÿ”—

Find all containers in a Deployment that don't have resource limits defined:

Audit Resource Limits
yq '.spec.template.spec.containers[] | select(has("resources") | not) | .name' deployment.yaml

Update the image tag across multiple GitHub Action workflow files:

Update Image Tag
yq -i '.jobs.build.steps[] | select(.uses == "docker/build-push-action*") | .with.tags = "v2.1.0"' .github/workflows/*.yml

Extract values from a legacy config and format them for a new system:

Extract and Format
yq '.database | {host: .addr, port: .port}' old-config.yaml

Core Functionality๐Ÿ”—

Three behaviors cover most of what you'll reach for day to day:

  • In-place Editing (-i)


    Why it matters: Allows you to modify files directly without temporary files or redirects.

    Update Config
    yq -i '.debug = true' config.yaml
    

    Key insight: Always verify your filter without -i first โ€” and treat the edit as step one, not step three. Edit the git-tracked manifest, commit, and let your pipeline or reconciler apply it. Piping straight into kubectl apply against a running cluster skips the review and audit trail Git exists to give you.

  • Multi-document Handling


    Why it matters: Kubernetes files often contain multiple documents separated by ---.

    Read All Documents
    yq '.. | select(has("kind")) | .kind' multi.yaml
    

    Key insight: yq handles the stream of documents automatically.

  • Format Conversion (-o)


    Why it matters: Sometimes you need JSON for a tool that doesn't speak YAML.

    YAML to JSON
    yq -o=json '.' service.yaml
    

    Key insight: Useful for interoperability between different CLI tools.

Common Pitfalls๐Ÿ”—

  • Two Different Tools Share This Name


    mikefarah/yq (what this article covers) and kislyuk/yq (a Python wrapper that converts YAML to JSON and pipes it through the real jq) use different filter syntax entirely. A filter that works in one throws a cryptic error in the other โ€” check which one you actually have.

    Confirm Which yq You Have
    1
    2
    3
    yq --version
    # yq (https://github.com/mikefarah/yq/) version v4.x.x   โœ… this article
    # yq 3.x.x                                                โŒ kislyuk/yq โ€” different syntax
    
  • Forgetting -i Means Nothing Is Saved


    Without -i, yq prints the modified document to your terminal and leaves the file on disk untouched โ€” easy to mistake for "the edit didn't work."

    Wrong - Prints to Screen, File Unchanged
    yq '.spec.replicas = 3' deployment.yaml   # โŒ stdout only, file untouched
    
    Correct - Writes Back to the File
    yq -i '.spec.replicas = 3' deployment.yaml   # โœ… saved in place
    
  • Same Shell-Quoting Trap as jq


    yq filters starting with . and containing [] are just as vulnerable to shell glob expansion as jq's are. Always quote:

    Always Quote the Filter
    yq '.spec.template.spec.containers[]' deployment.yaml   # โœ… quoted
    

Practice Problems๐Ÿ”—

Practice Problem 1: Navigating Lists

In a YAML file like {"items": [{"name": "a", "val": 1}, {"name": "b", "val": 2}]}, how do you get the value (val) for the item named "b"?

Answer

Select a Field from a Matching List Item
yq '.items[] | select(.name == "b") | .val' file.yaml
This iterates through the list, filters for the specific name, and then selects the desired field.

Practice Problem 2: Adding a Field

How would you add a labels object with app: my-app to the metadata of a YAML file?

Answer

Add a Nested Field, Creating Parents as Needed
yq '.metadata.labels.app = "my-app"' file.yaml
yq will automatically create the parent objects (labels) if they don't exist.

Key Takeaways๐Ÿ”—

Feature command/Filter
Read yq '.path.to.key' file.yaml
Write yq -i '.key = "value"' file.yaml
Filter select(.key == "match")
Convert -o=json (to JSON), -o=xml (to XML)
Delete del(.key.to.remove)

What's Next๐Ÿ”—

If you're following the Debugging With Nothing But a Terminal pathway, the next step is Vim Survival Mode โ€” vi/vim is still what you'll find on almost every server when there's no time to install anything else, and it covers the four commands that get you in, fixed, and out.

Further Reading๐Ÿ”—

Official Documentation๐Ÿ”—

  • jq - The JSON processor that inspired yq.
  • yamllint - For validating YAML syntax and style.

Deep Dives๐Ÿ”—

  • YAML Specification - For when you really need to understand why your indentation is broken.
  • How Parsers Work - The lexing-then-parsing pipeline underneath every yq call.