Skip to content

feat(builtins): add yaml command (non-standard, simplified yq) #567

@chaliy

Description

@chaliy

Summary

A new, non-standard builtin providing simple YAML operations, mirroring the json builtin (#561) semantics. YAML is the dominant config format (Kubernetes, CI/CD, Ansible, Docker Compose, GitHub Actions) — yet shell tooling for it is poor. yq exists but isn't standard and has competing incompatible versions.

Note: This is a bashkit-specific extension, not a standard command. Mirrors the json builtin API for consistency.

Proposed Syntax

yaml <subcommand> [args...] [< input]

Proposed Subcommands

Subcommand Description
yaml get .path Extract value at dot-notation path
yaml set .path value Set value at path
yaml delete .path Remove key at path
yaml merge file1 file2 Deep merge two YAML documents
yaml keys List top-level keys
yaml type .path Print type (string, number, mapping, sequence, bool, null)
yaml valid Validate YAML (exit 0 if valid, 1 if not)
yaml fmt Pretty-print / normalize YAML
yaml each .path Iterate sequence, output one element per line
yaml to-json Convert YAML to JSON
yaml from-json Convert JSON to YAML

Use Cases

# Read a value from config
yaml get .database.host < config.yaml
# localhost

# Set a value
yaml set .database.port 5432 < config.yaml > updated.yaml

# Merge configs (override takes precedence)
yaml merge defaults.yaml overrides.yaml > config.yaml

# Validate before deploying
if yaml valid < deployment.yaml; then
    kubectl apply -f deployment.yaml
fi

# Iterate over list items
yaml each .services < docker-compose.yaml
# web
# db
# redis

# Extract nested value from GitHub Actions
yaml get .jobs.build.runs-on < .github/workflows/ci.yaml
# ubuntu-latest

# Convert between formats
yaml to-json < config.yaml | json get .version
cat config.json | yaml from-json > config.yaml

# Pipeline: modify and write back
cat deployment.yaml \
  | yaml set .spec.replicas 3 \
  | yaml set .spec.template.spec.containers[0].image "app:v2" \
  > deployment-updated.yaml

# Multi-document support (--- separator)
yaml get .metadata.name --document 1 < multi.yaml

Proposed Flags

Flag Description
--document N / -d N Select Nth document in multi-document YAML (0-indexed, default 0)
--all-documents Apply operation to all documents
--in-place FILE / -i FILE Modify file in place

Path Notation

Same dot notation as json builtin for consistency:

  • .foo.bar — nested key access
  • .items[0] — sequence index
  • .items[-1] — last element
  • .items[*] — all elements
  • . — root document

YAML-Specific Considerations

Feature Handling
Multi-document (---) --document N to select, default is first
Anchors & aliases (&/*) Resolved on read, not preserved on write
Comments Preserved where possible (best-effort)
Quoted strings Round-trip preserves quoting style
Flow vs block style yaml fmt normalizes to block style
Tags (!!str, !!int) Supported but rarely needed
null vs missing yaml get returns empty string + exit 1 for missing; literal "null" for explicit null

Implementation Notes

  • Use serde_yaml or yaml-rust2 crate for parsing/serialization
  • Path resolution logic shared with json builtin (extract into common module)
  • yaml to-json and yaml from-json enable interop with jq for complex queries
  • Multi-document YAML is common in Kubernetes — must handle --- separators
  • Comment preservation is a differentiator vs yq — use a parser that tracks comments if possible
  • Exit codes match json builtin: 0 = success, 1 = path not found or invalid YAML
  • YAML is a superset of JSON, so yaml can also parse JSON input

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions