| created | "2025-12-16T00:00:00.000Z" |
| modified | "2025-12-16T00:00:00.000Z" |
| reviewed | "2025-12-16T00:00:00.000Z" |
| name | yq YAML Processing |
| description | YAML querying, filtering, and transformation with yq command-line tool. Use when working with YAML files, parsing YAML configuration, modifying Kubernetes manifests, GitHub Actions workflows, or transforming YAML structures. |
| allowed-tools | Bash, Read, Write, Edit, Grep, Glob |
yq YAML Processing
Expert knowledge for processing, querying, and transforming YAML data using yq v4+, the lightweight command-line YAML processor with jq-like syntax.
Core Expertise
YAML Operations
- Query and filter YAML with path expressions
- Transform YAML structure and shape
- Multi-document YAML support
- Convert between YAML, JSON, XML, and other formats
Configuration Management
- Modify Kubernetes manifests
- Update GitHub Actions workflows
- Process Helm values files
- Manage application configurations
Essential Commands
Basic Querying
yq '.' file.yaml
yq eval '.' file.yaml
yq '.fieldName' file.yaml
yq '.spec.containers[0].name' pod.yaml
yq '.[0]' array.yaml
yq '.items[2]' data.yaml
Reading YAML
yq '.metadata.name' deployment.yaml
yq '.spec.template.spec.containers[].image' deployment.yaml
yq '.optional // "default"' file.yaml
yq 'has("fieldName")' file.yaml
Array Operations
yq '.items | length' file.yaml
yq '.items[].name' file.yaml
yq '.items[] | select(.active == true)' file.yaml
yq '.users[] | select(.age > 18)' file.yaml
yq '.items | sort_by(.name)' file.yaml
yq '.items | sort_by(.date) | reverse' file.yaml
yq '.items | first' file.yaml
yq '.items | last' file.yaml
yq '.tags | unique' file.yaml
yq '[.items[] | select(.status == "active")]' file.yaml
Modifying YAML (In-Place)
yq -i '.metadata.name = "new-name"' file.yaml
yq -i '.spec.replicas = 3' deployment.yaml
yq -i '.metadata.labels.app = "myapp"' file.yaml
yq -i 'del(.spec.nodeSelector)' file.yaml
yq -i '.items += {"name": "new-item"}' file.yaml
yq -i '.items[0].status = "updated"' file.yaml
yq -i '(.items[] | select(.name == "foo")).status = "active"' file.yaml
Multi-Document YAML
yq -s '.metadata.name' multi-doc.yaml
yq 'select(document_index == 0)' multi-doc.yaml
yq eval-all '.' multi-doc.yaml
yq 'select(.kind == "Deployment")' k8s-resources.yaml
yq eval-all '. as $item ireduce ({}; . * $item)' file1.yaml file2.yaml
Object Operations
yq 'keys' file.yaml
yq '{name, version}' file.yaml
yq '{newName: .oldName, other: .other}' file.yaml
yq '. * {"updated": true}' file.yaml
yq eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' base.yaml override.yaml
yq eval-all '. as $item ireduce ({}; . *+ $item)' base.yaml override.yaml
Filtering and Conditions
yq 'select(.status == "active")' file.yaml
yq '.[] | select(.price < 100)' file.yaml
yq '.[] | select(.active and .verified)' file.yaml
yq '.[] | select(.age > 18 and .country == "US")' file.yaml
yq '.[] | select(.type == "admin" or .type == "moderator")' file.yaml
yq '.[] | select(has("email"))' file.yaml
yq 'select(.optional != null)' file.yaml
yq '.[] | select(.status != "deleted")' file.yaml
yq '.tags | contains(["important"])' file.yaml
String Operations
yq '"Hello, \(.name)"' file.yaml
yq '.port | tostring' file.yaml
yq '.[] | select(.email | contains("@gmail.com"))' file.yaml
yq '.[] | select(.name | test("^A"))' file.yaml
yq '.[] | select(.file | test("\\.yaml$"))' file.yaml
yq '.path | split("/")' file.yaml
yq '.tags | join(", ")' file.yaml
yq '.name | downcase' file.yaml
yq '.name | upcase' file.yaml
yq '.image | sub("v1.0"; "v2.0")' file.yaml
Format Conversion
yq -o=json '.' file.yaml
yq -p=json '.' file.json
yq -o=xml '.' file.yaml
yq -o=csv '.' file.yaml
yq -o=tsv '.' file.yaml
yq -o=props '.' file.yaml
yq -o=json -I=0 '.' file.yaml
Output Formatting
yq -o=yaml -I=0 '.' file.yaml
yq -I=4 '.' file.yaml
yq --no-colors '.' file.yaml
yq -r '.message' file.yaml
yq -n '.name = "example" | .version = "1.0"'
Real-World Examples
yq '.spec.template.spec.containers[].image' deployment.yaml
yq -i '.spec.template.spec.containers[0].image = "myapp:v2.0"' deployment.yaml
yq -i '(.metadata.labels.environment = "production")' deployment.yaml
yq '.jobs | keys' .github/workflows/ci.yml
yq -i '(.jobs.*.steps[] | select(.uses == "actions/checkout*")).uses = "actions/checkout@v5"' workflow.yml
yq '.services | keys' docker-compose.yml
yq -i '.services.web.image = "nginx:latest"' docker-compose.yml
yq -i '.replicaCount = 5 | .image.tag = "v2.0"' values.yaml
yq eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' base-config.yaml prod-config.yaml
yq '.spec.template.spec.containers[].env[].name' deployment.yaml
yq -n '.apiVersion = "v1" | .kind = "ConfigMap" | .metadata.name = "myconfig" |
.data.key1 = "value1" | .data.key2 = "value2"'
yq -i '(.. | select(has("port"))).port = 8080' config.yaml
Advanced Patterns
yq '.. | select(has("image")) | .image' file.yaml
yq '.items[] | . as $item | $item.name + " - " + ($item.price | tostring)' file.yaml
yq -i '(.spec.replicas) |= if . < 3 then 3 else . end' deployment.yaml
yq '[.items[].price] | add' file.yaml
yq 'group_by(.category)' items.yaml
yq '.items | flatten' file.yaml
yq '.optional // "default-value"' file.yaml
yq '.mayNotExist // empty' file.yaml
Best Practices
Query Construction
- Use
yq eval for complex expressions
- Test on small files first before modifying production configs
- Use
-i flag carefully (always backup first)
- Prefer specific paths over recursive descent for performance
Configuration Management
- Version control before in-place edits
- Use
yq eval-all for merging configurations
- Validate YAML after modifications
- Document complex transformations in scripts
Multi-Document YAML
- Use
select(document_index == N) for specific documents
- Use
eval-all when processing multiple documents together
- Split large multi-doc files with
-s for easier management
Performance
- Use targeted queries for large files (instead of
.. recursive descent)
- Use specific paths when possible
- Process files in parallel when operating on multiple files
- Stream large files if yq supports it
Common Patterns
Kubernetes Manifests
yq -i '.spec.template.spec.containers[0].image = "app:v2.0"' deployment.yaml
yq -i '.spec.replicas = 5' deployment.yaml
yq -i '.spec.template.spec.containers[0].env += [{"name": "DEBUG", "value": "true"}]' deployment.yaml
yq '.metadata.name' *.yaml
yq 'select(.kind == "Service")' *.yaml
yq '.metadata.namespace' *.yaml | sort -u
GitHub Actions Workflows
yq '.jobs | keys' .github/workflows/ci.yml
yq '.jobs.build.steps[].name' .github/workflows/ci.yml
yq -i '(.jobs.*.steps[] | select(.uses | test("actions/checkout"))).uses = "actions/checkout@v5"' workflow.yml
yq -i '.jobs.build.env.NODE_ENV = "production"' .github/workflows/ci.yml
yq '.on | keys' .github/workflows/*.yml
Configuration Files
yq eval-all 'select(fileIndex == 0) *+ select(fileIndex == 1)' base.yaml production.yaml
yq -i '.database.host = "prod-db.example.com"' config.yaml
yq -i '.allowed_hosts += ["example.com"]' config.yaml
yq -i 'del(.secrets)' config.yaml
Docker Compose
yq '.services | keys' docker-compose.yml
yq -i '.services.app.image = "myapp:latest"' docker-compose.yml
yq -i '.services.web.ports += ["8080:80"]' docker-compose.yml
yq -i '.services.app.environment.DEBUG = "true"' docker-compose.yml
Troubleshooting
Invalid YAML
yq '.' file.yaml
yq eval '.' file.yaml
Empty Results
yq '.' file.yaml
yq 'keys' file.yaml
yq 'type' file.yaml
yq '.. | select(tag == "!!str")' file.yaml
Unexpected In-Place Edits
yq '.field = "new-value"' file.yaml
cp file.yaml file.yaml.bak
yq -i '.field = "new-value"' file.yaml
git diff file.yaml
Multi-Document Issues
yq 'document_index' multi-doc.yaml | sort -u | wc -l
yq 'select(document_index == 0)' multi-doc.yaml
yq eval-all '.' multi-doc.yaml
Integration with Other Tools
kubectl get deployment myapp -o yaml | yq '.spec.replicas'
helm template myapp ./chart | yq 'select(.kind == "Service")'
git diff deployment.yaml | grep '^+' | yq -p yaml '.'
find . -name "*.yaml" -exec yq '.version' {} \;
yq -o=json '.' file.yaml | jq '.specific.field'
yq '.database.host = strenv(DB_HOST)' config.yaml
yq vs jq Comparison
| Operation | jq | yq |
|---|
| Read field | jq '.field' | yq '.field' |
| Update in-place | Not supported | yq -i '.field = "value"' |
| Format output | jq . | yq . |
| Multi-file merge | jq -s | yq eval-all |
| String interpolation | "\(.var)" | "\(.var)" |
| Convert to JSON | N/A | yq -o=json |
Quick Reference
Operators
.field - Access field
.[] - Iterate array/object
| - Pipe (chain operations)
, - Multiple outputs
// - Alternative operator (default value)
* - Merge objects (shallow)
*+ - Deep merge objects
Functions
keys, values - Object keys/values
length - Array/object/string length
select() - Filter
sort_by() - Sort
group_by() - Group
unique - Remove duplicates
has() - Check field existence
type - Get value type
add - Sum or concatenate
del() - Delete field
Flags
-i - In-place edit
-o - Output format (json, yaml, xml, csv, tsv, props)
-p - Input format (json, yaml, xml)
-I - Indent (default: 2)
-r - Raw output (no quotes)
-n - Null input (create from scratch)
-s - Split multi-document YAML
String Functions
split(), join() - String/array conversion
contains() - String/array contains
test() - Regex match
sub(), gsub() - String substitution
upcase, downcase - Case conversion
Installation
brew install yq
brew install yq
sudo snap install yq
yq --version
Important: This skill assumes yq v4+ (mikefarah/yq). The older Python-based yq has different syntax.
Resources