Diff tools
Line diffs are the wrong abstraction for structured files: reordering keys, moving a map entry, or re-wrapping a long string produces noise hunks that hide the one semantic change inside. Structural (semantic) diff tools parse first, then diff the tree — so “what actually changed” is the output, not “which lines changed”.
YAML / structured diff landscape
- diffyml (OSS) — Go, structural YAML diff with Kubernetes intelligence (matches resources by apiVersion+kind+name, rename detection by content similarity,
--ignore-api-versionfor api migrations), directory comparison, word-level inline highlighting, native CI annotations for GitHub/GitLab/Gitea,GIT_EXTERNAL_DIFFauto-detection, one dependency (yaml.v3) — minimal attack surface per its own pitch. - dyff (homeport/dyff) — the established YAML diff for k8s manifests; identifier-based rename detection (name must not change), 23 dependencies, no CI annotation output.
- jd (josephburnett/jd) — JSON(-ish) diff/patch with a formal algebra and
jdpatch format; two-way: diff → patch → apply round-trips. - deepdiff / dictdiffer (Python) — library-grade structural comparison; the standard answer inside Python tooling.
- Difftastic (wilfred/difftastic) — the general syntactic diff: parses 20+ languages via tree-sitter and diffs syntax trees; language-agnostic, so the go-to for code, less k8s-aware than diffyml/dyff.
- plain
diff/git diff— still right for prose and unknown formats; the baseline everything else is measured against.
The pattern across all of them: parse → tree-diff → render (move/rename detection is where implementations diverge — content-similarity vs identifier matching matters exactly when refactors rename things).
The merge/review side of diffing
- mergiraf (OSS) — syntax-aware merge driver (tree-sitter): resolves git merge/rebase conflicts language-aware, erring toward keeping conflict markers on suspicious resolutions; teach new languages declaratively. Not a viewer — it removes the conflicts a viewer would show.
- sem (OSS) — semantic version control CLI: entity-level diff, blame, graph, impact analysis over git history (Rust, 32+ languages via tree-sitter, “built for coding agents”).
- hunk (OSS) — review-first terminal diff viewer for agent-authored changesets (OpenTUI + Pierre diffs; 9.4k★).
- lumen (OSS) — git diff viewer + AI-generated commit messages + change summaries, all in the CLI (Rust).
The pattern repeats at a higher level: line diffs → structural diffs → entity diffs (sem) → diff-aware merging (mergiraf) → diff UX built for reviewing agents instead of humans (hunk/lumen) — the same readable→explainable shift ghuntley names.
Why it matters here
- Ansible review (todo: try diffyml on ansible) — playbooks and vars files are YAML where the semantic unit is a task/parameter, not a line; a structural diff in the mr/review path would surface “this task changed its module args” instead of context-free hunks. Extra angles: rename detection for renamed tasks/hosts, directory diff for vars/ trees, Gitea CI annotations map straight onto the work Gitea (spec:
oktawaveremote). Unknowns to test: Ansible-specific noise (anchors, multi-doc---separators, jinja in values) and whether the k8s-resource matching gets in the way of plain file pairs. - Golden repo — a structural-diff gate on YAML changes (compose files, CI workflows, manifests) is a reviewability rule in the same family as the Cilium CODEOWNERS gates.
- Kin to documentation-drift-audit: drift detection is a structural diff against the source of truth, named as a check.
Related: Golden repo · Infrastructure diagrams (the “diff the picture” angle) · legacy-tool-backtest habit (verify new diff tooling against real old diffs before trusting it) · Git recovery (mergiraf prevents the conflicts) · Git commit messages (lumen’s AI summaries feed the message habit) · Git hooks