Skip to content
Latchkey

yq: mikefarah (Go) vs kislyuk (Python) Differences

There are two different tools named yq: mikefarah/yq (Go, standalone) and kislyuk/yq (Python, a jq wrapper). They take different syntax.

The number one real-world yq failure in CI is a script written for one yq running on the other. Knowing which one a runner has, and how their syntax diverges, prevents hours of confusion.

What it does

mikefarah/yq is a self-contained Go binary with its own expression language and does not need jq. kislyuk/yq is a thin Python wrapper that converts YAML to JSON, pipes it through jq, and converts back, so it needs jq installed and uses jq syntax. Same command name, different engines.

How to tell them apart

Terminal
yq --version
# Go:     yq (https://github.com/mikefarah/yq/) version v4.x.x
# Python: yq 3.x.x
yq --help | head -1   # Python mentions jq; Go does not

Key differences

Aspectmikefarah (Go) vs kislyuk (Python)
In-place editGo: -i with = assignment; Python: -i is jq-arg, no = operator
Default outputGo: YAML; Python: JSON (use -y for YAML)
EngineGo: built-in; Python: shells out to jq
CommentsGo: preserved on edit; Python: dropped (round-trips via JSON)
Env varsGo: strenv()/env(); Python: jq env.VAR
MergeGo: * operator, eval-all; Python: jq -s slurp

In CI

Pin the implementation explicitly. Installing mikefarah/yq from its GitHub release binary avoids picking up the Python one from pip or a distro package. Add a guard step: yq --version | grep -q mikefarah || { echo "wrong yq"; exit 1; }.

Common errors in CI

Symptoms of running a Go-yq script on Python yq (or vice versa): "= " assignments do nothing, getting JSON when you expected YAML, comments disappearing, strenv()/eval/eval-all reported as unknown, or -i not editing in place. The fix is not to rewrite the expression but to install the yq the script targets, then verify with yq --version.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →